aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-05-02 04:13:03 -0700
committerLinux Build Service Account <lnxbuild@localhost>2019-05-02 04:13:03 -0700
commitfb13b6a373d9e92e8b2adeeb2dcf49e6d1065cef (patch)
tree5d9af4c49774c5ccc63ea9164964bfe38e5a372e
parentefdc25857558d8d6011701a3f0056c29685fb0ee (diff)
parented2cce8e3aaebb68ee7b0db32dd679f75b14d622 (diff)
Merge ed2cce8e3aaebb68ee7b0db32dd679f75b14d622 on remote branchLA.UM.7.8.r3-01400-SDM710.0
Change-Id: Ic9550ddbaada69bb201a9d09d2b60033d5adc596
-rw-r--r--Documentation/devicetree/bindings/arm/msm/clock-controller.txt1
-rw-r--r--Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt4
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt3
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt3
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-camera-flash.txt18
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt22
-rw-r--r--Documentation/devicetree/bindings/qseecom/qseecom.txt3
-rw-r--r--arch/arm/configs/msm8909w-perf_defconfig1
-rw-r--r--arch/arm/configs/msm8937_defconfig1
-rw-r--r--arch/arm/configs/msm8937go-perf_defconfig5
-rw-r--r--arch/arm/configs/msm8937go_defconfig6
-rw-r--r--arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi35
-rw-r--r--arch/arm64/boot/dts/qcom/msm8937-camera-sensor-cdp.dtsi292
-rw-r--r--arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi1
-rw-r--r--arch/arm64/boot/dts/qcom/pm8937.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/qcs605.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/qm215-camera-sensor-qrd.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi75
-rw-r--r--arch/arm64/boot/dts/qcom/qm215-qrd.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/qm215.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi7
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-audio.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts6
-rw-r--r--arch/arm64/configs/msm8937-perf_defconfig1
-rw-r--r--arch/arm64/configs/sdm670-perf_defconfig1
-rw-r--r--arch/arm64/configs/sdm670_defconfig1
-rw-r--r--arch/arm64/kernel/perf_event.c4
-rw-r--r--arch/arm64/mm/dma-mapping.c24
-rw-r--r--drivers/android/binder_alloc.c18
-rw-r--r--drivers/char/adsprpc.c25
-rw-r--r--drivers/char/diag/diag_dci.c32
-rw-r--r--drivers/char/diag/diag_dci.h3
-rw-r--r--drivers/char/diag/diag_usb.c6
-rw-r--r--drivers/char/diag/diagchar.h12
-rw-r--r--drivers/char/diag/diagchar_core.c136
-rw-r--r--drivers/char/diag/diagfwd.c4
-rw-r--r--drivers/char/diag/diagfwd_cntl.c7
-rw-r--r--drivers/char/diag/diagmem.c4
-rw-r--r--drivers/clk/msm/clock-gcc-8952.c42
-rw-r--r--drivers/cpufreq/cpufreq_times.c6
-rw-r--r--drivers/crypto/msm/ice.c4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.c57
-rw-r--r--drivers/gpu/drm/msm/dp/dp_catalog.h4
-rw-r--r--drivers/gpu/drm/msm/dp/dp_ctrl.c30
-rw-r--r--drivers/gpu/drm/msm/dp/dp_debug.c17
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c11
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_clk.h19
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c42
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_display.c64
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_panel.c29
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_panel.h6
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_phy.c7
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c58
-rw-r--r--drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c16
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_color_processing.c38
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c47
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h6
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c37
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c36
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c40
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.c2
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_dsc.c4
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c11
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.h1
-rw-r--r--drivers/gpu/drm/msm/sde_hdcp_1x.c4
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c2
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.c10
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.c6
-rw-r--r--drivers/hwtracing/coresight/coresight-ost.c11
-rw-r--r--drivers/iommu/dma-iommu.c5
-rw-r--r--drivers/iommu/dma-mapping-fast.c14
-rw-r--r--drivers/iommu/iommu-debug.c10
-rw-r--r--drivers/leds/leds-qpnp-vibrator.c12
-rw-r--r--drivers/leds/leds-qti-tri-led.c33
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c5
-rw-r--r--drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c10
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_context_utils.c12
-rw-r--r--drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c18
-rw-r--r--drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c5
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c12
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c25
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c17
-rw-r--r--drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c24
-rw-r--r--drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c10
-rw-r--r--drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c34
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c54
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h8
-rw-r--r--drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c8
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c43
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c39
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c82
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c164
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c37
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h4
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c66
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c104
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h5
-rw-r--r--drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c4
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c96
-rw-r--r--drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h7
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c14
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h6
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/qm215_gpio_flash.c264
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c30
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context.c9
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c21
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h44
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_core/cam_node.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c18
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c21
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h537
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h769
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c32
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/hfi.c11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c9
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c88
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c8
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c749
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c890
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c156
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h17
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h28
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c61
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h (renamed from drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.h)180
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h369
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c23
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c284
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h23
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c59
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c27
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h26
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h22
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c102
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c93
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c52
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c52
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h336
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h8
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h (renamed from drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h)307
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h1131
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c16
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c18
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c1232
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h143
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c267
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h19
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c15
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c163
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c638
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h94
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c226
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c12
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile2
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c34
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c67
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.h8
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c750
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h29
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c6
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c103
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c35
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c166
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c3
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c57
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c142
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c28
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c426
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h11
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c17
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h7
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c122
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c97
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h4
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c28
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c14
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c155
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c19
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c160
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h5
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c20
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/Makefile1
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c135
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.h (renamed from drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_log.h)22
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c121
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h10
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c102
-rw-r--r--drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h12
-rw-r--r--drivers/media/platform/msm/vidc/hfi_response_handler.c65
-rw-r--r--drivers/media/platform/msm/vidc/vidc_hfi_api.h5
-rw-r--r--drivers/media/platform/msm/vidc_3x/hfi_response_handler.c65
-rw-r--r--drivers/media/platform/msm/vidc_3x/msm_smem.c5
-rw-r--r--drivers/media/platform/msm/vidc_3x/msm_vidc.c7
-rw-r--r--drivers/media/platform/msm/vidc_3x/msm_vidc_common.c4
-rw-r--r--drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h6
-rw-r--r--drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h5
-rw-r--r--drivers/misc/hdcp_qseecom.c28
-rw-r--r--drivers/misc/qseecom.c267
-rw-r--r--drivers/mmc/core/core.c8
-rw-r--r--drivers/mmc/core/sd.c18
-rw-r--r--drivers/mmc/host/cmdq_hci.c12
-rw-r--r--drivers/net/ppp/pppolac.c7
-rw-r--r--drivers/perf/arm_pmu.c14
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_intf.c21
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_intf.c19
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c4
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c9
-rw-r--r--drivers/platform/msm/sps/sps.c30
-rw-r--r--drivers/platform/msm/sps/sps_bam.c27
-rw-r--r--drivers/platform/msm/sps/sps_dma.c11
-rw-r--r--drivers/platform/msm/sps/sps_mem.c10
-rw-r--r--drivers/platform/msm/sps/sps_rm.c14
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c8
-rw-r--r--drivers/power/supply/qcom/qpnp-smb5.c2
-rw-r--r--drivers/power/supply/qcom/qpnp-smbcharger.c39
-rw-r--r--drivers/power/supply/qcom/smb-lib.c1
-rw-r--r--drivers/power/supply/qcom/smb1360-charger-fg.c84
-rw-r--r--drivers/pwm/core.c20
-rw-r--r--drivers/pwm/pwm-qti-lpg.c112
-rw-r--r--drivers/pwm/sysfs.c6
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c36
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c19
-rw-r--r--drivers/scsi/ufs/ufs.h1
-rw-r--r--drivers/scsi/ufs/ufs_quirks.c4
-rw-r--r--drivers/scsi/ufs/ufs_quirks.h9
-rw-r--r--drivers/scsi/ufs/ufshcd.c90
-rw-r--r--drivers/scsi/ufs/ufshcd.h3
-rw-r--r--drivers/slimbus/slim-msm-ngd.c20
-rw-r--r--drivers/soc/qcom/glink_spi_xprt.c33
-rw-r--r--drivers/soc/qcom/icnss.c49
-rw-r--r--drivers/soc/qcom/pil-q6v5.c6
-rw-r--r--drivers/soc/qcom/socinfo.c8
-rw-r--r--drivers/soc/qcom/subsys-pil-bg.c4
-rw-r--r--drivers/spmi/spmi-pmic-arb-debug.c14
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c6
-rw-r--r--drivers/usb/dwc3/ep0.c2
-rw-r--r--drivers/video/fbdev/msm/mdp3.c13
-rw-r--r--drivers/video/fbdev/msm/mdp3.h3
-rw-r--r--drivers/video/fbdev/msm/mdp3_ctrl.c31
-rw-r--r--drivers/video/fbdev/msm/mdp3_ctrl.h7
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c7
-rw-r--r--fs/proc/inode.c9
-rw-r--r--fs/proc/internal.h3
-rw-r--r--fs/proc/root.c52
-rw-r--r--include/dt-bindings/clock/msm-clocks-hwio-8952.h5
-rw-r--r--include/linux/diagchar.h1
-rw-r--r--include/linux/hdcp_qseecom.h3
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/perf_event.h14
-rw-r--r--include/linux/pwm.h79
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/soc/qcom/icnss.h3
-rw-r--r--include/soc/qcom/socinfo.h8
-rw-r--r--include/uapi/media/cam_defs.h3
-rw-r--r--include/uapi/media/cam_isp.h39
-rw-r--r--include/uapi/media/cam_isp_ife.h6
-rw-r--r--include/uapi/media/cam_req_mgr.h2
-rw-r--r--include/uapi/scsi/ufs/ufs.h4
-rw-r--r--kernel/cpu.c2
-rw-r--r--kernel/cpuset.c18
-rw-r--r--kernel/events/core.c207
-rw-r--r--kernel/sched/core.c4
-rw-r--r--lib/qmi_encdec.c6
-rw-r--r--mm/memory.c2
-rw-r--r--net/wireless/db.txt308
-rwxr-xr-xscripts/checkpatch.pl2
-rwxr-xr-xscripts/gcc-wrapper.py10
313 files changed, 13979 insertions, 3464 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
index 75f901bcde9c..fd53d9f1e127 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
@@ -30,6 +30,7 @@ Required properties:
"qcom,gcc-8917"
"qcom,gcc-8940"
"qcom,gcc-8920"
+ "qcom,gcc-qm215"
"qcom,gcc-spm-8952"
"qcom,gcc-spm-8937"
"qcom,rpmcc-8909"
diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
index 0d1a67af32a2..99f8c4c62593 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
@@ -184,6 +184,9 @@ Optional properties:
255 = default value.
- qcom,mdss-brightness-max-level: Specifies the max brightness level supported.
255 = default value.
+- qcom,bl-update-flag: A string that specifies controls for backlight update of the panel.
+ "delay_until_first_frame" = Delay backlight update of the panel
+ until the first frame is received from the HW.
- qcom,mdss-dsi-interleave-mode: Specifies interleave mode.
0 = default value.
- qcom,mdss-dsi-panel-type: Specifies the panel operating mode.
@@ -600,6 +603,7 @@ Example:
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = < 15>;
qcom,mdss-brightness-max-level = <255>;
+ qcom,bl-update-flag = "delay_until_first_frame";
qcom,mdss-dsi-interleave-mode = <0>;
qcom,mdss-dsi-panel-type = "dsi_video_mode";
qcom,mdss-dsi-te-check-enable;
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt b/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
index 29ea987e306d..8aa0ec530a3a 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
@@ -15,7 +15,8 @@ First Level Node - CAM IFE CSID device
- compatible
Usage: required
Value type: <string>
- Definition: Should be "qcom,csid170" or "qcom,csid-lite170".
+ Definition: Should be "qcom,csid170", "qcom,csid175", "qcom,csid175_200",
+ "qcom,csid-lite170" or "qcom,csid-lite175".
- cell-index
Usage: required
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt b/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
index f156cc67b2aa..9750d63794d1 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
@@ -17,7 +17,8 @@ Required properties:
Usage: required
Value type: <string>
Definition: Should specify the compatibility string for matching the
- driver. e.g. "qcom,vfe170", "qcom,vfe-lite170".
+ driver. e.g. "qcom,vfe175", "qcom,vfe170", "qcom,vfe175_130",
+ "qcom,vfe-lite175", "qcom,vfe-lite175_130", "qcom,vfe-lite170".
- cell-index
Usage: required
diff --git a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
index d24314ae196d..970dae26dc57 100644
--- a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
@@ -124,3 +124,21 @@ led_flash_rear: qcom,camera-flash@0 {
qcom,max-current = <1500>;
qcom,max-duration = <1200>;
};
+
+
+Example:
+
+flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,qm215-gpio-flash";
+ qcom,flash-type = <2>;
+ gpios = <&tlmm 34 0>;
+ <&tlmm 33 0>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-flash-en = <0>;
+ qcom,gpio-flash-now = <1>;
+ qcom,gpio-req-tbl-label = "CAM_FLASH",
+ "CAM_TORCH";
+ status = "ok";
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
index 8b2234e0c9fe..326f279623eb 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1360-charger-fg.txt
@@ -13,12 +13,15 @@ Required Properties:
Optional Properties:
-- interrupts This indicates the IRQ number of the GPIO
- connected to the STAT pin.
+- interrupts This indicates the IRQ numbers of the GPIOs
+ connected to the STAT and usb-id pins.
+- interrupt-names The irq names should be smb1360_stat_irq and
+ smb1360_usb_id_irq.The stat irq is mandatory
+ and usb_id irq is optional.
- pinctrl-names: The state name of the pin configuration. Only
support: "default".
-- pinctrl-0: The phandle of the pin configuration node in
- pinctrl for smb_int_pin.
+- pinctrl-0: The phandles of the pin configuration node in
+ pinctrl for smb_int_pin and usb-id pin.
For details of pinctrl properties, please refer to:
"Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt"
- qcom,float-voltage-mv Float Voltage in mV - the maximum voltage up to which
@@ -177,6 +180,8 @@ Optional Properties:
Please go through the documentation for PMIC gpio
configuration details:
Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+- qcom,usb-id-gpio GPIO for usb-id detection.This property is mandatory
+ if usb-id irq is specified.
- qcom,parallel-charging-enabled: A bool property which enables SMB1360 to
operate in the parallel mode. SMB1360 acts
as the primary charger.
@@ -192,9 +197,13 @@ Example:
compatible = "qcom,smb1360-chg-fg";
reg = <0x1b>;
interrupt-parent = <&spmi_bus>;
- interrupts = <0x00 0xcd 0>;
+ interrupts = <0x00 0xcd 0>,
+ <0 0xc3 0 3>;
+ interrupt-names = "smb1360_stat_irq",
+ "smb1360_usb_id_irq";
pinctrl-names = "default";
- pinctrl-0 = <&smb_int_default>;
+ pinctrl-0 = <&smb_int_default>,
+ <&usb_id_default>;
/* battery-profile selection properties */
qcom,batt-profile-select;
@@ -242,5 +251,6 @@ Example:
qcom,otg-fet-present;
qcom,otg-fet-enable-gpio = <&pm8916_gpios 3 0>;
+ qcom,usb-id-gpio = <&pm8916_gpios 4 0>;
};
};
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
index 8fbf8e2fc8cc..83a2e8a6ae6a 100644
--- a/Documentation/devicetree/bindings/qseecom/qseecom.txt
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -27,6 +27,7 @@ Optional properties:
- qcom,qsee-reentrancy-support: indicates the qsee reentrancy phase supported by the target
- qcom,commonlib64-loaded-by-uefi: indicates commonlib64 is loaded by uefi already
- qcom,fde-key-size: indicates which FDE key size is used in device.
+ - qcom,enable-key-wrap-in-ks: enables wrapping of ICE key with KS key.
Example:
qcom,qseecom@fe806000 {
@@ -40,6 +41,7 @@ Example:
qcom,hlos-ce-hw-instance = <1 2>;
qcom,qsee-ce-hw-instance = <0>;
qcom,support-fde;
+ qcom,enable-key-wrap-in-ks;
qcom,support-pfe;
qcom,msm_bus,name = "qseecom-noc";
qcom,msm_bus,num_cases = <4>;
@@ -64,6 +66,7 @@ Example: The following dts setup is the same as the example above.
reg = <0x7f00000 0x500000>;
reg-names = "secapp-region";
qcom,support-fde;
+ qcom,enable-key-wrap-in-ks;
qcom,full-disk-encrypt-info = <0 1 2>, <0 2 2>;
qcom,support-pfe;
qcom,per-file-encrypt-info = <0 1 0>, <0 2 0>;
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 084e48707f58..8a5099dc084a 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -329,7 +329,6 @@ CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_SPI_PANEL=y
CONFIG_FB_MSM_MDSS_MDP3=y
-CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig
index 5eaa0eb983a6..b65fbac85719 100644
--- a/arch/arm/configs/msm8937_defconfig
+++ b/arch/arm/configs/msm8937_defconfig
@@ -677,7 +677,6 @@ CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_LIST=y
diff --git a/arch/arm/configs/msm8937go-perf_defconfig b/arch/arm/configs/msm8937go-perf_defconfig
index 3a388860b041..6be2749963db 100644
--- a/arch/arm/configs/msm8937go-perf_defconfig
+++ b/arch/arm/configs/msm8937go-perf_defconfig
@@ -107,10 +107,12 @@ CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -127,7 +129,6 @@ CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -174,6 +175,7 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
@@ -207,6 +209,7 @@ CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
CONFIG_L2TP=y
CONFIG_L2TP_DEBUGFS=y
CONFIG_L2TP_V3=y
diff --git a/arch/arm/configs/msm8937go_defconfig b/arch/arm/configs/msm8937go_defconfig
index 0f7c8231c30a..b76c4183a762 100644
--- a/arch/arm/configs/msm8937go_defconfig
+++ b/arch/arm/configs/msm8937go_defconfig
@@ -110,10 +110,12 @@ CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -130,7 +132,6 @@ CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -177,6 +178,7 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
@@ -210,6 +212,7 @@ CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
CONFIG_L2TP=y
CONFIG_L2TP_DEBUGFS=y
CONFIG_L2TP_V3=y
@@ -671,7 +674,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHED_STACK_END_CHECK=y
# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_LIST=y
diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
index 13e5187ed6b5..dcbfe47cec8f 100644
--- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -509,7 +509,7 @@
};
};
- qcom,msm-dai-tdm-quat-rx {
+ msm_dai_tdm_quat_rx: qcom,msm-dai-tdm-quat-rx {
compatible = "qcom,msm-dai-tdm";
qcom,msm-cpudai-tdm-group-id = <37168>;
qcom,msm-cpudai-tdm-group-num-ports = <1>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
index 47a925e4c34a..96a282673b56 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
@@ -329,16 +329,43 @@
/* CPR controlled regulator */
&soc {
+ /delete-node/ regulator@1942130;
mem_acc_vreg_corner: regulator@1942130 {
compatible = "qcom,mem-acc-regulator";
- reg = <0x1942130 0x4>;
- reg-names = "acc-sel-l1";
regulator-name = "mem_acc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,acc-sel-l1-bit-pos = <0>;
- qcom,corner-acc-map = <0 1 1>;
+ qcom,acc-reg-addr-list =
+ <0x1942130 0x1942120>;
+
+ qcom,acc-init-reg-config = <1 0x1>, <2 0x0>;
+ qcom,num-acc-corners = <3>;
+ qcom,boot-acc-corner = <2>;
+
+ qcom,corner1-reg-config =
+ /* SVS => SVS */
+ <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>,
+ /* SVS => NOM */
+ < 1 0x0 >, < 2 0x09240000>, < 1 0x1 >,
+ /* SVS => TURBO */
+ < 1 0x1 >, < 2 0x0>, < (-1) (-1) >;
+
+ qcom,corner2-reg-config =
+ /* NOM => SVS */
+ < 1 0x0 >, < 2 0x09240000>, < 2 0x0 >,
+ /* NOM => NOM */
+ <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>,
+ /* NOM => TURBO */
+ < 1 0x1 >, < 2 0x08200000>, < 2 0x0 >;
+
+ qcom,corner3-reg-config =
+ /* TURBO => SVS */
+ < 1 0x0 >, < 2 0x0>, < (-1) (-1) >,
+ /* TURBO => NOM */
+ < 1 0x1 >, < 2 0x08200000>, < 2 0x09240000 >,
+ /* TURBO => TURBO */
+ <(-1) (-1)>, <(-1) (-1)>, <(-1) (-1)>;
};
apc_vreg_corner: regulator@b018000 {
diff --git a/arch/arm64/boot/dts/qcom/msm8937-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-camera-sensor-cdp.dtsi
new file mode 100644
index 000000000000..8f174fbda46e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-camera-sensor-cdp.dtsi
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2850000>;
+ qcom,cam-vreg-max-voltage = <2850000>;
+ qcom,cam-vreg-op-mode = <80000>;
+ };
+
+ actuator1: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2850000>;
+ qcom,cam-vreg-max-voltage = <2850000>;
+ qcom,cam-vreg-op-mode = <80000>;
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ compatible = "qcom,eeprom";
+ qcom,cci-master = <0>;
+ reg = <0x0>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vaf";
+ qcom,cam-vreg-min-voltage = <0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_reset
+ &cam_sensor_rear_standby
+ &cam_sensor_rear_vdig>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep
+ &cam_sensor_rear_reset_sleep
+ &cam_sensor_rear_standby_sleep
+ &cam_sensor_rear_vdig_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 36 0>,
+ <&tlmm 35 0>,
+ <&tlmm 62 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0",
+ "CAM_VDIG";
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ qcom,eeprom-name = "sunny_8865";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x6c>;
+ qcom,cci-master = <0>;
+ qcom,num-blocks = <8>;
+
+ qcom,page0 = <1 0x0100 2 0x01 1 1>;
+ qcom,poll0 = <0 0x0 2 0x0 1 0>;
+ qcom,mem0 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page1 = <1 0x5002 2 0x00 1 0>;
+ qcom,poll1 = <0 0x0 2 0x0 1 0>;
+ qcom,mem1 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
+ qcom,poll2 = <0 0x0 2 0x0 1 0>;
+ qcom,mem2 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page3 = <1 0x3d88 2 0x70 1 0>;
+ qcom,poll3 = <0 0x0 2 0x0 1 0>;
+ qcom,mem3 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page4 = <1 0x3d89 2 0x10 1 0>;
+ qcom,poll4 = <0 0x0 2 0x0 1 0>;
+ qcom,mem4 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page5 = <1 0x3d8a 2 0x70 1 0>;
+ qcom,poll5 = <0 0x0 2 0x0 1 0>;
+ qcom,mem5 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page6 = <1 0x3d8b 2 0xf4 1 0>;
+ qcom,poll6 = <0 0x0 2 0x0 1 0>;
+ qcom,mem6 = <0 0x0 2 0x0 1 0>;
+
+ qcom,page7 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll7 = <0 0x0 2 0x0 1 1>;
+ qcom,mem7 = <1536 0x7010 2 0 1 0>;
+
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ qcom,cam-power-seq-type = "sensor_vreg", "sensor_vreg",
+ "sensor_vreg",
+ "sensor_gpio", "sensor_gpio" , "sensor_clk";
+ qcom,cam-power-seq-val = "cam_vdig", "cam_vana", "cam_vio",
+ "sensor_gpio_reset", "sensor_gpio_standby",
+ "sensor_cam_mclk";
+ qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>;
+ qcom,cam-power-seq-delay = <1 1 1 30 30 5>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom0>;
+ qcom,actuator-src = <&actuator0>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vaf";
+ qcom,cam-vreg-min-voltage = <0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_reset
+ &cam_sensor_rear_standby
+ &cam_sensor_rear_vdig>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep
+ &cam_sensor_rear_reset_sleep
+ &cam_sensor_rear_standby_sleep
+ &cam_sensor_rear_vdig_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 36 0>,
+ <&tlmm 35 0>,
+ <&tlmm 62 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-vdig = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0",
+ "CAM_VDIG";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_default
+ &cam_sensor_front_default>;
+ pinctrl-1 = <&cam_sensor_mclk1_sleep
+ &cam_sensor_front_sleep>;
+ gpios = <&tlmm 27 0>,
+ <&tlmm 38 0>,
+ <&tlmm 50 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_STANDBY1";
+ qcom,sensor-position = <0x100>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <1>;
+ clocks = <&clock_gcc clk_mclk1_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk1_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,eeprom-src = <&eeprom1>;
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi
index 46e480ed7f11..c4100ab27c9d 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-cdp.dtsi
@@ -12,6 +12,7 @@
*/
#include <dt-bindings/clock/msm-clocks-8952.h>
+#include "msm8937-camera-sensor-cdp.dtsi"
&soc {
gpio_keys {
diff --git a/arch/arm64/boot/dts/qcom/pm8937.dtsi b/arch/arm64/boot/dts/qcom/pm8937.dtsi
index 18a3270c3a0d..b97cec6b7871 100644
--- a/arch/arm64/boot/dts/qcom/pm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8937.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -284,6 +284,7 @@
qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1800>;
qcom,adc_tm-vadc = <&pm8937_vadc>;
+ #thermal-sensor-cells = <1>;
chan@36 {
label = "pa_therm0";
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 7801775c7e3b..c437ef1dbfac 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -59,7 +59,7 @@
};
&secure_display_memory {
- status = "disabled";
+ size = <0 0xa000000>;
};
&sp_mem {
diff --git a/arch/arm64/boot/dts/qcom/qm215-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/qm215-camera-sensor-qrd.dtsi
index f7c6814a0333..ab5557216974 100644
--- a/arch/arm64/boot/dts/qcom/qm215-camera-sensor-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/qm215-camera-sensor-qrd.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -97,6 +97,21 @@
qcom,clock-rates = <19200000 0>;
};
+ flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,qm215-gpio-flash";
+ qcom,flash-type = <2>;
+ gpios = <&tlmm 34 0>,
+ <&tlmm 33 0>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-flash-en = <0>;
+ qcom,gpio-flash-now = <1>;
+ qcom,gpio-req-tbl-label = "CAM_FLASH",
+ "CAM_TORCH";
+ status = "ok";
+ };
+
qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
@@ -104,6 +119,7 @@
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
+ qcom,led-flash-src = <&flash0>;
qcom,actuator-src = <&actuator0>;
qcom,eeprom-src = <&eeprom0>;
cam_vana-supply = <&pm8916_l16>;
diff --git a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
index 0885da1cb2e9..06aadee8c948 100644
--- a/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
+++ b/arch/arm64/boot/dts/qcom/qm215-qrd-smb1360.dtsi
@@ -11,3 +11,78 @@
*/
#include "qm215-qrd.dtsi"
+
+&pm8916_chg{
+ qcom,use-external-charger;
+};
+
+&pm8916_bms{
+ qcom,disable-bms;
+};
+
+&tlmm {
+ /* SMB interrupt pin */
+ smb_int_pin {
+ smb_int_default: smb_int_default {
+ mux {
+ pins = "gpio13";
+ function ="gpio";
+ };
+ config {
+ pins = "gpio13";
+ bias-pull-up; /* PULL UP*/
+ input-enable;
+ };
+ };
+ };
+};
+
+&pm8916_gpios {
+ usb_id {
+ usb_id_default: usb_id_default {
+ pins = "gpio4";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ power-source = <0>;
+ };
+ };
+};
+
+&i2c_2 {
+ status ="ok";
+ smb1360_otg_supply: smb1360-chg-fg@14 {
+ compatible = "qcom,smb1360-chg-fg";
+ reg = <0x14>;
+ interrupts-extended = <&tlmm 13 8>,
+ <&spmi_bus 0 0xc3 0 3>;
+ interrupt-names = "smb1360_stat_irq",
+ "smb1360_usb_id_irq";
+ pinctrl-names = "default";
+ pinctrl-0 = <&smb_int_default>,
+ <&usb_id_default>;
+ qcom,empty-soc-disabled;
+ qcom,chg-inhibit-disabled;
+ qcom,float-voltage-mv = <4400>;
+ qcom,iterm-ma = <100>;
+ qcom,recharge-thresh-mv = <100>;
+ qcom,thermal-mitigation = <1500 700 600 0>;
+ qcom,fg-batt-capacity-mah = <2800>;
+ qcom,fg-cutoff-voltage-mv = <3400>;
+ qcom,fg-iterm-ma = <130>;
+ qcom,fg-delta-soc = <1>;
+ qcom,usb-id-gpio = <&pm8916_gpios 4 0>;
+ qcom,soft-jeita-supported;
+ qcom,warm-bat-decidegc = <450>;
+ qcom,cool-bat-decidegc = <150>;
+ qcom,warm-bat-mv = <4200>;
+ qcom,cool-bat-mv = <4200>;
+ qcom,warm-bat-ma = <1000>;
+ qcom,cool-bat-ma = <1000>;
+ status= "okay";
+ };
+};
+
+&usb_otg {
+ extcon = <&smb1360_otg_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qm215-qrd.dtsi b/arch/arm64/boot/dts/qcom/qm215-qrd.dtsi
index 058edaa9ddd7..fa29c8ed9ad2 100644
--- a/arch/arm64/boot/dts/qcom/qm215-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/qm215-qrd.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,8 @@
&blsp1_uart2 {
status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
};
#include <dt-bindings/clock/msm-clocks-8952.h>
diff --git a/arch/arm64/boot/dts/qcom/qm215.dtsi b/arch/arm64/boot/dts/qcom/qm215.dtsi
index 597ce27b1a2f..810932ae7d8c 100644
--- a/arch/arm64/boot/dts/qcom/qm215.dtsi
+++ b/arch/arm64/boot/dts/qcom/qm215.dtsi
@@ -56,6 +56,10 @@
};
};
+&clock_gcc {
+ compatible = "qcom,gcc-qm215";
+};
+
/* GPU overrides */
&msm_gpu {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
index 78047bd22f9e..fd0aa8a39a33 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-qrd.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -194,6 +194,11 @@
};
&cam_cci {
+ qcom,cam-res-mgr {
+ compatible = "qcom,cam-res-mgr";
+ status = "ok";
+ };
+
actuator_rear: qcom,actuator@0 {
cell-index = <0>;
reg = <0x0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index bf50ce61cec7..b967af9d2ab7 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1621,6 +1621,7 @@
qcom,xprt-linkid = <1>;
qcom,xprt-version = <1>;
qcom,fragmented-data;
+ qcom,dynamic-wakeup-source;
};
qcom,ipc_router_cdsp_xprt {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
index b5c1ded20fc7..a64467c3ef68 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -67,7 +67,8 @@
<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>,
<&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>,
<&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>,
- <&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>;
+ <&dai_quat_tdm_rx_0>, <&dai_quat_tdm_tx_0>,
+ <&dai_quat_tdm_rx_1>;
asoc-cpu-names = "msm-dai-q6-hdmi.8", "msm-dai-q6-dp.24608",
"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
@@ -89,7 +90,8 @@
"msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865",
"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
- "msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913";
+ "msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913",
+ "msm-dai-q6-tdm.36914";
};
};
@@ -99,3 +101,13 @@
elemental-addr = [ff ff ff fe 17 02];
};
};
+
+&msm_dai_tdm_quat_rx {
+ qcom,msm-cpudai-tdm-group-num-ports = <2>;
+ qcom,msm-cpudai-tdm-group-port-id = <36912 36914>;
+ dai_quat_tdm_rx_1: qcom,msm-dai-q6-tdm-quat-rx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36914>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts
index f7b9ec1d9207..5df6dc42f122 100644
--- a/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts
@@ -26,8 +26,10 @@
qcom,msm-id = <245 0>,
<258 0>,
<275 0>,
- <300 0>;
- qcom,board-id = <8 0x10f>;
+ <300 0>,
+ <301 0>;
+ qcom,board-id = <8 0x10f>,
+ <8 0x117>;
qcom,pmic-id = <0x0001001b 0x0 0x0 0x0>,
<0x0001011b 0x0 0x0 0x0>;
};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 2a801e9a4620..467dc4fbb133 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -640,7 +640,6 @@ CONFIG_CORESIGHT_QCOM_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_TPDA=y
CONFIG_CORESIGHT_TPDM=y
-CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_PFK=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 3bc57d26d6b3..5c305104dd12 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -232,6 +232,7 @@ CONFIG_NET_ACT_SKBEDIT=y
CONFIG_RMNET_DATA=y
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_SOCKEV_NLMCAST=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 707a7d79fa51..35539f0aaba2 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -240,6 +240,7 @@ CONFIG_DNS_RESOLVER=y
CONFIG_RMNET_DATA=y
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_SOCKEV_NLMCAST=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index e0b731e70f66..c845bf57ccb3 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -779,8 +779,8 @@ static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
- /* Ignore if we don't have an event or if it's a zombie event */
- if (!event || event->state == PERF_EVENT_STATE_ZOMBIE)
+ /* Ignore if we don't have an event */
+ if (!event || event->state != PERF_EVENT_STATE_ACTIVE)
continue;
/*
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 42dde2d64166..c38c08ee630d 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -1256,6 +1256,9 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
size_t array_size = count * sizeof(struct page *);
int i = 0;
bool is_coherent = is_dma_coherent(dev, attrs);
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ unsigned int alloc_sizes = mapping->domain->pgsize_bitmap;
+ unsigned long order_mask;
if (array_size <= PAGE_SIZE)
pages = kzalloc(array_size, gfp);
@@ -1284,13 +1287,26 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
* IOMMU can map any pages, so himem can also be used here
*/
gfp |= __GFP_NOWARN | __GFP_HIGHMEM;
+ order_mask = alloc_sizes >> PAGE_SHIFT;
+ order_mask &= (2U << MAX_ORDER) - 1;
+ if (!order_mask)
+ goto error;
while (count) {
- int j, order = __fls(count);
+ int j, order;
+
+ order_mask &= (2U << __fls(count)) - 1;
+ order = __fls(order_mask);
+
+ pages[i] = alloc_pages(order ? (gfp | __GFP_NORETRY) &
+ ~__GFP_RECLAIM : gfp, order);
+ while (!pages[i] && order) {
+ order_mask &= ~(1U << order);
+ order = __fls(order_mask);
+ pages[i] = alloc_pages(order ? (gfp | __GFP_NORETRY) &
+ ~__GFP_RECLAIM : gfp, order);
+ }
- pages[i] = alloc_pages(gfp, order);
- while (!pages[i] && order)
- pages[i] = alloc_pages(gfp, --order);
if (!pages[i])
goto error;
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 1c76daacfb0b..b8fffb591ec4 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -924,14 +924,13 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
index = page - alloc->pages;
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
+
+ mm = alloc->vma_vm_mm;
+ if (!mmget_not_zero(mm))
+ goto err_mmget;
+ if (!down_write_trylock(&mm->mmap_sem))
+ goto err_down_write_mmap_sem_failed;
vma = alloc->vma;
- if (vma) {
- if (!mmget_not_zero(alloc->vma_vm_mm))
- goto err_mmget;
- mm = alloc->vma_vm_mm;
- if (!down_write_trylock(&mm->mmap_sem))
- goto err_down_write_mmap_sem_failed;
- }
list_lru_isolate(lru, item);
spin_unlock(lock);
@@ -945,10 +944,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
PAGE_SIZE, NULL);
trace_binder_unmap_user_end(alloc, index);
-
- up_write(&mm->mmap_sem);
- mmput(mm);
}
+ up_write(&mm->mmap_sem);
+ mmput(mm);
trace_binder_unmap_kernel_start(alloc, index);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index b332a13a9925..2d0574200459 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -106,6 +106,7 @@
#define PERF_KEYS \
"count:flush:map:copy:glink:getargs:putargs:invalidate:invoke:tid:ptr"
+#define FASTRPC_STATIC_HANDLE_KERNEL (1)
#define FASTRPC_STATIC_HANDLE_LISTENER (3)
#define FASTRPC_STATIC_HANDLE_MAX (20)
#define FASTRPC_LATENCY_CTRL_ENB (1)
@@ -1953,6 +1954,14 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
if (fl->profile)
getnstimeofday(&invoket);
+ if (!kernel) {
+ VERIFY(err, invoke->handle != FASTRPC_STATIC_HANDLE_KERNEL);
+ if (err) {
+ pr_err("adsprpc: ERROR: %s: user application %s trying to send a kernel RPC message to channel %d",
+ __func__, current->comm, cid);
+ goto bail;
+ }
+ }
VERIFY(err, fl->sctx != NULL);
if (err)
@@ -2092,7 +2101,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@@ -2187,7 +2196,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[5].buf.len = sizeof(inbuf.siglen);
fds[5] = 0;
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(6, 4, 0);
if (uproc->attrs)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 6, 0);
@@ -2273,7 +2282,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
ra[2].buf.pv = (void *)pages;
ra[2].buf.len = sizeof(*pages);
fds[2] = 0;
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(8, 3, 0);
ioctl.inv.pra = ra;
@@ -2325,7 +2334,7 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
tgid = fl->tgid;
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@@ -2371,7 +2380,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
ra[2].buf.pv = (void *)&routargs;
ra[2].buf.len = sizeof(routargs);
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
if (fl->apps->compat)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(4, 2, 1);
else
@@ -2426,7 +2435,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys,
ra[0].buf.pv = (void *)&routargs;
ra[0].buf.len = sizeof(routargs);
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1);
ioctl.inv.pra = ra;
ioctl.fds = NULL;
@@ -2477,7 +2486,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr,
ra[0].buf.pv = (void *)&inargs;
ra[0].buf.len = sizeof(inargs);
- ioctl.inv.handle = 1;
+ ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL;
if (fl->apps->compat)
ioctl.inv.sc = REMOTE_SCALARS_MAKE(5, 1, 0);
else
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 0937b2f14d77..5a1afd0e41c7 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2757,10 +2757,11 @@ err:
int diag_dci_init(void)
{
- int ret = 0;
+ int ret = 0, i;
driver->dci_tag = 0;
- driver->dci_client_id = 0;
+ for (i = 0; i < MAX_DCI_CLIENTS; i++)
+ driver->dci_client_id[i] = 0;
driver->num_dci_client = 0;
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
@@ -2956,8 +2957,8 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry)
mutex_init(&new_entry->write_buf_mutex);
new_entry->dci_log_mask = vzalloc(DCI_LOG_MASK_SIZE);
if (!new_entry->dci_log_mask) {
- pr_err("diag: Unable to create log mask for client, %d",
- driver->dci_client_id);
+ pr_err("diag: Unable to create log mask for DCI client, tgid: %d\n",
+ current->tgid);
goto fail_alloc;
}
create_dci_log_mask_tbl(new_entry->dci_log_mask, DCI_LOG_MASK_CLEAN);
@@ -3006,17 +3007,24 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry)
proc_buf->buf_curr = proc_buf->buf_primary;
}
- list_add_tail(&new_entry->track, &driver->dci_client_list);
- driver->dci_client_id++;
- new_entry->client_info.client_id = driver->dci_client_id;
- reg_entry->client_id = driver->dci_client_id;
+ for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+ if (driver->dci_client_id[i] == 0)
+ break;
+ }
+
+ if (i == MAX_DCI_CLIENTS)
+ goto fail_alloc;
+ driver->dci_client_id[i] = 1;
+ new_entry->client_info.client_id = i+1;
+ reg_entry->client_id = i+1;
driver->num_dci_client++;
+ list_add_tail(&new_entry->track, &driver->dci_client_list);
if (driver->num_dci_client == 1)
diag_update_proc_vote(DIAG_PROC_DCI, VOTE_UP, reg_entry->token);
queue_work(driver->diag_real_time_wq, &driver->diag_real_time_work);
mutex_unlock(&driver->dci_mutex);
- return driver->dci_client_id;
+ return reg_entry->client_id;
fail_alloc:
if (new_entry) {
@@ -3075,7 +3083,11 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry)
*/
if (!list_empty(&entry->track))
list_del(&entry->track);
+
+ if (entry->client_info.client_id > MAX_DCI_CLIENTS)
+ return DIAG_DCI_NO_REG;
driver->num_dci_client--;
+ driver->dci_client_id[entry->client_info.client_id - 1] = 0;
/*
* Clear the client's log and event masks, update the cumulative
* masks and send the masks to peripherals
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 2fb0e3f7adf3..835c0c1708cf 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,6 @@
#ifndef DIAG_DCI_H
#define DIAG_DCI_H
-#define MAX_DCI_CLIENTS 10
#define DCI_PKT_RSP_CODE 0x93
#define DCI_DELAYED_RSP_CODE 0x94
#define DCI_CONTROL_PKT_CODE 0x9A
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index 24a9f8af728a..b8b8b3206528 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -324,8 +324,8 @@ static void diag_usb_write_done(struct diag_usb_info *ch,
DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n",
atomic_read(&entry->ref_count));
diag_ws_on_copy_complete(DIAG_WS_MUX);
- spin_unlock_irqrestore(&ch->write_lock, flags);
diagmem_free(driver, req, ch->mempool);
+ spin_unlock_irqrestore(&ch->write_lock, flags);
return;
}
DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n",
@@ -343,8 +343,8 @@ static void diag_usb_write_done(struct diag_usb_info *ch,
buf = NULL;
len = 0;
ctxt = 0;
- spin_unlock_irqrestore(&ch->write_lock, flags);
diagmem_free(driver, req, ch->mempool);
+ spin_unlock_irqrestore(&ch->write_lock, flags);
}
static void diag_usb_notifier(void *priv, unsigned int event,
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index f63d78c32b6e..56be94c8197f 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -288,6 +288,7 @@ for (i = 0; i <= fwd_info->num_pd - 2; i++) \
#define DIAG_CNTL_TYPE 2
#define DIAG_DCI_TYPE 3
+#define MAX_DCI_CLIENTS 10
/*
* List of diag ids
* 0 is reserved for unknown diag id, 1 for apps, diag ids
@@ -479,6 +480,12 @@ struct diag_logging_mode_param_t {
int peripheral;
} __packed;
+struct diag_query_pid_t {
+ uint32_t peripheral_mask;
+ uint32_t pd_mask;
+ int pid;
+};
+
struct diag_md_session_t {
int pid;
int peripheral_mask;
@@ -580,7 +587,7 @@ struct diagchar_dev {
struct list_head dci_req_list;
struct list_head dci_client_list;
int dci_tag;
- int dci_client_id;
+ int dci_client_id[MAX_DCI_CLIENTS];
struct mutex dci_mutex;
int num_dci_client;
unsigned char *apps_dci_buf;
@@ -597,6 +604,7 @@ struct diagchar_dev {
unsigned int poolsize_hdlc;
unsigned int poolsize_dci;
unsigned int poolsize_user;
+ spinlock_t diagmem_lock;
/* Buffers for masks */
struct mutex diag_cntl_mutex;
/* Members for Sending response */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 8adaf6478acb..8a88cf08e574 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -213,17 +213,19 @@ static void drain_timer_func(unsigned long data)
static void diag_drain_apps_data(struct diag_apps_data_t *data)
{
int err = 0;
+ unsigned long flags;
if (!data || !data->buf)
return;
err = diag_mux_write(DIAG_LOCAL_PROC, data->buf, data->len,
data->ctxt);
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
if (err)
diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
-
data->buf = NULL;
data->len = 0;
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
}
void diag_update_user_client_work_fn(struct work_struct *work)
@@ -294,6 +296,8 @@ static void diag_mempool_init(void)
diagmem_init(driver, POOL_TYPE_HDLC);
diagmem_init(driver, POOL_TYPE_USER);
diagmem_init(driver, POOL_TYPE_DCI);
+
+ spin_lock_init(&driver->diagmem_lock);
}
static void diag_mempool_exit(void)
@@ -2356,6 +2360,93 @@ static int diag_ioctl_query_pd_logging(struct diag_logging_mode_param_t *param)
return ret;
}
+static void diag_ioctl_query_session_pid(struct diag_query_pid_t *param)
+{
+ int prev_pid = 0, test_pid = 0, i = 0, count = 0;
+ uint32_t pd_mask = 0, peripheral_mask = 0;
+ struct diag_md_session_t *info = NULL;
+
+ param->pid = 0;
+
+ if (param->pd_mask && param->peripheral_mask) {
+ param->pid = -EINVAL;
+ return;
+ } else if (param->peripheral_mask) {
+ if (param->peripheral_mask == DIAG_CON_ALL) {
+ for (i = 0; i <= NUM_PERIPHERALS; i++) {
+ if (driver->md_session_map[i]) {
+ test_pid =
+ driver->md_session_map[i]->pid;
+ count++;
+ if (!prev_pid)
+ prev_pid = test_pid;
+ if (test_pid != prev_pid) {
+ DIAG_LOG(DIAG_DEBUG_USERSPACE,
+ "diag: One of the peripherals is being logged already\n");
+ param->pid = -EINVAL;
+ }
+ }
+ }
+ if (i == count && prev_pid)
+ param->pid = prev_pid;
+ } else {
+ peripheral_mask =
+ diag_translate_mask(param->peripheral_mask);
+ for (i = 0; i <= NUM_PERIPHERALS; i++) {
+ if (driver->md_session_map[i] &&
+ (peripheral_mask &
+ MD_PERIPHERAL_MASK(i))) {
+ info = driver->md_session_map[i];
+ if (peripheral_mask !=
+ info->peripheral_mask) {
+ DIAG_LOG(DIAG_DEBUG_USERSPACE,
+ "diag: Invalid Peripheral mask given as input\n");
+ param->pid = -EINVAL;
+ return;
+ }
+ test_pid = info->pid;
+ if (!prev_pid)
+ prev_pid = test_pid;
+ if (test_pid != prev_pid) {
+ DIAG_LOG(DIAG_DEBUG_USERSPACE,
+ "diag: One of the peripherals is logged in different session\n");
+ param->pid = -EINVAL;
+ return;
+ }
+ }
+ }
+ param->pid = prev_pid;
+ }
+ } else if (param->pd_mask) {
+ pd_mask =
+ diag_translate_mask(param->pd_mask);
+ for (i = UPD_WLAN; i < NUM_MD_SESSIONS; i++) {
+ if (driver->md_session_map[i] &&
+ (pd_mask & MD_PERIPHERAL_MASK(i))) {
+ info = driver->md_session_map[i];
+ if (pd_mask != info->peripheral_mask) {
+ DIAG_LOG(DIAG_DEBUG_USERSPACE,
+ "diag: Invalid PD mask given as input\n");
+ param->pid = -EINVAL;
+ return;
+ }
+ test_pid = info->pid;
+ if (!prev_pid)
+ prev_pid = test_pid;
+ if (test_pid != prev_pid) {
+ DIAG_LOG(DIAG_DEBUG_USERSPACE,
+ "diag: One of the PDs is being logged already\n");
+ param->pid = -EINVAL;
+ return;
+ }
+ }
+ }
+ param->pid = prev_pid;
+ }
+ DIAG_LOG(DIAG_DEBUG_USERSPACE,
+ "diag: Pid for the active ODL session: %d\n", param->pid);
+}
+
static int diag_ioctl_register_callback(unsigned long ioarg)
{
int err = 0;
@@ -2482,6 +2573,7 @@ long diagchar_compat_ioctl(struct file *filp,
uint16_t remote_dev;
struct diag_dci_client_tbl *dci_client = NULL;
struct diag_logging_mode_param_t mode_param;
+ struct diag_query_pid_t pid_query;
switch (iocmd) {
case DIAG_IOCTL_COMMAND_REG:
@@ -2600,6 +2692,22 @@ long diagchar_compat_ioctl(struct file *filp,
return -EFAULT;
result = diag_ioctl_query_pd_logging(&mode_param);
break;
+ case DIAG_IOCTL_QUERY_MD_PID:
+ if (copy_from_user((void *)&pid_query, (void __user *)ioarg,
+ sizeof(pid_query))) {
+ result = -EFAULT;
+ break;
+ }
+ mutex_lock(&driver->md_session_lock);
+ diag_ioctl_query_session_pid(&pid_query);
+ mutex_unlock(&driver->md_session_lock);
+
+ if (copy_to_user((void __user *)ioarg, &pid_query,
+ sizeof(pid_query)))
+ result = -EFAULT;
+ else
+ result = 0;
+ break;
}
return result;
}
@@ -2614,6 +2722,7 @@ long diagchar_ioctl(struct file *filp,
uint16_t remote_dev;
struct diag_dci_client_tbl *dci_client = NULL;
struct diag_logging_mode_param_t mode_param;
+ struct diag_query_pid_t pid_query;
switch (iocmd) {
case DIAG_IOCTL_COMMAND_REG:
@@ -2732,6 +2841,23 @@ long diagchar_ioctl(struct file *filp,
return -EFAULT;
result = diag_ioctl_query_pd_logging(&mode_param);
break;
+ case DIAG_IOCTL_QUERY_MD_PID:
+ if (copy_from_user((void *)&pid_query, (void __user *)ioarg,
+ sizeof(pid_query))) {
+ result = -EFAULT;
+ break;
+ }
+
+ mutex_lock(&driver->md_session_lock);
+ diag_ioctl_query_session_pid(&pid_query);
+ mutex_unlock(&driver->md_session_lock);
+
+ if (copy_to_user((void __user *)ioarg, &pid_query,
+ sizeof(pid_query)))
+ result = -EFAULT;
+ else
+ result = 0;
+ break;
}
return result;
}
@@ -2744,6 +2870,7 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
struct diag_apps_data_t *data = &hdlc_data;
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+ unsigned long flags;
/*
* The maximum encoded size of the buffer can be atmost twice the length
* of the packet. Add three bytes foe footer - 16 bit CRC (2 bytes) +
@@ -2848,10 +2975,11 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
return PKT_ALLOC;
fail_free_buf:
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
data->buf = NULL;
data->len = 0;
-
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
fail_ret:
return ret;
}
@@ -2863,6 +2991,7 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
int ret = PKT_DROP;
struct diag_pkt_frame_t header;
struct diag_apps_data_t *data = &non_hdlc_data;
+ unsigned long flags;
/*
* The maximum packet size, when the data is non hdlc encoded is equal
* to the size of the packet frame header and the length. Add 1 for the
@@ -2927,10 +3056,11 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
return PKT_ALLOC;
fail_free_buf:
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
diagmem_free(driver, data->buf, POOL_TYPE_HDLC);
data->buf = NULL;
data->len = 0;
-
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
fail_ret:
return ret;
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index f1bc1c5047e1..d637405a71d1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1823,9 +1823,11 @@ static int diagfwd_mux_write_done(unsigned char *buf, int len, int buf_ctxt,
diagfwd_write_done(peripheral, type, num);
diag_ws_on_copy(DIAG_WS_MUX);
} else if (peripheral == APPS_DATA) {
+ spin_lock_irqsave(&driver->diagmem_lock, flags);
diagmem_free(driver, (unsigned char *)buf,
POOL_TYPE_HDLC);
buf = NULL;
+ spin_unlock_irqrestore(&driver->diagmem_lock, flags);
} else {
pr_err_ratelimited("diag: Invalid peripheral %d in %s, type: %d\n",
peripheral, __func__, type);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index a6d5ca8a952a..7a7d0fc27d05 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -619,7 +619,12 @@ static int update_msg_mask_tbl_entry(struct diag_msg_mask_t *mask,
}
if (range->ssid_last >= mask->ssid_last) {
temp_range = range->ssid_last - mask->ssid_first + 1;
- mask->ssid_last = range->ssid_last;
+ if (temp_range > MAX_SSID_PER_RANGE) {
+ temp_range = MAX_SSID_PER_RANGE;
+ mask->ssid_last = mask->ssid_first + temp_range - 1;
+ } else
+ mask->ssid_last = range->ssid_last;
+ mask->ssid_last_tools = mask->ssid_last;
mask->range = temp_range;
}
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index ada645d92104..2a3602568a1d 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2014, 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 2016, 2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -221,7 +221,7 @@ void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type)
break;
}
spin_lock_irqsave(&mempool->lock, flags);
- if (mempool->count > 0) {
+ if (mempool->count > 0 && buf) {
mempool_free(buf, mempool->pool);
atomic_add(-1, (atomic_t *)&mempool->count);
} else {
diff --git a/drivers/clk/msm/clock-gcc-8952.c b/drivers/clk/msm/clock-gcc-8952.c
index 71f0ea6fb746..ed39a8ba777f 100644
--- a/drivers/clk/msm/clock-gcc-8952.c
+++ b/drivers/clk/msm/clock-gcc-8952.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -371,6 +371,7 @@ DEFINE_EXT_CLK(gpll0_clk_src, NULL);
DEFINE_EXT_CLK(gpll0_ao_clk_src, NULL);
DEFINE_EXT_CLK(gpll0_out_aux_clk_src, &gpll0_clk_src.c);
DEFINE_EXT_CLK(gpll0_out_main_clk_src, &gpll0_clk_src.c);
+DEFINE_EXT_CLK(gpll0_gfx_clk_src, &gpll0_clk_src.c);
DEFINE_EXT_CLK(ext_pclk0_clk_src, NULL);
DEFINE_EXT_CLK(ext_byte0_clk_src, NULL);
DEFINE_EXT_CLK(ext_pclk1_clk_src, NULL);
@@ -428,6 +429,7 @@ static struct pll_vote_clk gpll6_clk_src = {
DEFINE_EXT_CLK(gpll6_aux_clk_src, &gpll6_clk_src.c);
DEFINE_EXT_CLK(gpll6_out_main_clk_src, &gpll6_clk_src.c);
+DEFINE_EXT_CLK(gpll6_gfx_clk_src, &gpll6_clk_src.c);
static struct alpha_pll_masks pll_masks_p = {
.lock_mask = BIT(31),
@@ -873,6 +875,28 @@ static struct clk_freq_tbl ftbl_gcc_oxili_gfx3d_clk_8917_650MHz[] = {
F_END
};
+static struct clk_freq_tbl ftbl_gcc_oxili_gfx3d_clk_qm215[] = {
+ F_SLEW( 19200000, FIXED_CLK_SRC, xo, 1, 0, 0),
+ F_SLEW( 50000000, FIXED_CLK_SRC, gpll0_gfx, 16, 0, 0),
+ F_SLEW( 80000000, FIXED_CLK_SRC, gpll0_gfx, 10, 0, 0),
+ F_SLEW( 100000000, FIXED_CLK_SRC, gpll0_gfx, 8, 0, 0),
+ F_SLEW( 160000000, FIXED_CLK_SRC, gpll0_gfx, 5, 0, 0),
+ F_SLEW( 200000000, FIXED_CLK_SRC, gpll0_gfx, 4, 0, 0),
+ F_SLEW( 228570000, FIXED_CLK_SRC, gpll0_gfx, 3.5, 0, 0),
+ F_SLEW( 240000000, FIXED_CLK_SRC, gpll6_gfx, 4.5, 0, 0),
+ F_SLEW( 266670000, FIXED_CLK_SRC, gpll0_gfx, 3, 0, 0),
+ F_SLEW( 270000000, FIXED_CLK_SRC, gpll6_gfx, 4, 0, 0),
+ F_SLEW( 320000000, FIXED_CLK_SRC, gpll0_gfx, 2.5, 0, 0),
+ F_SLEW( 400000000, FIXED_CLK_SRC, gpll0_gfx, 2, 0, 0),
+ F_SLEW( 465000000, 930000000, gpll3, 1, 0, 0),
+ F_SLEW( 484800000, 969600000, gpll3, 1, 0, 0),
+ F_SLEW( 500000000, 1000000000, gpll3, 1, 0, 0),
+ F_SLEW( 523200000, 1046400000, gpll3, 1, 0, 0),
+ F_SLEW( 550000000, 1100000000, gpll3, 1, 0, 0),
+ F_SLEW( 598000000, 1196000000, gpll3, 1, 0, 0),
+ F_END
+};
+
static struct rcg_clk gfx3d_clk_src = {
.cmd_rcgr_reg = GFX3D_CMD_RCGR,
.set_rate = set_rate_hid,
@@ -4388,6 +4412,7 @@ static int msm_gcc_probe(struct platform_device *pdev)
bool compat_bin4 = false;
bool compat_bin5 = false;
bool compat_bin6 = false;
+ bool compat_bin7 = false;
compat_bin = of_device_is_compatible(pdev->dev.of_node,
"qcom,gcc-8937");
@@ -4407,11 +4432,14 @@ static int msm_gcc_probe(struct platform_device *pdev)
compat_bin6 = of_device_is_compatible(pdev->dev.of_node,
"qcom,gcc-sdm439");
+ compat_bin7 = of_device_is_compatible(pdev->dev.of_node,
+ "qcom,gcc-qm215");
+
ret = vote_bimc(&bimc_clk, INT_MAX);
if (ret < 0)
return ret;
- if (compat_bin2 || compat_bin4 || compat_bin5)
+ if (compat_bin2 || compat_bin4 || compat_bin5 || compat_bin7)
nbases = APCS_C0_PLL_BASE;
if (compat_bin5 || compat_bin6) {
@@ -4444,7 +4472,7 @@ static int msm_gcc_probe(struct platform_device *pdev)
return PTR_ERR(vdd_dig.regulator[0]);
}
- if (!compat_bin2 && !compat_bin4 && !compat_bin5) {
+ if (!compat_bin2 && !compat_bin4 && !compat_bin5 && !compat_bin7) {
vdd_sr2_pll.regulator[0] = devm_regulator_get(&pdev->dev,
"vdd_sr2_pll");
if (IS_ERR(vdd_sr2_pll.regulator[0])) {
@@ -4538,7 +4566,7 @@ static int msm_gcc_probe(struct platform_device *pdev)
475000000;
}
}
- } else if (compat_bin2 || compat_bin4) {
+ } else if (compat_bin2 || compat_bin4 || compat_bin7) {
gpll0_clk_src.c.parent = &gpll0_clk_src_8937.c;
gpll0_ao_clk_src.c.parent = &gpll0_ao_clk_src_8937.c;
vdd_dig.num_levels = VDD_DIG_NUM_8917;
@@ -4548,6 +4576,9 @@ static int msm_gcc_probe(struct platform_device *pdev)
get_speed_bin(pdev, &speed_bin);
override_for_8917(speed_bin);
+ if (compat_bin7)
+ OVERRIDE_FTABLE(gfx3d, ftbl_gcc_oxili_gfx3d_clk, qm215);
+
if (compat_bin2) {
blsp1_qup2_spi_apps_clk_src.freq_tbl =
ftbl_gcc_blsp1_2_qup1_4_spi_apps_clk_8917;
@@ -4577,7 +4608,7 @@ static int msm_gcc_probe(struct platform_device *pdev)
ret = of_msm_clock_register(pdev->dev.of_node,
msm_clocks_lookup_8937,
ARRAY_SIZE(msm_clocks_lookup_8937));
- else if (compat_bin2)
+ else if (compat_bin2 || compat_bin7)
ret = of_msm_clock_register(pdev->dev.of_node,
msm_clocks_lookup_8917,
ARRAY_SIZE(msm_clocks_lookup_8917));
@@ -4650,6 +4681,7 @@ static const struct of_device_id msm_clock_gcc_match_table[] = {
{ .compatible = "qcom,gcc-8920" },
{ .compatible = "qcom,gcc-sdm439" },
{ .compatible = "qcom,gcc-sdm429" },
+ { .compatible = "qcom,gcc-qm215" },
{}
};
diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c
index 6254f45ca907..2ba2c204758b 100644
--- a/drivers/cpufreq/cpufreq_times.c
+++ b/drivers/cpufreq/cpufreq_times.c
@@ -29,8 +29,10 @@
static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS);
-static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */
-static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */
+/* task->time_in_state */
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(task_time_in_state_lock);
+/* uid_hash_table */
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(uid_lock);
struct uid_entry {
uid_t uid;
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index 3c90fe5527f7..d13d8897fcec 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1798,7 +1798,7 @@ int qcom_ice_setup_ice_hw(const char *storage_type, int enable)
if (ice_dev == ERR_PTR(-EPROBE_DEFER))
return -EPROBE_DEFER;
- if (!ice_dev)
+ if (!ice_dev || (ice_dev->is_ice_enabled == false))
return ret;
if (enable)
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index bfe98b505cf6..5396a35ff4bb 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -780,12 +780,10 @@ static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl,
}
static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl,
- u32 rate, u32 stream_rate_khz,
- bool fixed_nvid)
+ u32 rate, u32 stream_rate_khz)
{
u32 pixel_m, pixel_n;
u32 mvid, nvid;
- u64 mvid_calc;
u32 const nvid_fixed = 0x8000;
u32 const link_rate_hbr2 = 540000;
u32 const link_rate_hbr3 = 810000;
@@ -798,44 +796,31 @@ static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl,
}
catalog = dp_catalog_get_priv(ctrl);
- if (fixed_nvid) {
- pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
- nvid = nvid_fixed;
-
- pr_debug("link rate=%dkbps, stream_rate_khz=%uKhz",
- rate, stream_rate_khz);
-
- /*
- * For intermediate results, use 64 bit arithmetic to avoid
- * loss of precision.
- */
- mvid_calc = (u64) stream_rate_khz * nvid;
- mvid_calc = div_u64(mvid_calc, rate);
-
- /*
- * truncate back to 32 bits as this final divided value will
- * always be within the range of a 32 bit unsigned int.
- */
- mvid = (u32) mvid_calc;
- } else {
- io_data = catalog->io.dp_mmss_cc;
-
- pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M);
- pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N);
- pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
+ io_data = catalog->io.dp_mmss_cc;
- mvid = (pixel_m & 0xFFFF) * 5;
- nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
+ pixel_m = dp_read(catalog, io_data, MMSS_DP_PIXEL_M);
+ pixel_n = dp_read(catalog, io_data, MMSS_DP_PIXEL_N);
+ pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
- pr_debug("rate = %d\n", rate);
+ mvid = (pixel_m & 0xFFFF) * 5;
+ nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
- if (link_rate_hbr2 == rate)
- nvid *= 2;
+ if (nvid < nvid_fixed) {
+ u32 temp;
- if (link_rate_hbr3 == rate)
- nvid *= 3;
+ temp = (nvid_fixed / nvid) * nvid;
+ mvid = (nvid_fixed / nvid) * mvid;
+ nvid = temp;
}
+ pr_debug("rate = %d\n", rate);
+
+ if (link_rate_hbr2 == rate)
+ nvid *= 2;
+
+ if (link_rate_hbr3 == rate)
+ nvid *= 3;
+
io_data = catalog->io.dp_link;
pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
dp_write(catalog, io_data, DP_SOFTWARE_MVID, mvid);
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 743468de6c26..dbcbd8b0efd9 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -94,7 +94,7 @@ struct dp_catalog_ctrl {
void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable);
void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb);
void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate,
- u32 stream_rate_khz, bool fixed_nvid);
+ u32 stream_rate_khz);
void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern);
void (*reset)(struct dp_catalog_ctrl *ctrl);
void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index f2e9085cb5a2..befbc5c7f9f9 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1177,24 +1177,6 @@ static void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
pr_debug("Host deinitialized successfully\n");
}
-static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl)
-{
- u8 *dpcd = ctrl->panel->dpcd;
-
- /*
- * For better interop experience, used a fixed NVID=0x8000
- * whenever connected to a VGA dongle downstream.
- */
- if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT) {
- u8 type = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
- DP_DWN_STRM_PORT_TYPE_MASK;
- if (type == DP_DWN_STRM_PORT_TYPE_ANALOG)
- return true;
- }
-
- return false;
-}
-
static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)
{
int ret = 0;
@@ -1247,8 +1229,7 @@ static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl)
ctrl->catalog->config_msa(ctrl->catalog,
drm_dp_bw_code_to_link_rate(
- ctrl->link->link_params.bw_code),
- ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
+ ctrl->link->link_params.bw_code), ctrl->pixel_rate);
reinit_completion(&ctrl->idle_comp);
@@ -1306,9 +1287,7 @@ static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
u32 pattern_sent = 0x0;
u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;
- ctrl->catalog->update_vx_px(ctrl->catalog,
- ctrl->link->phy_params.v_level,
- ctrl->link->phy_params.p_level);
+ dp_ctrl_update_vx_px(ctrl);
ctrl->catalog->send_phy_pattern(ctrl->catalog, pattern_requested);
ctrl->link->send_test_response(ctrl->link);
@@ -1416,8 +1395,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) {
ctrl->catalog->config_msa(ctrl->catalog,
drm_dp_bw_code_to_link_rate(
- ctrl->link->link_params.bw_code),
- ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
+ ctrl->link->link_params.bw_code), ctrl->pixel_rate);
rc = dp_ctrl_setup_main_link(ctrl, true);
if (!rc)
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 6e6efa5cd416..64945cf752cd 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -49,6 +49,7 @@ struct dp_debug_private {
struct device *dev;
struct work_struct sim_work;
struct dp_debug dp_debug;
+ struct mutex lock;
};
static int dp_debug_get_edid_buf(struct dp_debug_private *debug)
@@ -98,6 +99,8 @@ static ssize_t dp_debug_write_edid(struct file *file,
if (!debug)
return -ENODEV;
+ mutex_lock(&debug->lock);
+
if (*ppos)
goto bail;
@@ -148,6 +151,7 @@ bail:
if (!debug->dp_debug.sim_mode)
debug->panel->set_edid(debug->panel, edid);
+ mutex_unlock(&debug->lock);
return rc;
}
@@ -166,6 +170,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file,
if (!debug)
return -ENODEV;
+ mutex_lock(&debug->lock);
+
if (*ppos)
goto bail;
@@ -230,6 +236,7 @@ bail:
else
debug->panel->set_dpcd(debug->panel, dpcd);
+ mutex_unlock(&debug->lock);
return rc;
}
@@ -873,6 +880,8 @@ static ssize_t dp_debug_write_sim(struct file *file,
if (*ppos)
return 0;
+ mutex_lock(&debug->lock);
+
/* Leave room for termination char */
len = min_t(size_t, count, SZ_8 - 1);
if (copy_from_user(buf, user_buff, len))
@@ -906,9 +915,11 @@ static ssize_t dp_debug_write_sim(struct file *file,
debug->aux->set_sim_mode(debug->aux, debug->dp_debug.sim_mode,
debug->edid, debug->dpcd);
end:
+ mutex_unlock(&debug->lock);
return len;
error:
devm_kfree(debug->dev, debug->edid);
+ mutex_unlock(&debug->lock);
return len;
}
@@ -1272,6 +1283,8 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
dp_debug->hdisplay = 0;
dp_debug->vrefresh = 0;
+ mutex_init(&debug->lock);
+
rc = dp_debug_init(dp_debug);
if (rc) {
devm_kfree(dev, debug);
@@ -1308,6 +1321,8 @@ void dp_debug_put(struct dp_debug *dp_debug)
dp_debug_deinit(dp_debug);
+ mutex_destroy(&debug->lock);
+
if (debug->edid)
devm_kfree(debug->dev, debug->edid);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index a0a0daf42c6a..f80c371b4666 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -140,9 +140,18 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
struct sde_hdcp_ops *ops;
int rc = 0;
u32 hdcp_auth_state;
+ u8 sink_status = 0;
dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
+ drm_dp_dpcd_readb(dp->aux->drm_aux, DP_SINK_STATUS, &sink_status);
+ sink_status &= (DP_RECEIVE_PORT_0_STATUS | DP_RECEIVE_PORT_1_STATUS);
+ if (sink_status < 1) {
+ pr_debug("Sink not synchronized. Queuing again then exiting\n");
+ queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ);
+ return;
+ }
+
rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl);
if (rc >= 0) {
hdcp_auth_state = (rc >> 20) & 0x3;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
index cdcb331dbf9d..9f81ed1411e0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -261,13 +261,13 @@ void *dsi_register_clk_handle(void *clk_mngr, char *client);
int dsi_deregister_clk_handle(void *client);
/**
- * dsi_display_link_clk_force_update_ctrl() - force to set link clks
+ * dsi_display_link_clk_force_update() - force to set link clks
* @handle: Handle of desired DSI clock client.
*
* return: error code in case of failure or 0 for success.
*/
-int dsi_display_link_clk_force_update_ctrl(void *handle);
+int dsi_display_link_clk_force_update(void *handle);
/**
* dsi_display_clk_ctrl() - set frequencies for link clks
@@ -277,7 +277,8 @@ int dsi_display_link_clk_force_update_ctrl(void *handle);
*
* return: error code in case of failure or 0 for success.
*/
-int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state);
+int dsi_display_clk_ctrl(void *handle, enum dsi_clk_type clk_type,
+ enum dsi_clk_state clk_state);
/**
* dsi_clk_set_link_frequencies() - set frequencies for link clks
@@ -331,4 +332,14 @@ int dsi_clk_prepare_enable(struct dsi_clk_link_set *clk);
* @clk: list of src clocks.
*/
void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk);
+
+/**
+ * dsi_clk_req_state() - request to change dsi clock state
+ * @client: DSI clocl client pointer.
+ * @clk: DSI clock list.
+ * @state: Requested state of the clock.
+ */
+int dsi_clk_req_state(void *client, enum dsi_clk_type clk,
+ enum dsi_clk_state state);
+
#endif /* _DSI_CLK_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
index 9592603f7491..2faccadd829c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1255,9 +1255,7 @@ int dsi_clk_req_state(void *client, enum dsi_clk_type clk,
return rc;
}
-DEFINE_MUTEX(dsi_mngr_clk_mutex);
-
-static int dsi_display_link_clk_force_update(void *client)
+int dsi_display_link_clk_force_update(void *client)
{
int rc = 0;
struct dsi_clk_client_info *c = client;
@@ -1304,42 +1302,6 @@ error:
}
-int dsi_display_link_clk_force_update_ctrl(void *handle)
-{
- int rc = 0;
-
- if (!handle) {
- pr_err("%s: Invalid arg\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&dsi_mngr_clk_mutex);
-
- rc = dsi_display_link_clk_force_update(handle);
-
- mutex_unlock(&dsi_mngr_clk_mutex);
-
- return rc;
-}
-
-int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state)
-{
- int rc = 0;
-
- if (!handle) {
- pr_err("%s: Invalid arg\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&dsi_mngr_clk_mutex);
- rc = dsi_clk_req_state(handle, clk_type, clk_state);
- if (rc)
- pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
- mutex_unlock(&dsi_mngr_clk_mutex);
-
- return rc;
-}
-
void *dsi_register_clk_handle(void *clk_mngr, char *client)
{
void *handle = NULL;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index f8170b2df2b1..612cea70f4f1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -45,6 +45,9 @@
static DEFINE_MUTEX(dsi_display_list_lock);
static LIST_HEAD(dsi_display_list);
+
+static DEFINE_MUTEX(dsi_display_clk_mutex);
+
static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN];
static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY];
@@ -4261,6 +4264,7 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
int i;
struct dsi_display_ctrl *ctrl;
struct dsi_display_mode_priv_info *priv_info;
+ struct dsi_host_config *config;
priv_info = mode->priv_info;
if (!dsi_display_has_ext_bridge(display) && !priv_info) {
@@ -4269,9 +4273,9 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
return -EINVAL;
}
- rc = dsi_panel_get_host_cfg_for_mode(display->panel,
- mode,
- &display->config);
+ config = &display->config;
+
+ rc = dsi_panel_get_host_cfg_for_mode(display->panel, mode, config);
if (rc) {
pr_err("[%s] failed to get host config for mode, rc=%d\n",
display->name, rc);
@@ -4303,8 +4307,16 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
for (i = 0; i < display->ctrl_count; i++) {
ctrl = &display->ctrl[i];
- rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config,
- mode->dsi_mode_flags, display->dsi_clk_handle);
+ /*
+ * if bit clock is overridden then update the phy timings
+ * and clock out control values first.
+ */
+ if (config->bit_clk_rate_hz)
+ dsi_phy_update_phy_timings(ctrl->phy, config);
+
+ rc = dsi_ctrl_update_host_config(ctrl->ctrl, config,
+ mode->dsi_mode_flags,
+ display->dsi_clk_handle);
if (rc) {
pr_err("[%s] failed to update ctrl config, rc=%d\n",
display->name, rc);
@@ -4515,6 +4527,43 @@ int dsi_display_splash_res_cleanup(struct dsi_display *display)
return rc;
}
+static int dsi_display_link_clk_force_update_ctrl(void *handle)
+{
+ int rc = 0;
+
+ if (!handle) {
+ pr_err("%s: Invalid arg\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dsi_display_clk_mutex);
+
+ rc = dsi_display_link_clk_force_update(handle);
+
+ mutex_unlock(&dsi_display_clk_mutex);
+
+ return rc;
+}
+
+int dsi_display_clk_ctrl(void *handle,
+ enum dsi_clk_type clk_type, enum dsi_clk_state clk_state)
+{
+ int rc = 0;
+
+ if (!handle) {
+ pr_err("%s: Invalid arg\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dsi_display_clk_mutex);
+ rc = dsi_clk_req_state(handle, clk_type, clk_state);
+ if (rc)
+ pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
+ mutex_unlock(&dsi_display_clk_mutex);
+
+ return rc;
+}
+
static int dsi_display_force_update_dsi_clk(struct dsi_display *display)
{
int rc = 0;
@@ -4603,6 +4652,7 @@ static ssize_t sysfs_dynamic_dsi_clk_write(struct device *dev,
mutex_lock(&display->display_lock);
+ mutex_lock(&dsi_display_clk_mutex);
display->cached_clk_rate = clk_rate;
rc = dsi_display_update_dsi_bitrate(display, clk_rate);
if (!rc) {
@@ -4615,12 +4665,14 @@ static ssize_t sysfs_dynamic_dsi_clk_write(struct device *dev,
atomic_set(&display->clkrate_change_pending, 0);
display->cached_clk_rate = 0;
+ mutex_unlock(&dsi_display_clk_mutex);
mutex_unlock(&display->display_lock);
return rc;
}
atomic_set(&display->clkrate_change_pending, 1);
+ mutex_unlock(&dsi_display_clk_mutex);
mutex_unlock(&display->display_lock);
return count;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index 8e78ae55b7f9..b43b23cda9c3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -1998,6 +1998,7 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel,
{
int rc = 0;
const char *bl_type;
+ const char *data;
u32 val = 0;
bl_type = of_get_property(of_node,
@@ -2017,6 +2018,17 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel,
panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN;
}
+ data = of_get_property(of_node, "qcom,bl-update-flag", NULL);
+ if (!data) {
+ panel->bl_config.bl_update = BL_UPDATE_NONE;
+ } else if (!strcmp(data, "delay_until_first_frame")) {
+ panel->bl_config.bl_update = BL_UPDATE_DELAY_UNTIL_FIRST_FRAME;
+ } else {
+ pr_debug("[%s] No valid bl-update-flag: %s\n",
+ panel->name, data);
+ panel->bl_config.bl_update = BL_UPDATE_NONE;
+ }
+
panel->bl_config.bl_scale = MAX_BL_SCALE_LEVEL;
panel->bl_config.bl_scale_ad = MAX_AD_BL_SCALE_LEVEL;
@@ -2115,7 +2127,7 @@ int dsi_dsc_populate_static_param(struct msm_display_dsc_info *dsc)
int target_bpp_x16;
int data;
int final_value, final_scale;
- int ratio_index;
+ int ratio_index, mod_offset;
dsc->rc_model_size = 8192;
@@ -2187,7 +2199,20 @@ int dsi_dsc_populate_static_param(struct msm_display_dsc_info *dsc)
dsc->quant_incr_limit1 = 19;
}
- dsc->slice_last_group_size = 3 - (dsc->slice_width % 3);
+ mod_offset = dsc->slice_width % 3;
+ switch (mod_offset) {
+ case 0:
+ dsc->slice_last_group_size = 2;
+ break;
+ case 1:
+ dsc->slice_last_group_size = 0;
+ break;
+ case 2:
+ dsc->slice_last_group_size = 1;
+ break;
+ default:
+ break;
+ }
dsc->det_thresh_flatness = 7 + 2*(bpc - 8);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index ac55d7d2b5e2..ab8ccee9fb98 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -51,6 +51,11 @@ enum dsi_backlight_type {
DSI_BACKLIGHT_MAX,
};
+enum bl_update_flag {
+ BL_UPDATE_DELAY_UNTIL_FIRST_FRAME,
+ BL_UPDATE_NONE,
+};
+
enum {
MODE_GPIO_NOT_VALID = 0,
MODE_SEL_DUAL_PORT,
@@ -93,6 +98,7 @@ struct dsi_panel_phy_props {
struct dsi_backlight_config {
enum dsi_backlight_type type;
+ enum bl_update_flag bl_update;
u32 bl_min_level;
u32 bl_max_level;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
index ebc699aa13ff..32497ffe9abd 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -883,6 +883,8 @@ int dsi_phy_update_phy_timings(struct msm_dsi_phy *phy,
&phy->cfg.timing, true);
if (rc)
pr_err("failed to calculate phy timings %d\n", rc);
+ else
+ phy->cfg.is_phy_timing_present = true;
return rc;
}
@@ -1045,6 +1047,9 @@ int dsi_phy_set_timing_params(struct msm_dsi_phy *phy,
return -EINVAL;
}
+ if (phy->cfg.is_phy_timing_present)
+ return rc;
+
mutex_lock(&phy->phy_lock);
if (phy->hw.ops.phy_timing_val)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
index 44d092846117..5d9759d90467 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -434,6 +434,44 @@ error:
return rc;
}
+static int calc_clk_post(struct dsi_phy_hw *phy,
+ struct phy_clk_params *clk_params,
+ struct phy_timing_desc *desc)
+{
+ struct timing_entry *t = &desc->clk_post;
+ int temp = 0, rc;
+
+ temp = DIV_ROUND_UP(((60 * clk_params->bitclk_mbps) + 9000), 8000) - 1;
+ t->rec = DIV_ROUND_UP((t->rec_max + (9 * temp)), 10);
+
+ rc = dsi_phy_cmn_validate_and_set(t, "clk_post");
+
+ pr_debug("clk_post val 0x%x\n", t->reg_value);
+ return rc;
+}
+
+static int calc_clk_pre(struct dsi_phy_hw *phy,
+ struct phy_clk_params *clk_params,
+ struct phy_timing_desc *desc)
+{
+ struct timing_entry *t = &desc->clk_pre;
+ int temp = 0, rc;
+
+ temp = desc->clk_prepare.reg_value + desc->clk_zero.reg_value +
+ desc->hs_rqst_clk.reg_value + 2;
+
+ if (temp > t->rec_max) {
+ t->rec = DIV_ROUND_UP(((2 * t->rec_max) + (9 * temp)), 10);
+ t->rec = t->rec / 2;
+ } else
+ t->rec = DIV_ROUND_UP((t->rec_max + (9 * temp)), 10);
+
+ rc = dsi_phy_cmn_validate_and_set(t, "clk_pre");
+
+ pr_debug("clk_pre val 0x%x\n", t->reg_value);
+ return rc;
+}
+
/**
* dsi_phy_calc_timing_params - calculates timing paramets for a given bit clock
*/
@@ -501,6 +539,19 @@ static int dsi_phy_cmn_calc_timing_params(struct dsi_phy_hw *phy,
pr_err("hs_rqst_clk calculations failed, rc=%d\n", rc);
goto error;
}
+
+ rc = calc_clk_post(phy, clk_params, desc);
+ if (rc) {
+ pr_err("clk_post calculation failed, rc= %d\n", rc);
+ goto error;
+ }
+
+ rc = calc_clk_pre(phy, clk_params, desc);
+ if (rc) {
+ pr_err("clk_pre calculation failed, rc= %d\n", rc);
+ goto error;
+ }
+
error:
return rc;
}
@@ -582,6 +633,8 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
desc.hs_exit.rec_max = hs_exit_reco_max;
desc.hs_rqst.mipi_min = hs_rqst_spec_min;
desc.hs_rqst_clk.mipi_min = hs_rqst_spec_min;
+ desc.clk_post.rec_max = 63;
+ desc.clk_pre.rec_max = 63;
if (ops->get_default_phy_params) {
ops->get_default_phy_params(&clk_params);
@@ -611,6 +664,9 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
if (ops->update_timing_params) {
ops->update_timing_params(timing, &desc);
+ /* update clock out timing control values */
+ host->t_clk_pre = desc.clk_pre.reg_value;
+ host->t_clk_post = desc.clk_post.reg_value;
} else {
rc = -EINVAL;
goto error;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
index c0e9d441542d..c169a435981b 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,14 +17,14 @@
void dsi_phy_hw_v3_0_get_default_phy_params(
struct phy_clk_params *params)
{
- params->clk_prep_buf = 0;
- params->clk_zero_buf = 0;
- params->clk_trail_buf = 0;
- params->hs_prep_buf = 0;
- params->hs_zero_buf = 0;
- params->hs_trail_buf = 0;
+ params->clk_prep_buf = 50;
+ params->clk_zero_buf = 2;
+ params->clk_trail_buf = 30;
+ params->hs_prep_buf = 50;
+ params->hs_zero_buf = 10;
+ params->hs_trail_buf = 30;
params->hs_rqst_buf = 0;
- params->hs_exit_buf = 0;
+ params->hs_exit_buf = 10;
}
int32_t dsi_phy_hw_v3_0_calc_clk_zero(s64 rec_temp1, s64 mult)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 4b152ac05e86..a4d71f79da6a 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -50,6 +50,7 @@ int msm_drm_register_client(struct notifier_block *nb)
return blocking_notifier_chain_register(&msm_drm_notifier_list,
nb);
}
+EXPORT_SYMBOL(msm_drm_register_client);
/**
* msm_drm_unregister_client - unregister a client notifier
@@ -63,6 +64,7 @@ int msm_drm_unregister_client(struct notifier_block *nb)
return blocking_notifier_chain_unregister(&msm_drm_notifier_list,
nb);
}
+EXPORT_SYMBOL(msm_drm_unregister_client);
/**
* msm_drm_notifier_call_chain - notify clients of drm_events
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 8680449b3e88..378847d92308 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -1862,24 +1862,29 @@ int sde_cp_ad_interrupt(struct drm_crtc *crtc_drm, bool en,
node = container_of(ad_irq, struct sde_crtc_irq_info, irq);
+ /* deregister AD irq */
if (!en) {
spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_ENABLED) {
+ node->state = IRQ_DISABLING;
+ spin_unlock_irqrestore(&node->state_lock, flags);
ret = sde_core_irq_disable(kms, &irq_idx, 1);
- if (ret)
+ spin_lock_irqsave(&node->state_lock, flags);
+ if (ret) {
DRM_ERROR("disable irq %d error %d\n",
irq_idx, ret);
- else
- node->state = IRQ_NOINIT;
- } else {
- node->state = IRQ_NOINIT;
+ node->state = IRQ_ENABLED;
+ } else {
+ node->state = IRQ_DISABLED;
+ }
}
spin_unlock_irqrestore(&node->state_lock, flags);
+
sde_core_irq_unregister_callback(kms, irq_idx, ad_irq);
- ret = 0;
goto exit;
}
+ /* register AD irq */
ad_irq->arg = crtc;
ad_irq->func = sde_cp_ad_interrupt_cb;
ret = sde_core_irq_register_callback(kms, irq_idx, ad_irq);
@@ -1889,11 +1894,15 @@ int sde_cp_ad_interrupt(struct drm_crtc *crtc_drm, bool en,
}
spin_lock_irqsave(&node->state_lock, flags);
- if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
+ if (node->state == IRQ_DISABLED) {
+ node->state = IRQ_ENABLING;
+ spin_unlock_irqrestore(&node->state_lock, flags);
ret = sde_core_irq_enable(kms, &irq_idx, 1);
+ spin_lock_irqsave(&node->state_lock, flags);
if (ret) {
DRM_ERROR("enable irq %d error %d\n", irq_idx, ret);
sde_core_irq_unregister_callback(kms, irq_idx, ad_irq);
+ node->state = IRQ_DISABLED;
} else {
node->state = IRQ_ENABLED;
}
@@ -2138,15 +2147,10 @@ int sde_cp_hist_interrupt(struct drm_crtc *crtc_drm, bool en,
irq_idx, ret);
node->state = IRQ_ENABLED;
} else {
- node->state = IRQ_NOINIT;
+ node->state = IRQ_DISABLED;
}
- spin_unlock_irqrestore(&node->state_lock, flags);
- } else if (node->state == IRQ_DISABLED) {
- node->state = IRQ_NOINIT;
- spin_unlock_irqrestore(&node->state_lock, flags);
- } else {
- spin_unlock_irqrestore(&node->state_lock, flags);
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
sde_core_irq_unregister_callback(kms, irq_idx, hist_irq);
goto exit;
@@ -2162,12 +2166,16 @@ int sde_cp_hist_interrupt(struct drm_crtc *crtc_drm, bool en,
}
spin_lock_irqsave(&node->state_lock, flags);
- if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
+ if (node->state == IRQ_DISABLED) {
+ node->state = IRQ_ENABLING;
+ spin_unlock_irqrestore(&node->state_lock, flags);
ret = sde_core_irq_enable(kms, &irq_idx, 1);
+ spin_lock_irqsave(&node->state_lock, flags);
if (ret) {
DRM_ERROR("enable irq %d error %d\n", irq_idx, ret);
sde_core_irq_unregister_callback(kms,
irq_idx, hist_irq);
+ node->state = IRQ_DISABLED;
} else {
node->state = IRQ_ENABLED;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index fce87e34ccaf..85b9f7e153a9 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -89,12 +89,19 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
if (!bl_lvl && brightness)
bl_lvl = 1;
+ if (display->panel->bl_config.bl_update ==
+ BL_UPDATE_DELAY_UNTIL_FIRST_FRAME && !c_conn->allow_bl_update) {
+ c_conn->unset_bl_level = bl_lvl;
+ return 0;
+ }
+
if (c_conn->ops.set_backlight) {
event.type = DRM_EVENT_SYS_BACKLIGHT;
event.length = sizeof(u32);
msm_mode_object_event_notify(&c_conn->base.base,
c_conn->base.dev, &event, (u8 *)&brightness);
rc = c_conn->ops.set_backlight(c_conn->display, bl_lvl);
+ c_conn->unset_bl_level = 0;
}
return rc;
@@ -519,6 +526,15 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn)
bl_config = &dsi_display->panel->bl_config;
+ if (dsi_display->panel->bl_config.bl_update ==
+ BL_UPDATE_DELAY_UNTIL_FIRST_FRAME && !c_conn->allow_bl_update) {
+ c_conn->unset_bl_level = bl_config->bl_level;
+ return 0;
+ }
+
+ if (c_conn->unset_bl_level)
+ bl_config->bl_level = c_conn->unset_bl_level;
+
if (c_conn->bl_scale > MAX_BL_SCALE_LEVEL)
bl_config->bl_scale = MAX_BL_SCALE_LEVEL;
else
@@ -533,6 +549,7 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn)
bl_config->bl_scale, bl_config->bl_scale_ad,
bl_config->bl_level);
rc = c_conn->ops.set_backlight(dsi_display, bl_config->bl_level);
+ c_conn->unset_bl_level = 0;
return rc;
}
@@ -572,8 +589,11 @@ static int _sde_connector_update_dirty_properties(
}
}
- /* Special handling for postproc properties */
- if (c_conn->bl_scale_dirty) {
+ /*
+ * Special handling for postproc properties and
+ * for updating backlight if any unset backlight level is present
+ */
+ if (c_conn->bl_scale_dirty || c_conn->unset_bl_level) {
_sde_connector_update_bl_scale(c_conn);
c_conn->bl_scale_dirty = false;
}
@@ -639,29 +659,44 @@ void sde_connector_helper_bridge_disable(struct drm_connector *connector)
sde_connector_schedule_status_work(connector, false);
c_conn = to_sde_connector(connector);
- if (c_conn->panel_dead) {
+ if (c_conn->bl_device) {
c_conn->bl_device->props.power = FB_BLANK_POWERDOWN;
c_conn->bl_device->props.state |= BL_CORE_FBBLANK;
backlight_update_status(c_conn->bl_device);
}
+
+ c_conn->allow_bl_update = false;
}
void sde_connector_helper_bridge_enable(struct drm_connector *connector)
{
struct sde_connector *c_conn = NULL;
+ struct dsi_display *display;
if (!connector)
return;
c_conn = to_sde_connector(connector);
+ display = (struct dsi_display *) c_conn->display;
+
+ /*
+ * Special handling for some panels which need atleast
+ * one frame to be transferred to GRAM before enabling backlight.
+ * So delay backlight update to these panels until the
+ * first frame commit is received from the HW.
+ */
+ if (display->panel->bl_config.bl_update ==
+ BL_UPDATE_DELAY_UNTIL_FIRST_FRAME)
+ sde_encoder_wait_for_event(c_conn->encoder,
+ MSM_ENC_TX_COMPLETE);
+ c_conn->allow_bl_update = true;
- /* Special handling for ESD recovery case */
- if (c_conn->panel_dead) {
+ if (c_conn->bl_device) {
c_conn->bl_device->props.power = FB_BLANK_UNBLANK;
c_conn->bl_device->props.state &= ~BL_CORE_FBBLANK;
backlight_update_status(c_conn->bl_device);
- c_conn->panel_dead = false;
}
+ c_conn->panel_dead = false;
}
int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 51dc92ded875..0ae6a91461d1 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -329,7 +329,9 @@ struct sde_connector_evt {
* @bl_scale_dirty: Flag to indicate PP BL scale value(s) is changed
* @bl_scale: BL scale value for ABA feature
* @bl_scale_ad: BL scale value for AD feature
- * last_cmd_tx_sts: status of the last command transfer
+ * @unset_bl_level: BL level that needs to be set later
+ * @allow_bl_update: Flag to indicate if BL update is allowed currently or not
+ * @last_cmd_tx_sts: status of the last command transfer
*/
struct sde_connector {
struct drm_connector base;
@@ -373,6 +375,8 @@ struct sde_connector {
bool bl_scale_dirty;
u32 bl_scale;
u32 bl_scale_ad;
+ u32 unset_bl_level;
+ bool allow_bl_update;
bool last_cmd_tx_sts;
};
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 53a7a60cb09e..e0094d7ec766 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -6216,7 +6216,7 @@ static int _sde_crtc_event_enable(struct sde_kms *kms,
INIT_LIST_HEAD(&node->list);
node->func = custom_events[i].func;
node->event = event;
- node->state = IRQ_NOINIT;
+ node->state = IRQ_DISABLED;
spin_lock_init(&node->state_lock);
break;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 709a51f15618..4700a6cb6a71 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -430,7 +430,7 @@ struct sde_crtc_state {
};
enum sde_crtc_irq_state {
- IRQ_NOINIT,
+ IRQ_ENABLING,
IRQ_ENABLED,
IRQ_DISABLING,
IRQ_DISABLED,
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index a1986dbbb659..122f319c7c00 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1454,7 +1454,7 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
struct msm_mode_info mode_info;
int i, rc = 0;
- if (!sde_enc || !disp_info) {
+ if (!sde_enc || !sde_enc->cur_master || !disp_info) {
SDE_ERROR("invalid param sde_enc:%d or disp_info:%d\n",
sde_enc != NULL, disp_info != NULL);
return;
@@ -2708,6 +2708,21 @@ void sde_encoder_virt_restore(struct drm_encoder *drm_enc)
_sde_encoder_virt_enable_helper(drm_enc);
}
+static void sde_encoder_off_work(struct kthread_work *work)
+{
+ struct sde_encoder_virt *sde_enc = container_of(work,
+ struct sde_encoder_virt, delayed_off_work.work);
+ struct drm_encoder *drm_enc;
+
+ if (!sde_enc) {
+ SDE_ERROR("invalid sde encoder\n");
+ return;
+ }
+ drm_enc = &sde_enc->base;
+
+ sde_encoder_idle_request(drm_enc);
+}
+
static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
{
struct sde_encoder_virt *sde_enc = NULL;
@@ -2768,6 +2783,11 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
sde_enc->input_handler_registered = true;
}
+ if (!(msm_is_mode_seamless_vrr(cur_mode)
+ || msm_is_mode_seamless_dms(cur_mode)))
+ kthread_init_delayed_work(&sde_enc->delayed_off_work,
+ sde_encoder_off_work);
+
ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
if (ret) {
SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n",
@@ -3094,21 +3114,6 @@ int sde_encoder_idle_request(struct drm_encoder *drm_enc)
return 0;
}
-static void sde_encoder_off_work(struct kthread_work *work)
-{
- struct sde_encoder_virt *sde_enc = container_of(work,
- struct sde_encoder_virt, delayed_off_work.work);
- struct drm_encoder *drm_enc;
-
- if (!sde_enc) {
- SDE_ERROR("invalid sde encoder\n");
- return;
- }
- drm_enc = &sde_enc->base;
-
- sde_encoder_idle_request(drm_enc);
-}
-
/**
* _sde_encoder_trigger_flush - trigger flush for a physical encoder
* drm_enc: Pointer to drm encoder structure
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index 4e9430e0d8f8..953106ee9823 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -255,6 +255,7 @@ struct sde_encoder_irq {
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
* @enable_state: Enable state tracking
* @vblank_refcount: Reference count of vblank request
+ * @wbirq_refcount: Reference count of wb irq request
* @vsync_cnt: Vsync count for the physical encoder
* @underrun_cnt: Underrun count for the physical encoder
* @pending_kickoff_cnt: Atomic counter tracking the number of kickoffs
@@ -293,6 +294,7 @@ struct sde_encoder_phys {
enum sde_enc_enable_state enable_state;
struct mutex *vblank_ctl_lock;
atomic_t vblank_refcount;
+ atomic_t wbirq_refcount;
atomic_t vsync_cnt;
atomic_t underrun_cnt;
atomic_t pending_ctlstart_cnt;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index f06ceb7e5f5c..4409408ba3fe 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -348,6 +348,24 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
struct sde_encoder_phys *phys_enc)
{
struct sde_encoder_irq *irq;
+ struct sde_kms *sde_kms = phys_enc->sde_kms;
+ int ret = 0;
+
+ mutex_lock(&sde_kms->vblank_ctl_global_lock);
+
+ if (atomic_read(&phys_enc->vblank_refcount)) {
+ SDE_ERROR(
+ "vblank_refcount mismatch detected, try to reset %d\n",
+ atomic_read(&phys_enc->vblank_refcount));
+ ret = sde_encoder_helper_unregister_irq(phys_enc,
+ INTR_IDX_RDPTR);
+ if (ret)
+ SDE_ERROR(
+ "control vblank irq registration error %d\n",
+ ret);
+
+ }
+ atomic_set(&phys_enc->vblank_refcount, 0);
irq = &phys_enc->irq[INTR_IDX_CTL_START];
irq->hw_idx = phys_enc->hw_ctl->idx;
@@ -368,6 +386,8 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
irq = &phys_enc->irq[INTR_IDX_AUTOREFRESH_DONE];
irq->hw_idx = phys_enc->hw_pp->idx;
irq->irq_idx = -EINVAL;
+
+ mutex_unlock(&sde_kms->vblank_ctl_global_lock);
}
static void sde_encoder_phys_cmd_cont_splash_mode_set(
@@ -674,13 +694,15 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
to_sde_encoder_phys_cmd(phys_enc);
int ret = 0;
int refcount;
+ struct sde_kms *sde_kms;
if (!phys_enc || !phys_enc->hw_pp) {
SDE_ERROR("invalid encoder\n");
return -EINVAL;
}
+ sde_kms = phys_enc->sde_kms;
- mutex_lock(phys_enc->vblank_ctl_lock);
+ mutex_lock(&sde_kms->vblank_ctl_global_lock);
refcount = atomic_read(&phys_enc->vblank_refcount);
/* Slave encoders don't report vblank */
@@ -698,11 +720,17 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
enable, refcount);
- if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
+ if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1) {
ret = sde_encoder_helper_register_irq(phys_enc, INTR_IDX_RDPTR);
- else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
+ if (ret)
+ atomic_dec_return(&phys_enc->vblank_refcount);
+ } else if (!enable &&
+ atomic_dec_return(&phys_enc->vblank_refcount) == 0) {
ret = sde_encoder_helper_unregister_irq(phys_enc,
INTR_IDX_RDPTR);
+ if (ret)
+ atomic_inc_return(&phys_enc->vblank_refcount);
+ }
end:
if (ret) {
@@ -714,7 +742,7 @@ end:
enable, refcount, SDE_EVTLOG_ERROR);
}
- mutex_unlock(phys_enc->vblank_ctl_lock);
+ mutex_unlock(&sde_kms->vblank_ctl_global_lock);
return ret;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index 4bbcb3ae567c..1042e207274b 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -904,7 +904,8 @@ static void sde_encoder_phys_wb_irq_ctrl(
{
struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys);
- int index = 0;
+ int index = 0, refcount;
+ int ret = 0;
if (!wb_enc)
return;
@@ -912,17 +913,33 @@ static void sde_encoder_phys_wb_irq_ctrl(
if (wb_enc->bypass_irqreg)
return;
- if (enable) {
- sde_encoder_helper_register_irq(phys, INTR_IDX_WB_DONE);
- if (phys->in_clone_mode) {
+ refcount = atomic_read(&phys->wbirq_refcount);
+
+ if (!enable && !refcount)
+ return;
+
+ SDE_EVT32(DRMID(phys->parent), enable,
+ atomic_read(&phys->wbirq_refcount));
+
+ if (enable && atomic_inc_return(&phys->wbirq_refcount) == 1) {
+ ret = sde_encoder_helper_register_irq(phys, INTR_IDX_WB_DONE);
+ if (ret)
+ atomic_dec_return(&phys->wbirq_refcount);
+
+ } else if (!enable &&
+ atomic_dec_return(&phys->wbirq_refcount) == 0) {
+ ret = sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE);
+ if (ret)
+ atomic_inc_return(&phys->wbirq_refcount);
+ }
+
+ if (phys->in_clone_mode) {
+ if (enable) {
for (index = 0; index < CRTC_DUAL_MIXERS; index++)
sde_encoder_helper_register_irq(phys,
index ? INTR_IDX_PP3_OVFL
: INTR_IDX_PP2_OVFL);
- }
- } else {
- sde_encoder_helper_unregister_irq(phys, INTR_IDX_WB_DONE);
- if (phys->in_clone_mode) {
+ } else {
for (index = 0; index < CRTC_DUAL_MIXERS; index++)
sde_encoder_helper_unregister_irq(phys,
index ? INTR_IDX_PP3_OVFL
@@ -1349,15 +1366,17 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc)
/* reset h/w before final flush */
if (phys_enc->hw_ctl->ops.clear_pending_flush)
phys_enc->hw_ctl->ops.clear_pending_flush(phys_enc->hw_ctl);
- if (sde_encoder_helper_reset_mixers(phys_enc, wb_enc->fb_disable))
+ if (sde_encoder_helper_reset_mixers(phys_enc, NULL))
goto exit;
phys_enc->enable_state = SDE_ENC_DISABLING;
sde_encoder_phys_wb_prepare_for_kickoff(phys_enc, NULL);
+ sde_encoder_phys_wb_irq_ctrl(phys_enc, true);
if (phys_enc->hw_ctl->ops.trigger_flush)
phys_enc->hw_ctl->ops.trigger_flush(phys_enc->hw_ctl);
sde_encoder_helper_trigger_start(phys_enc);
sde_encoder_phys_wb_wait_for_commit_done(phys_enc);
+ sde_encoder_phys_wb_irq_ctrl(phys_enc, false);
exit:
phys_enc->enable_state = SDE_ENC_DISABLED;
wb_enc->crtc = NULL;
@@ -1576,6 +1595,7 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init(
phys_enc->enc_spinlock = p->enc_spinlock;
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
+ atomic_set(&phys_enc->wbirq_refcount, 0);
irq = &phys_enc->irq[INTR_IDX_WB_DONE];
INIT_LIST_HEAD(&irq->cb.list);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index baec526f4d31..750cd5794cbd 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -3269,6 +3269,8 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->perf.min_prefill_lines = 24;
sde_cfg->vbif_qos_nlvl = 8;
sde_cfg->ts_prefill_rev = 2;
+ sde_cfg->sui_misr_supported = true;
+ sde_cfg->sui_block_xin_mask = 0x3F71;
} else {
SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
sde_cfg->perf.min_prefill_lines = 0xffff;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dsc.c b/drivers/gpu/drm/msm/sde/sde_hw_dsc.c
index 9fd3c25b4d49..4fa13bd8fb59 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dsc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dsc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -65,7 +65,7 @@ static void sde_hw_dsc_config(struct sde_hw_dsc *hw_dsc,
initial_lines += 1;
data |= (initial_lines << 20);
- data |= ((dsc->slice_last_group_size - 1) << 18);
+ data |= (dsc->slice_last_group_size << 18);
/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
lsb = dsc->bpp % 4;
bpp = dsc->bpp / 4;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index ed0e7b818da7..6cbd663bec09 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -3291,6 +3291,13 @@ static int sde_kms_hw_init(struct msm_kms *kms)
if (rc)
SDE_DEBUG("sde splash data fetch failed: %d\n", rc);
+ for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
+ priv->phandle.data_bus_handle[i].ab_rt =
+ SDE_POWER_HANDLE_CONT_SPLASH_BUS_AB_QUOTA;
+ priv->phandle.data_bus_handle[i].ib_rt =
+ SDE_POWER_HANDLE_CONT_SPLASH_BUS_IB_QUOTA;
+ }
+
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
true);
if (rc) {
@@ -3420,6 +3427,8 @@ static int sde_kms_hw_init(struct msm_kms *kms)
dev->mode_config.max_height = sde_kms->catalog->max_display_height;
mutex_init(&sde_kms->secure_transition_lock);
+ mutex_init(&sde_kms->vblank_ctl_global_lock);
+
atomic_set(&sde_kms->detach_sec_cb, 0);
atomic_set(&sde_kms->detach_all_cb, 0);
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index fb79fe79436b..2f1d4181998b 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -288,6 +288,7 @@ struct sde_kms {
atomic_t detach_sec_cb;
atomic_t detach_all_cb;
struct mutex secure_transition_lock;
+ struct mutex vblank_ctl_global_lock;
bool first_kickoff;
};
diff --git a/drivers/gpu/drm/msm/sde_hdcp_1x.c b/drivers/gpu/drm/msm/sde_hdcp_1x.c
index 2c7f52c7970b..53e20e261ebd 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_1x.c
+++ b/drivers/gpu/drm/msm/sde_hdcp_1x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1263,6 +1263,8 @@ static void sde_hdcp_1x_off(void *input)
hdcp->sink_r0_ready = false;
+ hdcp1_unload_app();
+
pr_debug("%s: HDCP: Off\n", SDE_HDCP_STATE_NAME);
} /* hdcp_1x_off */
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 68a7c2a2f987..699aff56bc4f 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -2245,7 +2245,7 @@ static int a5xx_microcode_load(struct adreno_device *adreno_dev)
desc.args[1] = 13;
desc.arginfo = SCM_ARGS(2);
- ret = scm_call2(SCM_SIP_FNID(SCM_SVC_BOOT, 0xA), &desc);
+ ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, 0xA), &desc);
if (ret) {
pr_err("SCM resume call failed with error %d\n", ret);
return ret;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2a149ac87ed1..06403a87bec8 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -64,7 +64,7 @@ static const char * const clocks[] = {
"ahb_clk"
};
-static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
+static unsigned long ib_votes[KGSL_MAX_BUSLEVELS];
static int last_vote_buslevel;
static int max_vote_buslevel;
@@ -127,7 +127,7 @@ static void _record_pwrevent(struct kgsl_device *device,
/**
* kgsl_get_bw() - Return latest msm bus IB vote
*/
-static unsigned int kgsl_get_bw(void)
+static unsigned long kgsl_get_bw(void)
{
return ib_votes[last_vote_buslevel];
}
@@ -141,8 +141,8 @@ static unsigned int kgsl_get_bw(void)
static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr,
unsigned long *ab)
{
- unsigned int ib = ib_votes[last_vote_buslevel];
- unsigned int max_bw = ib_votes[max_vote_buslevel];
+ unsigned long ib = ib_votes[last_vote_buslevel];
+ unsigned long max_bw = ib_votes[max_vote_buslevel];
if (!ab)
return;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 0ed17d859080..099daaf8403a 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -335,10 +335,8 @@ int kgsl_snapshot_get_object(struct kgsl_snapshot *snapshot,
entry = kgsl_sharedmem_find(process, gpuaddr);
- if (entry == NULL) {
- KGSL_CORE_ERR("Unable to find GPU buffer 0x%016llX\n", gpuaddr);
+ if (entry == NULL)
return -EINVAL;
- }
/* We can't freeze external memory, because we don't own it */
if (entry->memdesc.flags & KGSL_MEMFLAGS_USERMEM_MASK)
diff --git a/drivers/hwtracing/coresight/coresight-ost.c b/drivers/hwtracing/coresight/coresight-ost.c
index 340c58944424..aadc5885afbc 100644
--- a/drivers/hwtracing/coresight/coresight-ost.c
+++ b/drivers/hwtracing/coresight/coresight-ost.c
@@ -14,6 +14,7 @@
#include <linux/bitmap.h>
#include <linux/io.h>
#include "coresight-ost.h"
+#include <linux/coresight-stm.h>
#define STM_USERSPACE_HEADER_SIZE (8)
#define STM_USERSPACE_MAGIC1_VAL (0xf0)
@@ -139,7 +140,7 @@ static int stm_trace_data_header(void __iomem *addr)
}
static int stm_trace_data(void __iomem *ch_addr, uint32_t flags,
- const void *data, uint32_t size)
+ uint32_t entity_id, const void *data, uint32_t size)
{
void __iomem *addr;
int len = 0;
@@ -148,8 +149,10 @@ static int stm_trace_data(void __iomem *ch_addr, uint32_t flags,
addr = (void __iomem *)(ch_addr +
stm_channel_off(STM_PKT_TYPE_DATA, flags));
- /* send the data header */
- len += stm_trace_data_header(addr);
+ /* OST_ENTITY_DIAG no need to send the data header */
+ if (entity_id != OST_ENTITY_DIAG)
+ len += stm_trace_data_header(addr);
+
/* send the actual data */
len += stm_ost_send(addr, data, size);
@@ -192,7 +195,7 @@ static inline int __stm_trace(uint32_t flags, uint8_t entity_id,
proto_id);
/* send the payload data */
- len += stm_trace_data(ch_addr, flags, data, size);
+ len += stm_trace_data(ch_addr, flags, entity_id, data, size);
/* send the ost tail */
len += stm_trace_ost_tail(ch_addr, flags);
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 36c84df078c7..30815df2ba6b 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -369,8 +369,9 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
unsigned int order = __fls(order_mask);
order_size = 1U << order;
- page = alloc_pages((order_mask - order_size) ?
- gfp | __GFP_NORETRY : gfp, order);
+ page = alloc_pages(order ?
+ (gfp | __GFP_NORETRY) &
+ ~__GFP_RECLAIM : gfp, order);
if (!page)
continue;
if (!order)
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index 7e6287c986ef..31482f99f37f 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -546,12 +546,22 @@ static void *fast_smmu_alloc(struct device *dev, size_t size,
av8l_fast_iopte *ptep;
unsigned long flags;
struct sg_mapping_iter miter;
- unsigned int count = ALIGN(size, SZ_4K) >> PAGE_SHIFT;
+ size_t count = ALIGN(size, SZ_4K) >> PAGE_SHIFT;
int prot = IOMMU_READ | IOMMU_WRITE; /* TODO: extract from attrs */
bool is_coherent = is_dma_coherent(dev, attrs);
pgprot_t remap_prot = __get_dma_pgprot(attrs, PAGE_KERNEL, is_coherent);
struct page **pages;
+ /*
+ * sg_alloc_table_from_pages accepts unsigned int value for count
+ * so check count doesn't exceed UINT_MAX.
+ */
+
+ if (count > UINT_MAX) {
+ dev_err(dev, "count: %zx exceeds UNIT_MAX\n", count);
+ return NULL;
+ }
+
prot = __get_iommu_pgprot(attrs, prot, is_coherent);
*handle = DMA_ERROR_CODE;
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 2dcac176812c..87a1244206ba 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -1395,7 +1395,7 @@ static ssize_t iommu_debug_test_virt_addr_read(struct file *file,
else
snprintf(buf, buf_len, "0x%pK\n", test_virt_addr);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1518,7 +1518,7 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf,
else
snprintf(buf, sizeof(buf), "pte=%016llx\n", pte);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1587,7 +1587,7 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
snprintf(buf, 100, "%pa\n", &phys);
}
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1640,7 +1640,7 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf,
else
snprintf(buf, sizeof(buf), "%pa\n", &phys);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
@@ -1873,7 +1873,7 @@ static ssize_t iommu_debug_dma_map_read(struct file *file, char __user *ubuf,
iova = ddev->iova;
snprintf(buf, sizeof(buf), "%pa\n", &iova);
- buflen = min(count, strlen(buf)+1);
+ buflen = min(count, strlen(buf));
if (copy_to_user(ubuf, buf, buflen)) {
pr_err("Couldn't copy_to_user\n");
retval = -EFAULT;
diff --git a/drivers/leds/leds-qpnp-vibrator.c b/drivers/leds/leds-qpnp-vibrator.c
index cc2615daf1c1..c428bfb386b9 100644
--- a/drivers/leds/leds-qpnp-vibrator.c
+++ b/drivers/leds/leds-qpnp-vibrator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -314,6 +314,13 @@ static ssize_t qpnp_vib_get_state(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", !!chip->reg_en_ctl);
}
+static ssize_t qpnp_vib_set_state(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ /* At present, nothing to do with setting state */
+ return count;
+}
+
static ssize_t qpnp_vib_get_duration(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -391,7 +398,6 @@ static ssize_t qpnp_vib_set_activate(struct device *dev,
(vib->vib_play_ms % 1000) * 1000000),
HRTIMER_MODE_REL);
}
- vib->vib_play_ms = 0;
mutex_unlock(&vib->lock);
schedule_work(&vib->work);
@@ -399,7 +405,7 @@ static ssize_t qpnp_vib_set_activate(struct device *dev,
}
static struct device_attribute qpnp_vib_attrs[] = {
- __ATTR(state, 0444, qpnp_vib_get_state, NULL),
+ __ATTR(state, 0664, qpnp_vib_get_state, qpnp_vib_set_state),
__ATTR(duration, 0664, qpnp_vib_get_duration, qpnp_vib_set_duration),
__ATTR(activate, 0664, qpnp_vib_get_activate, qpnp_vib_set_activate),
};
diff --git a/drivers/leds/leds-qti-tri-led.c b/drivers/leds/leds-qti-tri-led.c
index c303893e1a28..c49465532f83 100644
--- a/drivers/leds/leds-qti-tri-led.c
+++ b/drivers/leds/leds-qti-tri-led.c
@@ -43,14 +43,14 @@
#define PWM_PERIOD_DEFAULT_NS 1000000
struct pwm_setting {
- u32 pre_period_ns;
- u32 period_ns;
- u32 duty_ns;
+ u64 pre_period_ns;
+ u64 period_ns;
+ u64 duty_ns;
};
struct led_setting {
- u32 on_ms;
- u32 off_ms;
+ u64 on_ms;
+ u64 off_ms;
enum led_brightness brightness;
bool blink;
bool breath;
@@ -164,24 +164,16 @@ static int __tri_led_set(struct qpnp_led_dev *led)
static int qpnp_tri_led_set(struct qpnp_led_dev *led)
{
- u32 on_ms, off_ms, period_ns, duty_ns;
+ u64 on_ms, off_ms, period_ns, duty_ns;
enum led_brightness brightness = led->led_setting.brightness;
int rc = 0;
if (led->led_setting.blink) {
on_ms = led->led_setting.on_ms;
off_ms = led->led_setting.off_ms;
- if (on_ms > INT_MAX / NSEC_PER_MSEC)
- duty_ns = INT_MAX - 1;
- else
- duty_ns = on_ms * NSEC_PER_MSEC;
- if (on_ms + off_ms > INT_MAX / NSEC_PER_MSEC) {
- period_ns = INT_MAX;
- duty_ns = (period_ns / (on_ms + off_ms)) * on_ms;
- } else {
- period_ns = (on_ms + off_ms) * NSEC_PER_MSEC;
- }
+ duty_ns = on_ms * NSEC_PER_MSEC;
+ period_ns = (on_ms + off_ms) * NSEC_PER_MSEC;
if (period_ns < duty_ns && duty_ns != 0)
period_ns = duty_ns + 1;
@@ -191,15 +183,14 @@ static int qpnp_tri_led_set(struct qpnp_led_dev *led)
if (brightness == LED_OFF)
duty_ns = 0;
- else if (period_ns > INT_MAX / brightness)
- duty_ns = (period_ns / LED_FULL) * brightness;
- else
- duty_ns = (period_ns * brightness) / LED_FULL;
+
+ duty_ns = period_ns * brightness;
+ do_div(duty_ns, LED_FULL);
if (period_ns < duty_ns && duty_ns != 0)
period_ns = duty_ns + 1;
}
- dev_dbg(led->chip->dev, "PWM settings for %s led: period = %dns, duty = %dns\n",
+ dev_dbg(led->chip->dev, "PWM settings for %s led: period = %lluns, duty = %lluns\n",
led->cdev.name, period_ns, duty_ns);
led->pwm_setting.duty_ns = duty_ns;
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
index e4ec08b41504..f753b34514bd 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -166,8 +166,7 @@ int cam_cdm_acquire(struct cam_cdm_acquire_data *data)
struct cam_hw_intf *hw;
uint32_t hw_index = 0;
- if ((!data) || (!data->identifier) || (!data->base_array) ||
- (!data->base_array_cnt))
+ if (!data || !data->base_array_cnt)
return -EINVAL;
if (get_cdm_mgr_refcount()) {
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
index 9021ecabb27c..b2575825f983 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_virtual_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -118,6 +118,14 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if ((!rc) && (vaddr_ptr) && (len) &&
(len >= cdm_cmd->cmd[i].offset)) {
+
+
+ if ((len - cdm_cmd->cmd[i].offset) <=
+ cdm_cmd->cmd[i].len) {
+ CAM_ERR(CAM_CDM, "Not enough buffer");
+ rc = -EINVAL;
+ break;
+ }
CAM_DBG(CAM_CDM,
"hdl=%x vaddr=%pK offset=%d cmdlen=%d:%zu",
cdm_cmd->cmd[i].bl_addr.mem_handle,
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index 8021f12934a9..dc16733f3bbb 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -275,6 +275,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
+ size_t remain_len = 0;
int32_t i = 0, j = 0;
if (!ctx || !cmd) {
@@ -323,12 +324,21 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
goto free_req;
}
+ remain_len = len;
+ if ((len < sizeof(struct cam_packet)) ||
+ ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_CTXT, "invalid buff length: %zu or offset", len);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)cmd->offset;
packet = (struct cam_packet *) ((uint8_t *)packet_addr +
(uint32_t)cmd->offset);
/* preprocess the configuration */
memset(&cfg, 0, sizeof(cfg));
cfg.packet = packet;
+ cfg.remain_len = remain_len;
cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
cfg.max_hw_update_entries = CAM_CTX_CFG_MAX;
cfg.num_hw_update_entries = req->num_hw_update_entries;
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
index 54b0f4d63bf8..656fcfac3996 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -152,6 +152,7 @@ struct cam_hw_mgr_dump_pf_data {
* struct cam_hw_prepare_update_args - Payload for prepare command
*
* @packet: CSL packet from user mode driver
+ * @remain_len Remaining length of CPU buffer after config offset
* @ctxt_to_hw_map: HW context from the acquire
* @max_hw_update_entries: Maximum hardware update entries supported
* @hw_update_entries: Actual hardware update configuration (returned)
@@ -168,6 +169,7 @@ struct cam_hw_mgr_dump_pf_data {
*/
struct cam_hw_prepare_update_args {
struct cam_packet *packet;
+ size_t remain_len;
void *ctxt_to_hw_map;
uint32_t max_hw_update_entries;
struct cam_hw_update_entry *hw_update_entries;
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index 7e78f458ec2b..c72893561980 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,8 @@
static struct cam_fd_hw_mgr g_fd_hw_mgr;
-static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet)
+static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet,
+ size_t remain_len)
{
struct cam_cmd_buf_desc *cmd_desc = NULL;
int i, rc;
@@ -50,7 +51,7 @@ static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet)
packet->patch_offset, packet->num_patches,
packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index);
- if (cam_packet_util_validate_packet(packet)) {
+ if (cam_packet_util_validate_packet(packet, remain_len)) {
CAM_ERR(CAM_FD, "invalid packet:%d %d %d %d %d",
packet->kmd_cmd_buf_index,
packet->num_cmd_buf, packet->cmd_buf_offset,
@@ -608,7 +609,13 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
rc);
return rc;
}
-
+ if (io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_FD,
+ "Invalid cpu buf %d %d %d",
+ io_cfg[i].direction,
+ io_cfg[i].resource_type, plane);
+ return -EINVAL;
+ }
cpu_addr[plane] += io_cfg[i].offsets[plane];
}
@@ -1559,7 +1566,8 @@ static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv,
goto error;
}
- rc = cam_fd_mgr_util_packet_validate(prepare->packet);
+ rc = cam_fd_mgr_util_packet_validate(prepare->packet,
+ prepare->remain_len);
if (rc) {
CAM_ERR(CAM_FD, "Error in packet validation %d", rc);
goto error;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index ca8bb3c8d543..94e259311326 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3698,6 +3698,9 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
packet = prepare_args->packet;
+ if (cam_packet_util_validate_packet(packet, prepare_args->remain_len))
+ return -EINVAL;
+
rc = cam_icp_mgr_pkt_validation(packet);
if (rc) {
mutex_unlock(&ctx_data->ctx_mutex);
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index aaa172deea97..69fa90693c5d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2035,6 +2035,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
+ size_t remain_len = 0;
struct cam_hw_prepare_update_args cfg;
struct cam_req_mgr_add_request add_req;
struct cam_isp_context *ctx_isp =
@@ -2069,6 +2070,14 @@ static int __cam_isp_ctx_config_dev_in_top_state(
goto free_req;
}
+ remain_len = len;
+ if ((len < sizeof(struct cam_packet)) ||
+ ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_ISP, "invalid buff length: %zu or offset", len);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)cmd->offset;
packet = (struct cam_packet *)(packet_addr + (uint32_t)cmd->offset);
CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle);
CAM_DBG(CAM_ISP, "packet address is 0x%zx", packet_addr);
@@ -2082,6 +2091,7 @@ 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;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index d29506fb8a21..45f88b3e79da 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -715,7 +715,8 @@ 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->res_id = vfe_out_res_id;
- ife_out_res->res_type = CAM_ISP_RESOURCE_VFE_OUT;
+ 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;
return 0;
@@ -805,7 +806,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel(
ife_out_res->hw_res[j]->res_id);
}
- ife_out_res->res_type = CAM_ISP_RESOURCE_VFE_OUT;
+ 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;
@@ -918,7 +920,8 @@ 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 = vfe_acquire.rsrc_type;
+ 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;
@@ -1150,7 +1153,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp(
goto end;
}
- csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH;
+ csid_res->res_type = (enum cam_ife_hw_mgr_res_type)
+ CAM_ISP_RESOURCE_PIX_PATH;
csid_res->res_id = CAM_IFE_PIX_PATH_RES_IPP;
if (in_port->usage_type)
@@ -1568,6 +1572,14 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv,
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);
@@ -2663,7 +2675,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map;
hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv;
- rc = cam_packet_util_validate_packet(prepare->packet);
+ rc = cam_packet_util_validate_packet(prepare->packet,
+ prepare->remain_len);
if (rc)
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index f652256d3dc5..abf208cb0361 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -105,7 +105,7 @@ static int cam_isp_update_dual_config(
struct cam_isp_hw_dual_isp_update_args dual_isp_update_args;
uint32_t outport_id;
uint32_t ports_plane_idx;
- size_t len = 0;
+ size_t len = 0, remain_len = 0;
uint32_t *cpu_addr;
uint32_t i, j;
@@ -117,9 +117,22 @@ static int cam_isp_update_dual_config(
if (rc)
return rc;
+ if ((len < sizeof(struct cam_isp_dual_config)) ||
+ (cmd_desc->offset >=
+ (len - sizeof(struct cam_isp_dual_config)))) {
+ CAM_ERR(CAM_UTIL, "not enough buffer provided");
+ return -EINVAL;
+ }
+ remain_len = len - cmd_desc->offset;
cpu_addr += (cmd_desc->offset / 4);
dual_config = (struct cam_isp_dual_config *)cpu_addr;
+ if ((dual_config->num_ports *
+ sizeof(struct cam_isp_dual_stripe_config)) >
+ (remain_len - offsetof(struct cam_isp_dual_config, stripes))) {
+ CAM_ERR(CAM_UTIL, "not enough buffer for all the dual configs");
+ return -EINVAL;
+ }
for (i = 0; i < dual_config->num_ports; i++) {
if (i >= CAM_ISP_IFE_OUT_RES_MAX) {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 9ffd923b55cb..a4c0cb10863e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2634,18 +2634,20 @@ static int cam_ife_csid_sof_irq_debug(
if (*((uint32_t *)cmd_args) == 1)
sof_irq_enable = true;
- val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
- csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
+ if (csid_reg->ipp_reg) {
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
- if (val) {
- if (sof_irq_enable)
- val |= CSID_PATH_INFO_INPUT_SOF;
- else
- val &= ~CSID_PATH_INFO_INPUT_SOF;
+ 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_ipp_irq_mask_addr);
- val = 0;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
+ val = 0;
+ }
}
for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++) {
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 7f0199f6e119..77fea6bfbc06 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -275,6 +275,12 @@ static int cam_jpeg_insert_cdm_change_base(
"unable to get src buf info for cmd buf: %d", rc);
return rc;
}
+
+ if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >=
+ ch_base_len) {
+ CAM_ERR(CAM_JPEG, "Not enough buf");
+ return -EINVAL;
+ }
CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d",
(void *)iova_addr, ch_base_len,
config_args->hw_update_entries[CAM_JPEG_CHBASE].offset);
@@ -713,7 +719,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
return -EINVAL;
}
- rc = cam_packet_util_validate_packet(packet);
+ rc = cam_packet_util_validate_packet(packet, prepare_args->remain_len);
if (rc) {
CAM_ERR(CAM_JPEG, "invalid packet %d", rc);
return rc;
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index eecba3972875..c6250327b640 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -83,7 +83,8 @@ static int cam_lrme_mgr_util_get_device(struct cam_lrme_hw_mgr *hw_mgr,
return 0;
}
-static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet)
+static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet,
+ size_t remain_len)
{
struct cam_cmd_buf_desc *cmd_desc = NULL;
int i, rc;
@@ -105,7 +106,7 @@ static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet)
packet->patch_offset, packet->num_patches,
packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index);
- if (cam_packet_util_validate_packet(packet)) {
+ if (cam_packet_util_validate_packet(packet, remain_len)) {
CAM_ERR(CAM_LRME, "invalid packet:%d %d %d %d %d",
packet->kmd_cmd_buf_index,
packet->num_cmd_buf, packet->cmd_buf_offset,
@@ -166,13 +167,6 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
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_LRME, "Invalid number of buffers %d %d %d",
- num_in_buf, num_out_buf, io_buf_size);
- return -EINVAL;
- }
-
memset(io_addr, 0, sizeof(io_addr));
for (plane = 0; plane < CAM_PACKET_MAX_PLANES; plane++) {
if (!io_cfg[i].mem_handle[plane])
@@ -186,6 +180,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
return -ENOMEM;
}
+ if ((size_t)io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_LRME, "Invalid plane offset: %zu",
+ (size_t)io_cfg[i].offsets[plane]);
+ return -EINVAL;
+ }
+
io_addr[plane] += io_cfg[i].offsets[plane];
CAM_DBG(CAM_LRME, "IO Address[%d][%d] : %llu",
@@ -194,6 +194,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
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 =
@@ -209,6 +215,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
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 =
@@ -841,7 +853,7 @@ static int cam_lrme_mgr_hw_prepare_update(void *hw_mgr_priv,
goto error;
}
- rc = cam_lrme_mgr_util_packet_validate(args->packet);
+ rc = cam_lrme_mgr_util_packet_validate(args->packet, args->remain_len);
if (rc) {
CAM_ERR(CAM_LRME, "Error in packet validation %d", rc);
goto error;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index f2c243e8c7a9..66142dbf3f74 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,6 +23,7 @@
#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_map_cpu_va(struct ion_handle *hdl,
uintptr_t *vaddr,
@@ -108,6 +109,7 @@ int cam_mem_mgr_init(void)
tbl.bufq[i].buf_handle = -1;
}
mutex_init(&tbl.m_lock);
+ atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED);
return rc;
bitmap_fail:
@@ -151,6 +153,11 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
{
int rc = 0, idx;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "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;
@@ -191,6 +198,10 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
uintptr_t kvaddr = 0;
size_t klen = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
if (!buf_handle || !vaddr_ptr || !len)
return -EINVAL;
@@ -242,6 +253,11 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
uint32_t ion_cache_ops;
unsigned long ion_flag = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd)
return -EINVAL;
@@ -518,6 +534,11 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)
dma_addr_t hw_vaddr = 0;
size_t len;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd) {
CAM_ERR(CAM_MEM, " Invalid argument");
return -EINVAL;
@@ -616,6 +637,11 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd)
dma_addr_t hw_vaddr = 0;
size_t len = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd || (cmd->fd < 0)) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
@@ -801,6 +827,7 @@ static int cam_mem_mgr_cleanup_table(void)
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);
@@ -889,6 +916,11 @@ 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_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
@@ -936,6 +968,11 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp || !out) {
CAM_ERR(CAM_MEM, "Invalid params");
return -EINVAL;
@@ -1054,6 +1091,11 @@ 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_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
@@ -1103,6 +1145,11 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp,
int32_t smmu_hdl = 0;
int32_t num_hdl = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp || !out) {
CAM_ERR(CAM_MEM, "Invalid param(s)");
return -EINVAL;
@@ -1195,6 +1242,11 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp)
int rc;
int32_t smmu_hdl;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h
index 92c366d723f9..73f0eb3d3425 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,12 @@
#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,
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index 4c4afc1841f8..8de297db8ff7 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -2432,16 +2432,17 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
return -EINVAL;
}
+ mutex_lock(&g_crm_core_dev->crm_lock);
+
/* session hdl's priv data is cam session struct */
cam_session = (struct cam_req_mgr_core_session *)
cam_get_device_priv(link_info->session_hdl);
if (!cam_session) {
CAM_DBG(CAM_CRM, "NULL pointer");
+ mutex_unlock(&g_crm_core_dev->crm_lock);
return -EINVAL;
}
- mutex_lock(&g_crm_core_dev->crm_lock);
-
/* Allocate link struct and map it with session's request queue */
link = __cam_req_mgr_reserve_link(cam_session);
if (!link) {
@@ -2778,7 +2779,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
goto end;
}
- if (control->num_links > MAX_LINKS_PER_SESSION) {
+ if ((control->num_links <= 0) ||
+ (control->num_links > MAX_LINKS_PER_SESSION)) {
CAM_ERR(CAM_CRM, "Invalid number of links %d",
control->num_links);
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index c14a74d7c862..8519115cb437 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
#include "cam_trace.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
int32_t cam_actuator_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -214,12 +215,12 @@ static int32_t cam_actuator_i2c_modes_util(
}
int32_t cam_actuator_slaveInfo_pkt_parser(struct cam_actuator_ctrl_t *a_ctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info;
- if (!a_ctrl || !cmd_buf) {
+ if (!a_ctrl || !cmd_buf || (len < sizeof(struct cam_cmd_i2c_info))) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
@@ -413,6 +414,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
int32_t i = 0;
uint32_t total_cmd_buf_in_bytes = 0;
size_t len_of_buff = 0;
+ size_t remain_len = 0;
uint32_t *offset = NULL;
uint32_t *cmd_buf = NULL;
uintptr_t generic_ptr;
@@ -449,16 +451,27 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
return rc;
}
- if (config.offset > len_of_buff) {
+ remain_len = len_of_buff;
+ if ((sizeof(struct cam_packet) > len_of_buff) ||
+ ((size_t)config.offset >= len_of_buff -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_ACTUATOR,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buff);
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buff);
return -EINVAL;
}
- csl_packet =
- (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
- CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
+ remain_len -= (size_t)config.offset;
+ csl_packet = (struct cam_packet *)
+ (generic_ptr + (uint32_t)config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_ACTUATOR, "Invalid packet params");
+ return -EINVAL;
+ }
+
+ CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_ACTUATOR_PACKET_OPCODE_INIT:
@@ -482,6 +495,14 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_ERR(CAM_ACTUATOR, "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_ACTUATOR,
+ "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;
@@ -490,7 +511,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR,
"Received slave info buffer");
rc = cam_actuator_slaveInfo_pkt_parser(
- a_ctrl, cmd_buf);
+ a_ctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to parse slave info: %d", rc);
@@ -504,7 +525,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- power_info);
+ power_info, remain_len);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"Failed:parse power settings: %d",
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index cb0bcc292037..9a1188537dd7 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,8 @@
#include "cam_csiphy_dev.h"
#include "cam_csiphy_soc.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
+
#include <soc/qcom/scm.h>
#include <cam_mem_mgr.h>
@@ -31,6 +33,7 @@ static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev,
bool protect, int32_t offset)
{
struct scm_desc desc = {0};
+ int result = -1;
if (offset >= CSIPHY_MAX_INSTANCES)
return -EINVAL;
@@ -38,8 +41,19 @@ static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev,
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)) {
+ /*
+ * If SECURE_SYSCALL_ID_2 is not supported
+ * then fallback to SECURE_SYSCALL_ID
+ */
+ result = scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID_2),
+ &desc);
+ if (result == -EOPNOTSUPP) {
+ desc.args[1] = csiphy_dev->soc_info.index;
+ CAM_ERR(CAM_CSIPHY, "SCM CALL 7 not supported fallback to 6");
+ result = scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS,
+ SECURE_SYSCALL_ID), &desc);
+ }
+ if (result) {
CAM_ERR(CAM_CSIPHY, "scm call to hypervisor failed");
return -EINVAL;
}
@@ -156,6 +170,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
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");
@@ -169,16 +184,25 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
return rc;
}
- if (cfg_dev->offset > len) {
+ remain_len = len;
+ if ((sizeof(struct cam_packet) > len) ||
+ ((size_t)cfg_dev->offset >= len - sizeof(struct cam_packet))) {
CAM_ERR(CAM_CSIPHY,
"offset is out of bounds: offset: %lld len: %zu",
cfg_dev->offset, len);
return -EINVAL;
}
+ remain_len -= (size_t)cfg_dev->offset;
csl_packet = (struct cam_packet *)
(generic_ptr + (uint32_t)cfg_dev->offset);
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_CSIPHY, "Invalid packet params");
+ return -EINVAL;
+ }
+
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&csl_packet->payload +
csl_packet->cmd_buf_offset / 4);
@@ -191,6 +215,13 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
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");
+ return -EINVAL;
+ }
+
cmd_buf = (uint32_t *)generic_ptr;
cmd_buf += cmd_desc->offset / 4;
cam_cmd_csiphy_info = (struct cam_csiphy_info *)cmd_buf;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 92bace40be4a..4dce293eb7ab 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
#include "cam_eeprom_soc.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
/**
* cam_eeprom_read_memory() - read map data into buffer
@@ -413,7 +414,7 @@ static int32_t cam_eeprom_update_slaveInfo(struct cam_eeprom_ctrl_t *e_ctrl,
static int32_t cam_eeprom_parse_memory_map(
struct cam_eeprom_memory_block_t *data,
void *cmd_buf, int cmd_length, uint16_t *cmd_length_bytes,
- int *num_map)
+ int *num_map, size_t remain_buf_len)
{
int32_t rc = 0;
int32_t cnt = 0;
@@ -427,8 +428,21 @@ static int32_t cam_eeprom_parse_memory_map(
struct cam_cmd_i2c_continuous_rd *i2c_cont_rd = NULL;
struct cam_cmd_conditional_wait *i2c_poll = NULL;
struct cam_cmd_unconditional_wait *i2c_uncond_wait = NULL;
+ size_t validate_size = 0;
generic_op_code = cmm_hdr->third_byte;
+
+ if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR)
+ validate_size = sizeof(struct cam_cmd_i2c_random_wr);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD)
+ validate_size = sizeof(struct cam_cmd_i2c_continuous_rd);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
+ validate_size = sizeof(struct cam_cmd_unconditional_wait);
+
+ if (remain_buf_len < validate_size) {
+ CAM_ERR(CAM_EEPROM, "not enough buffer");
+ return -EINVAL;
+ }
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
@@ -535,6 +549,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
uint32_t *cmd_buf = NULL;
uintptr_t generic_pkt_addr;
size_t pkt_len = 0;
+ size_t remain_len = 0;
uint32_t total_cmd_buf_in_bytes = 0;
uint32_t processed_cmd_buf_in_bytes = 0;
struct common_header *cmm_hdr = NULL;
@@ -577,13 +592,36 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
CAM_ERR(CAM_EEPROM, "invalid cmd buf");
return -EINVAL;
}
+
+ if ((pkt_len < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (pkt_len -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer");
+ return -EINVAL;
+ }
+ 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");
+ return -EINVAL;
+ }
/* 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");
+ return -EINVAL;
+ }
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");
+ return -EINVAL;
+ }
/* Configure the following map slave address */
map[num_map + 1].saddr = i2c_info->slave_addr;
rc = cam_eeprom_update_slaveInfo(e_ctrl,
@@ -599,7 +637,9 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
cmd_length_in_bytes = total_cmd_buf_in_bytes;
rc = cam_sensor_update_power_settings(cmd_buf,
- cmd_length_in_bytes, power_info);
+ cmd_length_in_bytes, power_info,
+ (remain_len -
+ processed_cmd_buf_in_bytes));
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/
@@ -616,7 +656,9 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
rc = cam_eeprom_parse_memory_map(
&e_ctrl->cal_data, cmd_buf,
total_cmd_buf_in_bytes,
- &cmd_length_in_bytes, &num_map);
+ &cmd_length_in_bytes, &num_map,
+ (remain_len -
+ processed_cmd_buf_in_bytes));
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/sizeof(uint32_t);
@@ -647,6 +689,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
uintptr_t buf_addr;
size_t buf_size;
uint8_t *read_buffer;
+ size_t remain_len = 0;
io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
&csl_packet->payload +
@@ -660,6 +703,17 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
if (io_cfg->direction == CAM_BUF_OUTPUT) {
rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0],
&buf_addr, &buf_size);
+ if (rc) {
+ CAM_ERR(CAM_EEPROM, "Fail in get buffer: %d",
+ rc);
+ return rc;
+ }
+ if (buf_size <= io_cfg->offsets[0]) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer");
+ return -EINVAL;
+ }
+
+ remain_len = buf_size - io_cfg->offsets[0];
CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n",
(void *)buf_addr, buf_size);
@@ -671,7 +725,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
}
read_buffer += io_cfg->offsets[0];
- if (buf_size < e_ctrl->cal_data.num_data) {
+ if (remain_len < e_ctrl->cal_data.num_data) {
CAM_ERR(CAM_EEPROM,
"failed to copy, Invalid size");
return -EINVAL;
@@ -704,6 +758,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
struct cam_config_dev_cmd dev_config;
uintptr_t generic_pkt_addr;
size_t pkt_len;
+ size_t remain_len = 0;
struct cam_packet *csl_packet = NULL;
struct cam_eeprom_soc_private *soc_private =
(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
@@ -723,15 +778,26 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
return rc;
}
- if (dev_config.offset > pkt_len) {
+ remain_len = pkt_len;
+ if ((sizeof(struct cam_packet) > pkt_len) ||
+ ((size_t)dev_config.offset >= pkt_len -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_EEPROM,
- "Offset is out of bound: off: %lld, %zu",
- dev_config.offset, pkt_len);
+ "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_EEPROM, "Invalid packet params");
+ return -EINVAL;
+ }
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_EEPROM_PACKET_OPCODE_INIT:
if (e_ctrl->userspace_probe == false) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
index 8c075f576ce6..182eec325789 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,7 @@
#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)
@@ -438,7 +439,7 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(
flash_ctrl->switch_trigger,
- LED_SWITCH_ON);
+ (enum led_brightness)LED_SWITCH_ON);
return 0;
}
@@ -452,7 +453,7 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger,
- LED_SWITCH_OFF);
+ (enum led_brightness)LED_SWITCH_OFF);
flash_ctrl->flash_state = CAM_FLASH_STATE_START;
return 0;
@@ -591,11 +592,15 @@ static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl,
}
static int32_t cam_flash_slaveInfo_pkt_parser(struct cam_flash_ctrl *fctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+ if (len < sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
if (fctrl->io_master_info.master_type == CCI_MASTER) {
fctrl->io_master_info.cci_client->cci_i2c_master =
fctrl->cci_i2c_master;
@@ -889,6 +894,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
size_t len_of_buffer;
+ size_t remain_len;
struct cam_flash_init *flash_init = NULL;
struct common_header *cmn_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
@@ -920,16 +926,27 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
return rc;
}
- if (config.offset > len_of_buffer) {
+ remain_len = len_of_buffer;
+ if ((sizeof(struct cam_packet) > len_of_buffer) ||
+ ((size_t)config.offset >= len_of_buffer -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_FLASH,
"offset is out of bounds: offset: %lld len: %zu",
config.offset, len_of_buffer);
return -EINVAL;
}
+ remain_len -= (size_t)config.offset;
/* Add offset to the flash csl header */
- csl_packet = (struct cam_packet *)(uintptr_t)(generic_ptr +
- config.offset);
+ csl_packet = (struct cam_packet *)(generic_ptr +
+ (uintptr_t)config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_FLASH, "Invalid packet params");
+ return -EINVAL;
+ }
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
/* INIT packet*/
@@ -954,6 +971,15 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
CAM_ERR(CAM_FLASH, "invalid cmd buf");
return -EINVAL;
}
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset >
+ (len_of_buffer -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "invalid cmd buf length");
+ return -EINVAL;
+ }
+ remain_len = len_of_buffer - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmn_hdr = (struct common_header *)cmd_buf;
@@ -964,6 +990,12 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
total_cmd_buf_in_bytes);
switch (cmn_hdr->cmd_type) {
case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO:
+ if (len_of_buffer <
+ sizeof(struct cam_flash_init)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
+
flash_init = (struct cam_flash_init *)cmd_buf;
fctrl->flash_type = flash_init->flash_type;
cmd_length_in_bytes =
@@ -975,7 +1007,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
break;
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
rc = cam_flash_slaveInfo_pkt_parser(
- fctrl, cmd_buf);
+ fctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_FLASH,
"Failed parsing slave info: rc: %d",
@@ -998,7 +1030,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- &fctrl->power_info);
+ &fctrl->power_info, remain_len);
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/
@@ -1196,6 +1228,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
size_t len_of_buffer;
+ size_t remain_len;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -1230,16 +1263,26 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
return rc;
}
- if (config.offset > len_of_buffer) {
+ remain_len = len_of_buffer;
+ if ((sizeof(struct cam_packet) > len_of_buffer) ||
+ ((size_t)config.offset >= len_of_buffer -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_FLASH,
"offset is out of bounds: offset: %lld len: %zu",
config.offset, len_of_buffer);
return -EINVAL;
}
+ remain_len -= (size_t)config.offset;
/* Add offset to the flash csl header */
- csl_packet =
- (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
+ csl_packet = (struct cam_packet *)(generic_ptr +
+ (uintptr_t)config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_FLASH, "Invalid packet params");
+ return -EINVAL;
+ }
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
@@ -1249,6 +1292,18 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
&generic_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc);
+ return -EINVAL;
+ }
+ 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");
+ return -EINVAL;
+ }
+
+ remain_len = len_of_buffer - cmd_desc->offset;
cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
cmd_desc->offset);
cam_flash_info = (struct cam_flash_init *)cmd_buf;
@@ -1278,8 +1333,23 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE: {
CAM_DBG(CAM_FLASH, "INIT_FIRE Operation");
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
+
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
+ if (!flash_operation_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_operation_info Null");
+ return -EINVAL;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ return -EINVAL;
+ }
fctrl->nrt_info.cmn_attr.count =
flash_operation_info->count;
fctrl->nrt_info.cmn_attr.request_id = 0;
@@ -1327,9 +1397,22 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
&generic_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: 0x%x",
+ cmd_desc->mem_handle);
+ return -EINVAL;
+ }
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "not enough buffer");
+ return -EINVAL;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+
cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
cmd_desc->offset);
-
if (!cmd_buf)
return -EINVAL;
@@ -1347,6 +1430,10 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
flash_data->cmn_attr.is_settings_valid = false;
return 0;
}
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
@@ -1355,6 +1442,11 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
"flash_operation_info Null");
return -EINVAL;
}
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ return -EINVAL;
+ }
flash_data->opcode = flash_operation_info->opcode;
flash_data->cmn_attr.count =
@@ -1378,6 +1470,18 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
&generic_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc);
+ return -EINVAL;
+ }
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
cmd_desc->offset);
cmn_hdr = (struct common_header *)cmd_buf;
@@ -1385,8 +1489,23 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
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");
+ return -EINVAL;
+ }
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
+ if (!flash_operation_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_operation_info Null");
+ return -EINVAL;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ return -EINVAL;
+ }
+
fctrl->nrt_info.cmn_attr.count =
flash_operation_info->count;
fctrl->nrt_info.cmn_attr.request_id = 0;
@@ -1408,6 +1527,10 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
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");
+ return -EINVAL;
+ }
flash_query_info =
(struct cam_flash_query_curr *)cmd_buf;
@@ -1425,7 +1548,22 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
}
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");
+ return -EINVAL;
+ }
flash_rer_info = (struct cam_flash_set_rer *)cmd_buf;
+ if (!flash_rer_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_rer_info Null");
+ return -EINVAL;
+ }
+ if (flash_rer_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ return -EINVAL;
+ }
+
fctrl->nrt_info.cmn_attr.cmd_type =
CAMERA_SENSOR_FLASH_CMD_TYPE_RER;
fctrl->nrt_info.opcode = flash_rer_info->opcode;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index 850b315c26a7..281b25482864 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#include "cam_debug_util.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
int32_t cam_ois_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -256,12 +257,12 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl,
}
static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_ois_info *ois_info;
- if (!o_ctrl || !cmd_buf) {
+ if (!o_ctrl || !cmd_buf || len < sizeof(struct cam_cmd_ois_info)) {
CAM_ERR(CAM_OIS, "Invalid Args");
return -EINVAL;
}
@@ -274,7 +275,8 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
ois_info->slave_addr >> 1;
o_ctrl->ois_fw_flag = ois_info->ois_fw_flag;
o_ctrl->is_ois_calib = ois_info->is_ois_calib;
- memcpy(o_ctrl->ois_name, ois_info->ois_name, 32);
+ memcpy(o_ctrl->ois_name, ois_info->ois_name, OIS_NAME_LEN);
+ o_ctrl->ois_name[OIS_NAME_LEN - 1] = '\0';
o_ctrl->io_master_info.cci_client->retries = 3;
o_ctrl->io_master_info.cci_client->id_map = 0;
memcpy(&(o_ctrl->opcode), &(ois_info->opcode),
@@ -433,6 +435,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
struct cam_cmd_buf_desc *cmd_desc = NULL;
uintptr_t generic_pkt_addr;
size_t pkt_len;
+ size_t remain_len = 0;
struct cam_packet *csl_packet = NULL;
size_t len_of_buff = 0;
uint32_t *offset = NULL, *cmd_buf;
@@ -453,15 +456,26 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
return rc;
}
- if (dev_config.offset > pkt_len) {
+ remain_len = pkt_len;
+ if ((sizeof(struct cam_packet) > pkt_len) ||
+ ((size_t)dev_config.offset >= pkt_len -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_OIS,
"offset is out of bound: off: %lld len: %zu",
dev_config.offset, pkt_len);
return -EINVAL;
}
+ 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;
@@ -485,13 +499,22 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
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);
+ o_ctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"Failed in parsing slave info");
@@ -505,7 +528,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- power_info);
+ power_info, remain_len);
if (rc) {
CAM_ERR(CAM_OIS,
"Failed: parse power settings");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h
index d6f0ec564508..06022ababf4e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,8 @@
#include <linux/dma-contiguous.h>
#include "cam_ois_dev.h"
+#define OIS_NAME_LEN 32
+
/**
* @power_info: power setting info to control the power
*
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index c88e96980ff9..a9985e5e1ff5 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,8 @@
#include "cam_soc_util.h"
#include "cam_trace.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
+
static void cam_sensor_update_req_mgr(
struct cam_sensor_ctrl_t *s_ctrl,
@@ -94,6 +96,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
struct cam_cmd_buf_desc *cmd_desc = NULL;
struct i2c_settings_array *i2c_reg_settings = NULL;
size_t len_of_buff = 0;
+ size_t remain_len = 0;
uint32_t *offset = NULL;
struct cam_config_dev_cmd config;
struct i2c_data_settings *i2c_data = NULL;
@@ -119,12 +122,23 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
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);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)config.offset;
csl_packet = (struct cam_packet *)(generic_ptr +
(uint32_t)config.offset);
- if (config.offset > len_of_buff) {
- CAM_ERR(CAM_SENSOR,
- "offset is out of bounds: off: %lld len: %zu",
- config.offset, len_of_buff);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_SENSOR, "Invalid packet params");
return -EINVAL;
}
@@ -342,7 +356,7 @@ int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info,
int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_sensor_ctrl_t *s_ctrl,
- int32_t cmd_buf_num, int cmd_buf_length)
+ int32_t cmd_buf_num, uint32_t cmd_buf_length, size_t remain_len)
{
int32_t rc = 0;
@@ -351,6 +365,13 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_cmd_i2c_info *i2c_info = NULL;
struct cam_cmd_probe *probe_info;
+ if (remain_len <
+ (sizeof(struct cam_cmd_i2c_info) +
+ sizeof(struct cam_cmd_probe))) {
+ CAM_ERR(CAM_SENSOR,
+ "not enough buffer for cam_cmd_i2c_info");
+ return -EINVAL;
+ }
i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
rc = cam_sensor_update_i2c_info(i2c_info, s_ctrl);
if (rc < 0) {
@@ -369,7 +390,8 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
break;
case 1: {
rc = cam_sensor_update_power_settings(cmd_buf,
- cmd_buf_length, &s_ctrl->sensordata->power_info);
+ cmd_buf_length, &s_ctrl->sensordata->power_info,
+ remain_len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed in updating power settings");
@@ -390,10 +412,11 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
uint32_t *cmd_buf;
void *ptr;
size_t len;
- struct cam_packet *pkt;
- struct cam_cmd_buf_desc *cmd_desc;
+ struct cam_packet *pkt = NULL;
+ struct cam_cmd_buf_desc *cmd_desc = NULL;
uintptr_t cmd_buf1 = 0;
uintptr_t packet = 0;
+ size_t remain_len = 0;
rc = cam_mem_get_cpu_buf(handle,
&packet, &len);
@@ -401,7 +424,19 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
CAM_ERR(CAM_SENSOR, "Failed to get the command Buffer");
return -EINVAL;
}
+
pkt = (struct cam_packet *)packet;
+ if (pkt == NULL) {
+ CAM_ERR(CAM_SENSOR, "packet pos is invalid");
+ return -EINVAL;
+ }
+
+ if ((len < sizeof(struct cam_packet)) ||
+ (pkt->cmd_buf_offset >= (len - sizeof(struct cam_packet)))) {
+ CAM_ERR(CAM_SENSOR, "Not enough buf provided");
+ return -EINVAL;
+ }
+
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&pkt->payload + pkt->cmd_buf_offset/4);
if (cmd_desc == NULL) {
@@ -423,12 +458,23 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
"Failed to parse the command Buffer Header");
return -EINVAL;
}
+ if (cmd_desc[i].offset >= len) {
+ CAM_ERR(CAM_SENSOR,
+ "offset past length of buffer");
+ return -EINVAL;
+ }
+ remain_len = len - cmd_desc[i].offset;
+ if (cmd_desc[i].length > remain_len) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided for cmd");
+ return -EINVAL;
+ }
cmd_buf = (uint32_t *)cmd_buf1;
cmd_buf += cmd_desc[i].offset/4;
ptr = (void *) cmd_buf;
rc = cam_handle_cmd_buffers_for_probe(ptr, s_ctrl,
- i, cmd_desc[i].length);
+ i, cmd_desc[i].length, remain_len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed to parse the command Buffer Header");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 5c1143ece162..061e054c3f9f 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -298,6 +298,8 @@ int cam_sensor_i2c_command_parser(
size_t len_of_buff = 0;
uintptr_t generic_ptr;
uint16_t cmd_length_in_bytes = 0;
+ size_t remain_len = 0;
+ size_t tot_size = 0;
for (i = 0; i < num_cmd_buffers; i++) {
uint32_t *cmd_buf = NULL;
@@ -319,16 +321,34 @@ int cam_sensor_i2c_command_parser(
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
&generic_ptr, &len_of_buff);
- cmd_buf = (uint32_t *)generic_ptr;
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"cmd hdl failed:%d, Err: %d, Buffer_len: %zd",
cmd_desc[i].mem_handle, rc, len_of_buff);
return rc;
}
+
+ remain_len = len_of_buff;
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset >
+ (len_of_buff - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_SENSOR, "buffer provided too small");
+ return -EINVAL;
+ }
+ cmd_buf = (uint32_t *)generic_ptr;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+ if (remain_len < cmd_desc[i].length) {
+ CAM_ERR(CAM_SENSOR, "buffer provided too small");
+ return -EINVAL;
+ }
+
while (byte_cnt < cmd_desc[i].length) {
+ if ((remain_len - byte_cnt) <
+ sizeof(struct common_header)) {
+ CAM_ERR(CAM_SENSOR, "Not enough buffer");
+ return -EINVAL;
+ }
cmm_hdr = (struct common_header *)cmd_buf;
generic_op_code = cmm_hdr->third_byte;
switch (cmm_hdr->cmd_type) {
@@ -338,6 +358,22 @@ int cam_sensor_i2c_command_parser(
*cam_cmd_i2c_random_wr =
(struct cam_cmd_i2c_random_wr *)cmd_buf;
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_i2c_random_wr)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+ 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");
+ return -EINVAL;
+ }
+
rc = cam_sensor_handle_random_write(
cam_cmd_i2c_random_wr,
i2c_reg_settings,
@@ -360,6 +396,24 @@ int cam_sensor_i2c_command_parser(
(struct cam_cmd_i2c_continuous_wr *)
cmd_buf;
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_i2c_continuous_wr)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+
+ tot_size = sizeof(struct i2c_rdwr_header) +
+ sizeof(cam_cmd_i2c_continuous_wr->reg_addr) +
+ (sizeof(struct cam_cmd_read) *
+ cam_cmd_i2c_continuous_wr->header.count);
+
+ if (tot_size > (remain_len - byte_cnt)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+
rc = cam_sensor_handle_continuous_write(
cam_cmd_i2c_continuous_wr,
i2c_reg_settings,
@@ -376,11 +430,16 @@ int cam_sensor_i2c_command_parser(
break;
}
case CAMERA_SENSOR_CMD_TYPE_WAIT: {
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_unconditional_wait)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer space");
+ return -EINVAL;
+ }
if (generic_op_code ==
CAMERA_SENSOR_WAIT_OP_HW_UCND ||
generic_op_code ==
CAMERA_SENSOR_WAIT_OP_SW_UCND) {
-
rc = cam_sensor_handle_delay(
&cmd_buf, generic_op_code,
i2c_reg_settings, j, &byte_cnt,
@@ -412,6 +471,12 @@ int cam_sensor_i2c_command_parser(
break;
}
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: {
+ if (remain_len - byte_cnt <
+ sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer space");
+ return -EINVAL;
+ }
rc = cam_sensor_handle_slave_info(
io_master, cmd_buf);
if (rc) {
@@ -750,8 +815,32 @@ int cam_sensor_util_request_gpio_table(
return rc;
}
+
+static int32_t cam_sensor_validate(void *ptr, size_t remain_buf)
+{
+ struct common_header *cmm_hdr = (struct common_header *)ptr;
+ size_t validate_size = 0;
+
+ if (remain_buf < sizeof(struct common_header))
+ return -EINVAL;
+
+ if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_PWR_UP ||
+ cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_PWR_DOWN)
+ validate_size = sizeof(struct cam_cmd_power);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
+ validate_size = sizeof(struct cam_cmd_unconditional_wait);
+
+ if (remain_buf < validate_size) {
+ CAM_ERR(CAM_SENSOR, "Invalid cmd_buf len %zu min %zu",
+ remain_buf, validate_size);
+ return -EINVAL;
+ }
+ return 0;
+}
+
int32_t cam_sensor_update_power_settings(void *cmd_buf,
- int cmd_length, struct cam_sensor_power_ctrl_t *power_info)
+ uint32_t cmd_length, struct cam_sensor_power_ctrl_t *power_info,
+ size_t cmd_buf_len)
{
int32_t rc = 0, tot_size = 0, last_cmd_type = 0;
int32_t i = 0, pwr_up = 0, pwr_down = 0;
@@ -760,7 +849,8 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
struct cam_cmd_power *pwr_cmd = (struct cam_cmd_power *)cmd_buf;
struct common_header *cmm_hdr = (struct common_header *)cmd_buf;
- if (!pwr_cmd || !cmd_length) {
+ if (!pwr_cmd || !cmd_length || cmd_buf_len < (size_t)cmd_length ||
+ cam_sensor_validate(cmd_buf, cmd_buf_len)) {
CAM_ERR(CAM_SENSOR, "Invalid Args: pwr_cmd %pK, cmd_length: %d",
pwr_cmd, cmd_length);
return -EINVAL;
@@ -787,6 +877,10 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
}
while (tot_size < cmd_length) {
+ if (cam_sensor_validate(ptr, (cmd_length - tot_size))) {
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
if (cmm_hdr->cmd_type ==
CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
struct cam_cmd_power *pwr_cmd =
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
index 583ddb14243b..85497fda011c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -60,7 +60,8 @@ int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info,
uint16_t power_setting_size);
int32_t cam_sensor_update_power_settings(void *cmd_buf,
- int cmd_length, struct cam_sensor_power_ctrl_t *power_info);
+ uint32_t cmd_length, struct cam_sensor_power_ctrl_t *power_info,
+ size_t cmd_buf_len);
int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info,
int bob_reg_idx, bool flag);
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index 56209c67255e..7a489d7204ff 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3005,7 +3005,7 @@ int cam_smmu_destroy_handle(int handle)
cam_smmu_clean_kernel_buffer_list(idx);
}
- if (&iommu_cb_set.cb_info[idx].is_secure) {
+ 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;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
index 66a4487af172..a1a372008cb8 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -50,23 +50,44 @@ int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc)
return 0;
}
-int cam_packet_util_validate_packet(struct cam_packet *packet)
+int cam_packet_util_validate_packet(struct cam_packet *packet,
+ size_t remain_len)
{
+ size_t sum_cmd_desc = 0;
+ size_t sum_io_cfgs = 0;
+ size_t sum_patch_desc = 0;
+ size_t pkt_wo_payload = 0;
+
if (!packet)
return -EINVAL;
+ if ((size_t)packet->header.size > remain_len) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid packet size: %zu, CPU buf length: %zu",
+ (size_t)packet->header.size, remain_len);
+ return -EINVAL;
+ }
+
+
CAM_DBG(CAM_UTIL, "num cmd buf:%d num of io config:%d kmd buf index:%d",
packet->num_cmd_buf, packet->num_io_configs,
packet->kmd_cmd_buf_index);
- if ((packet->kmd_cmd_buf_index >= packet->num_cmd_buf) ||
- (!packet->header.size) ||
- (packet->cmd_buf_offset > packet->header.size) ||
- (packet->io_configs_offset > packet->header.size)) {
- CAM_ERR(CAM_UTIL, "invalid packet:%d %d %d %d %d",
- packet->kmd_cmd_buf_index,
- packet->num_cmd_buf, packet->cmd_buf_offset,
- packet->io_configs_offset, packet->header.size);
+ sum_cmd_desc = packet->num_cmd_buf * sizeof(struct cam_cmd_buf_desc);
+ sum_io_cfgs = packet->num_io_configs * sizeof(struct cam_buf_io_cfg);
+ sum_patch_desc = packet->num_patches * sizeof(struct cam_patch_desc);
+ pkt_wo_payload = offsetof(struct cam_packet, payload);
+
+ if ((!packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->cmd_buf_offset +
+ sum_cmd_desc) > (size_t)packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->io_configs_offset +
+ sum_io_cfgs) > (size_t)packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->patch_offset +
+ sum_patch_desc) > (size_t)packet->header.size)) {
+ CAM_ERR(CAM_UTIL, "params not within mem len:%zu %zu %zu %zu",
+ (size_t)packet->header.size, sum_cmd_desc,
+ sum_io_cfgs, sum_patch_desc);
return -EINVAL;
}
@@ -78,6 +99,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
{
int rc = 0;
size_t len = 0;
+ size_t remain_len = 0;
struct cam_cmd_buf_desc *cmd_desc;
uint32_t *cpu_addr;
@@ -86,6 +108,13 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
return -EINVAL;
}
+ if ((packet->kmd_cmd_buf_index < 0) ||
+ (packet->kmd_cmd_buf_index > packet->num_cmd_buf)) {
+ CAM_ERR(CAM_UTIL, "Invalid kmd buf index: %d",
+ packet->kmd_cmd_buf_index);
+ return -EINVAL;
+ }
+
/* Take first command descriptor and add offset to it for kmd*/
cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)
&packet->payload + packet->cmd_buf_offset);
@@ -100,12 +129,21 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
if (rc)
return rc;
- if (len < cmd_desc->size) {
+ remain_len = len;
+ if (((size_t)cmd_desc->offset >= len) ||
+ ((size_t)cmd_desc->size >= (len - (size_t)cmd_desc->offset))) {
CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d",
len, cmd_desc->size);
return -EINVAL;
}
+ remain_len -= (size_t)cmd_desc->offset;
+ if ((size_t)packet->kmd_cmd_buf_offset >= remain_len) {
+ CAM_ERR(CAM_UTIL, "Invalid kmd cmd buf offset: %zu",
+ (size_t)packet->kmd_cmd_buf_offset);
+ return -EINVAL;
+ }
+
cpu_addr += (cmd_desc->offset / 4) + (packet->kmd_cmd_buf_offset / 4);
CAM_DBG(CAM_UTIL, "total size %d, cmd size: %d, KMD buffer size: %d",
cmd_desc->size, cmd_desc->length,
@@ -171,21 +209,17 @@ 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 (patch_desc[i].src_offset >= src_buf_size) {
- CAM_ERR_RATE_LIMIT(CAM_UTIL,
- "Inval src offset:0x%x src len:0x%x reqid:%lld",
- patch_desc[i].src_offset,
- (unsigned int)src_buf_size,
- packet->header.request_id);
+ if ((size_t)patch_desc[i].src_offset >= src_buf_size) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid src buf patch offset");
return -EINVAL;
}
- if (patch_desc[i].dst_offset >= dst_buf_len) {
- CAM_ERR_RATE_LIMIT(CAM_UTIL,
- "Inval dst offset:0x%x dst len:0x%x reqid:%lld",
- patch_desc[i].dst_offset,
- (unsigned int)dst_buf_len,
- packet->header.request_id);
+ 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;
}
@@ -211,6 +245,7 @@ int cam_packet_util_process_generic_cmd_buffer(
int rc;
uintptr_t cpu_addr;
size_t buf_size;
+ size_t remain_len = 0;
uint32_t *blob_ptr;
uint32_t blob_type, blob_size, blob_block_size, len_read;
@@ -233,6 +268,21 @@ int cam_packet_util_process_generic_cmd_buffer(
return rc;
}
+ remain_len = buf_size;
+ if ((buf_size < sizeof(uint32_t)) ||
+ ((size_t)cmd_buf->offset > (buf_size - sizeof(uint32_t)))) {
+ CAM_ERR(CAM_UTIL, "Invalid offset for cmd buf: %zu",
+ (size_t)cmd_buf->offset);
+ return -EINVAL;
+ }
+ remain_len -= (size_t)cmd_buf->offset;
+
+ if (remain_len < (size_t)cmd_buf->length) {
+ CAM_ERR(CAM_UTIL, "Invalid length for cmd buf: %zu",
+ (size_t)cmd_buf->length);
+ return -EINVAL;
+ }
+
blob_ptr = (uint32_t *)(((uint8_t *)cpu_addr) +
cmd_buf->offset);
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
index 94d269313c7d..284f0a520aed 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -59,10 +59,13 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
*
* @packet: Packet to be validated
*
+ * @remain_len: CPU buff length after config offset
+ *
* @return: 0 for success
* -EINVAL for Fail
*/
-int cam_packet_util_validate_packet(struct cam_packet *packet);
+int cam_packet_util_validate_packet(struct cam_packet *packet,
+ size_t remain_len);
/**
* cam_packet_util_validate_cmd_desc()
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
index 6a28da5926c7..69be506f6b0b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
@@ -3,3 +3,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v2
ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
obj-$(CONFIG_MSMB_CAMERA) += msm_flash.o
+obj-$(CONFIG_MSMB_CAMERA) += qm215_gpio_flash.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index 656b1ca2dc98..89a5ea06cc49 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
#include <linux/of_gpio.h>
#include <linux/leds-qpnp-flash.h>
#include "msm_flash.h"
+#include "msm_camera_io_util.h"
#include "msm_camera_dt_util.h"
#include "msm_cci.h"
@@ -514,6 +515,8 @@ static int32_t msm_flash_init(
__func__, __LINE__,
flash_data->cfg.flash_init_info->flash_driver_type);
}
+ if (flash_ctrl->platform_flash_init)
+ flash_ctrl->platform_flash_init(flash_ctrl, flash_data);
if (flash_ctrl->func_tbl->camera_flash_init) {
rc = flash_ctrl->func_tbl->camera_flash_init(
@@ -600,6 +603,8 @@ static int32_t msm_flash_prepare(
__func__, __LINE__, flash_ctrl->flash_state);
if (flash_ctrl->switch_trigger == NULL) {
+ if (flash_ctrl->platform_flash_init)
+ return ret;
pr_err("%s:%d Invalid argument\n",
__func__, __LINE__);
return -EINVAL;
@@ -1286,6 +1291,8 @@ static int32_t msm_flash_platform_probe(struct platform_device *pdev)
kfree(flash_ctrl);
return -EINVAL;
}
+ if (flash_ctrl->flash_driver_type == FLASH_DRIVER_GPIO)
+ platform_set_drvdata(pdev, flash_ctrl);
flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE;
flash_ctrl->power_info.dev = &flash_ctrl->pdev->dev;
@@ -1334,6 +1341,11 @@ static int32_t msm_flash_platform_probe(struct platform_device *pdev)
return rc;
}
+int32_t camera_flash_platform_probe(struct platform_device *pdev)
+{
+ return msm_flash_platform_probe(pdev);
+}
+
MODULE_DEVICE_TABLE(of, msm_flash_dt_match);
static struct platform_driver msm_flash_platform_driver = {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h
index eda6ce44b6bc..67a8c2c7333a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2016, 2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -102,6 +102,8 @@ struct msm_flash_ctrl_t {
/* flash state */
enum msm_camera_flash_state_t flash_state;
+ int32_t (*platform_flash_init)(struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data);
};
int msm_flash_i2c_probe(struct i2c_client *client,
@@ -124,4 +126,6 @@ int msm_flash_led_release(struct msm_flash_ctrl_t *fctrl);
int msm_flash_led_off(struct msm_flash_ctrl_t *fctrl);
int msm_flash_led_low(struct msm_flash_ctrl_t *fctrl);
int msm_flash_led_high(struct msm_flash_ctrl_t *fctrl);
+int32_t camera_flash_platform_probe(struct platform_device *pdev);
+
#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/qm215_gpio_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/qm215_gpio_flash.c
new file mode 100644
index 000000000000..11a7db55e3f4
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/qm215_gpio_flash.c
@@ -0,0 +1,264 @@
+/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/export.h>
+#include "msm_camera_io_util.h"
+#include "msm_flash.h"
+
+#define FLASH_NAME "qcom,gpio-flash"
+
+#undef CDBG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+
+static const struct of_device_id msm_gpio_flash_dt_match[] = {
+ {.compatible = "qcom,qm215-gpio-flash", .data = NULL},
+ {}
+};
+static struct msm_flash_table qm215_gpio_flash_table;
+MODULE_DEVICE_TABLE(of, msm_flash_dt_match);
+
+static int32_t qm215_flash_low(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+ struct msm_camera_gpio_num_info *gpio_num_info = NULL;
+
+ if (!flash_ctrl) {
+ pr_err("device data NULL\n");
+ return -EINVAL;
+ }
+
+ CDBG("Enter");
+ power_info = &flash_ctrl->power_info;
+ gpio_num_info = power_info->gpio_conf->gpio_num_info;
+
+ if (flash_ctrl->flash_driver_type == FLASH_DRIVER_GPIO &&
+ gpio_num_info->valid[SENSOR_GPIO_FL_NOW] &&
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN]) {
+
+ CDBG("flash op low gpio num %d(state:%d) %d(state: %d)\n",
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_NOW],
+ GPIO_OUT_HIGH,
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN],
+ GPIO_OUT_HIGH);
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_NOW],
+ GPIO_OUT_HIGH);
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN],
+ GPIO_OUT_HIGH);
+ }
+ CDBG("Exit\n");
+ return 0;
+}
+
+static int32_t qm215_flash_high(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+ struct msm_camera_gpio_num_info *gpio_num_info = NULL;
+
+ if (!flash_ctrl) {
+ pr_err("device data NULL\n");
+ return -EINVAL;
+ }
+
+ CDBG("Enter\n");
+ power_info = &flash_ctrl->power_info;
+ gpio_num_info = power_info->gpio_conf->gpio_num_info;
+
+ if (flash_ctrl->flash_driver_type == FLASH_DRIVER_GPIO &&
+ gpio_num_info->valid[SENSOR_GPIO_FL_NOW] &&
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN]) {
+
+ CDBG("flash op high gpio num %d(state:%d) %d(state:%d)\n",
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_NOW],
+ GPIO_OUT_LOW,
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN],
+ GPIO_OUT_HIGH);
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_NOW],
+ GPIO_OUT_LOW);
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN],
+ GPIO_OUT_HIGH);
+ }
+ CDBG("Exit\n");
+
+ return 0;
+}
+
+static int32_t qm215_flash_release(
+ struct msm_flash_ctrl_t *flash_ctrl)
+{
+ int32_t rc = 0;
+
+ if (!flash_ctrl) {
+ pr_err("device data NULL\n");
+ return -EINVAL;
+ }
+
+ CDBG("Enter\n");
+ rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, NULL);
+ if (rc < 0) {
+ pr_err("%s:%d camera_flash_init failed rc = %d",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+ flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE;
+ CDBG("Exit\n");
+ return 0;
+}
+
+static int32_t qm215_flash_off(struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+ struct msm_camera_gpio_num_info *gpio_num_info = NULL;
+
+ if (!flash_ctrl) {
+ pr_err("device data NULL\n");
+ return -EINVAL;
+ }
+
+ CDBG("Enter\n");
+ power_info = &flash_ctrl->power_info;
+ gpio_num_info = power_info->gpio_conf->gpio_num_info;
+
+ if (flash_ctrl->flash_driver_type == FLASH_DRIVER_GPIO &&
+ gpio_num_info->valid[SENSOR_GPIO_FL_NOW] &&
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN]) {
+
+ CDBG("flash off gpio num %d(state:%d) %d(state: %d)\n",
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_NOW],
+ GPIO_OUT_LOW,
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN],
+ GPIO_OUT_LOW);
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_NOW],
+ GPIO_OUT_LOW);
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_GPIO_FL_EN],
+ GPIO_OUT_LOW);
+ }
+
+ CDBG("Exit\n");
+ return 0;
+}
+
+static int32_t qm215_flash_gpio_init(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ int32_t rc = 0;
+
+ CDBG("Enter");
+ rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, flash_data);
+
+ CDBG("Exit");
+ return rc;
+}
+
+
+static int32_t qm215_platform_flash_init(struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ if (!flash_ctrl) {
+ pr_err("devices data NULL\n");
+ return -EINVAL;
+ }
+
+ if (flash_ctrl->flash_driver_type == FLASH_DRIVER_GPIO)
+ flash_ctrl->func_tbl = &qm215_gpio_flash_table.func_tbl;
+
+ return 0;
+}
+static int32_t qm215_flash_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ struct msm_flash_ctrl_t *flash_ctrl = NULL;
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+ struct msm_camera_gpio_conf *gpio_conf = NULL;
+
+ if (!pdev->dev.of_node) {
+ pr_err("of_node NULL\n");
+ return -EINVAL;
+ }
+ CDBG("enter probe\n");
+ rc = camera_flash_platform_probe(pdev);
+ if (rc >= 0) {
+ flash_ctrl =
+ (struct msm_flash_ctrl_t *) platform_get_drvdata(pdev);
+ CDBG("device data %pK\n", flash_ctrl);
+ if (!flash_ctrl) {
+ pr_err("of_node NULL\n");
+ return -EINVAL;
+ }
+ power_info = &flash_ctrl->power_info;
+ gpio_conf = power_info->gpio_conf;
+ rc = msm_camera_request_gpio_table(gpio_conf->cam_gpio_req_tbl,
+ gpio_conf->cam_gpio_req_tbl_size, 1);
+ if (rc < 0) {
+ pr_err("%s: request gpio failed\n", __func__);
+ return rc;
+ }
+ flash_ctrl->platform_flash_init = qm215_platform_flash_init;
+ }
+ return rc;
+}
+
+static struct platform_driver msm_gpio_flash_platform_driver = {
+ .probe = qm215_flash_platform_probe,
+ .driver = {
+ .name = "qcom,camera-gpio-flash",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_gpio_flash_dt_match,
+ },
+};
+
+static int __init qm215_gpio_flash_init_module(void)
+{
+ int32_t rc = 0;
+
+ CDBG("Enter\n");
+ rc = platform_driver_register(&msm_gpio_flash_platform_driver);
+ if (rc)
+ pr_err("platform probe for flash failed");
+
+ return rc;
+}
+
+static void __exit qm215_gpio_flash_exit_module(void)
+{
+ platform_driver_unregister(&msm_gpio_flash_platform_driver);
+}
+
+static struct msm_flash_table qm215_gpio_flash_table = {
+ .flash_driver_type = FLASH_DRIVER_GPIO,
+ .func_tbl = {
+ .camera_flash_init = qm215_flash_gpio_init,
+ .camera_flash_release = qm215_flash_release,
+ .camera_flash_off = qm215_flash_off,
+ .camera_flash_low = qm215_flash_low,
+ .camera_flash_high = qm215_flash_high,
+ .camera_flash_query_current = NULL,
+ },
+};
+
+module_init(qm215_gpio_flash_init_module);
+module_exit(qm215_gpio_flash_exit_module);
+MODULE_DESCRIPTION("MSM GPIO FLASH");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
index 13a653ae0399..e1809a1d789c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -509,8 +509,8 @@ int cam_hw_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if (!rc) {
CAM_DBG(CAM_CDM,
- "write BL success for cnt=%d with tag=%d",
- i, core->bl_tag);
+ "write BL success for cnt=%d with tag=%d total_cnt=%d",
+ i, core->bl_tag, req->data->cmd_arrary_count);
CAM_DBG(CAM_CDM, "Now commit the BL");
if (cam_hw_cdm_commit_bl_write(cdm_hw)) {
@@ -550,35 +550,33 @@ static void cam_hw_cdm_work(struct work_struct *work)
cdm_hw = payload->hw;
core = (struct cam_cdm *)cdm_hw->core_info;
- CAM_DBG(CAM_CDM, "IRQ status=%x", payload->irq_status);
+ CAM_DBG(CAM_CDM, "IRQ status=0x%x", payload->irq_status);
if (payload->irq_status &
CAM_CDM_IRQ_STATUS_INFO_INLINE_IRQ_MASK) {
- struct cam_cdm_bl_cb_request_entry *node;
+ struct cam_cdm_bl_cb_request_entry *node, *tnode;
- CAM_DBG(CAM_CDM, "inline IRQ data=%x",
+ CAM_DBG(CAM_CDM, "inline IRQ data=0x%x",
payload->irq_data);
mutex_lock(&cdm_hw->hw_mutex);
- node = cam_cdm_find_request_by_bl_tag(
- payload->irq_data,
- &core->bl_request_list);
- if (node) {
+ list_for_each_entry_safe(node, tnode,
+ &core->bl_request_list, entry) {
if (node->request_type ==
CAM_HW_CDM_BL_CB_CLIENT) {
cam_cdm_notify_clients(cdm_hw,
CAM_CDM_CB_STATUS_BL_SUCCESS,
(void *)node);
} else if (node->request_type ==
- CAM_HW_CDM_BL_CB_INTERNAL) {
+ CAM_HW_CDM_BL_CB_INTERNAL) {
CAM_ERR(CAM_CDM,
"Invalid node=%pK %d", node,
node->request_type);
}
list_del_init(&node->entry);
+ if (node->bl_tag == payload->irq_data) {
+ kfree(node);
+ break;
+ }
kfree(node);
- } else {
- CAM_ERR(CAM_CDM,
- "Inval node, inline_irq st=%x data=%x",
- payload->irq_status, payload->irq_data);
}
mutex_unlock(&cdm_hw->hw_mutex);
}
@@ -684,7 +682,7 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
CAM_ERR(CAM_CDM, "Failed to Write CDM HW IRQ cmd");
work_status = queue_work(cdm_core->work_queue, &payload->work);
if (work_status == false) {
- CAM_ERR(CAM_CDM, "Failed to queue work for irq=%x",
+ CAM_ERR(CAM_CDM, "Failed to queue work for irq=0x%x",
payload->irq_status);
kfree(payload);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c
index 9021ecabb27c..e5034c59a4a2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cdm/cam_cdm_virtual_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -118,6 +118,14 @@ int cam_virtual_cdm_submit_bl(struct cam_hw_info *cdm_hw,
if ((!rc) && (vaddr_ptr) && (len) &&
(len >= cdm_cmd->cmd[i].offset)) {
+
+
+ if ((len - cdm_cmd->cmd[i].offset) <
+ cdm_cmd->cmd[i].len) {
+ CAM_ERR(CAM_CDM, "Not enough buffer");
+ rc = -EINVAL;
+ break;
+ }
CAM_DBG(CAM_CDM,
"hdl=%x vaddr=%pK offset=%d cmdlen=%d:%zu",
cdm_cmd->cmd[i].bl_addr.mem_handle,
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
index d4f9b72f99f3..5f9d1e06d8a8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -43,7 +43,6 @@ int cam_context_shutdown(struct cam_context *ctx)
int rc = 0;
struct cam_release_dev_cmd cmd;
- mutex_lock(&ctx->ctx_mutex);
if (ctx->state > CAM_CTX_AVAILABLE && ctx->state < CAM_CTX_STATE_MAX) {
cmd.session_handle = ctx->session_hdl;
cmd.dev_handle = ctx->dev_hdl;
@@ -60,7 +59,6 @@ int cam_context_shutdown(struct cam_context *ctx)
ctx->dev_name, ctx->ctx_id, ctx->state);
rc = -EINVAL;
}
- mutex_unlock(&ctx->ctx_mutex);
rc = cam_destroy_device_hdl(ctx->dev_hdl);
if (rc)
@@ -173,6 +171,7 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
return -EINVAL;
}
+ mutex_lock(&ctx->ctx_mutex);
if (ctx->state_machine[ctx->state].crm_ops.apply_req) {
rc = ctx->state_machine[ctx->state].crm_ops.apply_req(ctx,
apply);
@@ -181,6 +180,7 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx,
ctx->dev_hdl, ctx->state);
rc = -EPROTO;
}
+ mutex_unlock(&ctx->ctx_mutex);
return rc;
}
@@ -243,6 +243,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
return -EINVAL;
}
+ mutex_lock(&ctx->ctx_mutex);
if (ctx->state_machine[ctx->state].pagefault_ops) {
rc = ctx->state_machine[ctx->state].pagefault_ops(ctx, iova,
buf_info);
@@ -250,6 +251,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d",
ctx->dev_hdl, ctx->state);
}
+ mutex_unlock(&ctx->ctx_mutex);
return rc;
}
@@ -528,6 +530,7 @@ int cam_context_init(struct cam_context *ctx,
ctx->dev_name = dev_name;
ctx->dev_id = dev_id;
ctx->ctx_id = ctx_id;
+ ctx->last_flush_req = 0;
ctx->ctx_crm_intf = NULL;
ctx->crm_ctx_intf = crm_node_intf;
ctx->hw_mgr_intf = hw_mgr_intf;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
index d98b900bc07a..174469e473da 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -262,6 +262,7 @@ int32_t cam_context_release_dev_to_hw(struct cam_context *ctx,
ctx->session_hdl = -1;
ctx->dev_hdl = -1;
ctx->link_hdl = -1;
+ ctx->last_flush_req = 0;
return 0;
}
@@ -303,6 +304,12 @@ int32_t cam_context_config_dev_to_hw(
return rc;
}
+ if ((len < sizeof(struct cam_packet)) ||
+ (cmd->offset >= (len - sizeof(struct cam_packet)))) {
+ CAM_ERR(CAM_CTXT, "Not enough buf");
+ return -EINVAL;
+
+ }
packet = (struct cam_packet *) ((uint8_t *)packet_addr +
(uint32_t)cmd->offset);
@@ -333,6 +340,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
+ size_t remain_len = 0;
int32_t i = 0, j = 0;
if (!ctx || !cmd) {
@@ -381,11 +389,19 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
goto free_req;
}
+ remain_len = len;
+ if ((len < sizeof(struct cam_packet)) ||
+ ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_CTXT, "invalid buff length: %zu or offset", len);
+ return -EINVAL;
+ }
+
+ remain_len -= (size_t)cmd->offset;
packet = (struct cam_packet *) ((uint8_t *)packet_addr +
(uint32_t)cmd->offset);
if (packet->header.request_id <= ctx->last_flush_req) {
- CAM_DBG(CAM_CORE,
+ CAM_ERR(CAM_CORE,
"request %lld has been flushed, reject packet",
packet->header.request_id);
rc = -EINVAL;
@@ -398,6 +414,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
/* preprocess the configuration */
memset(&cfg, 0, sizeof(cfg));
cfg.packet = packet;
+ cfg.remain_len = remain_len;
cfg.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
cfg.max_hw_update_entries = CAM_CTX_CFG_MAX;
cfg.num_hw_update_entries = req->num_hw_update_entries;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h
deleted file mode 100644
index 32330b1e07e4..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_core_defs.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _CAM_CORE_DEFS_H_
-#define _CAM_CORE_DEFS_H_
-
-#define CAM_CORE_TRACE_ENABLE 0
-
-#if (CAM_CORE_TRACE_ENABLE == 1)
- #define CAM_CORE_DBG(fmt, args...) do { \
- trace_printk("%d: [cam_core_dbg] "fmt"\n", __LINE__, ##args); \
- pr_debug("%s:%d "fmt"\n", __func__, __LINE__, ##args); \
- } while (0)
-
- #define CAM_CORE_WARN(fmt, args...) do { \
- trace_printk("%d: [cam_core_warn] "fmt"\n", __LINE__, ##args); \
- pr_warn("%s:%d "fmt"\n", __func__, __LINE__, ##args); \
- } while (0)
-
- #define CAM_CORE_ERR(fmt, args...) do { \
- trace_printk("%d: [cam_core_err] "fmt"\n", __LINE__, ##args); \
- pr_err("%s:%d "fmt"\n", __func__, __LINE__, ##args);\
- } while (0)
-#else
- #define CAM_CORE_DBG(fmt, args...) pr_debug("%s:%d "fmt"\n", \
- __func__, __LINE__, ##args)
-
- #define CAM_CORE_WARN(fmt, args...) pr_warn("%s:%d "fmt"\n", \
- __func__, __LINE__, ##args)
-
- #define CAM_CORE_ERR(fmt, args...) pr_err("%s:%d "fmt"\n", \
- __func__, __LINE__, ##args)
-#endif
-
-#endif /* _CAM_CORE_DEFS_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h
index fd30f115cc0c..c3d1c2eff4e9 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -153,6 +153,7 @@ struct cam_hw_mgr_dump_pf_data {
* struct cam_hw_prepare_update_args - Payload for prepare command
*
* @packet: CSL packet from user mode driver
+ * @remain_len Remaining length of CPU buffer after config offset
* @ctxt_to_hw_map: HW context from the acquire
* @max_hw_update_entries: Maximum hardware update entries supported
* @hw_update_entries: Actual hardware update configuration (returned)
@@ -169,6 +170,7 @@ struct cam_hw_mgr_dump_pf_data {
*/
struct cam_hw_prepare_update_args {
struct cam_packet *packet;
+ size_t remain_len;
void *ctxt_to_hw_map;
uint32_t max_hw_update_entries;
struct cam_hw_update_entry *hw_update_entries;
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
index 9da340b1e766..ee9b2bfc1bfa 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -111,6 +111,7 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node,
goto err;
}
+ ctx->last_flush_req = 0;
rc = cam_context_handle_acquire_dev(ctx, acquire);
if (rc) {
CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
@@ -657,6 +658,7 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
"acquire device failed(rc = %d)", rc);
goto acquire_kfree;
}
+ CAM_INFO(CAM_CORE, "Acquire HW successful");
}
if (copy_to_user((void __user *)cmd->handle, acquire_ptr,
@@ -763,6 +765,8 @@ acquire_kfree:
"release device failed(rc = %d)", rc);
}
+ CAM_INFO(CAM_CORE, "Release HW done(rc = %d)", rc);
+
release_kfree:
kfree(release_ptr);
break;
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
index 2a91f03ecdc8..017e810e07c0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -313,6 +313,9 @@ static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core,
goto mnoc_node_get_fail;
}
axi_port->axi_port_mnoc_node = axi_port_mnoc_node;
+ axi_port->ib_bw_voting_needed =
+ of_property_read_bool(axi_port_node,
+ "ib-bw-voting-needed");
rc = cam_cpas_util_register_bus_client(soc_info,
axi_port_mnoc_node, &axi_port->mnoc_bus);
@@ -662,12 +665,19 @@ static int cam_cpas_util_apply_client_axi_vote(
axi_port->camnoc_bus.src, axi_port->camnoc_bus.dst,
camnoc_bw, mnoc_bw);
- rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
- mnoc_bw, mnoc_bw, false);
+ if (axi_port->ib_bw_voting_needed)
+ rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
+ mnoc_bw, mnoc_bw, false);
+ else
+ rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
+ mnoc_bw, 0, false);
+
if (rc) {
CAM_ERR(CAM_CPAS,
"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
- mnoc_bw, mnoc_bw, rc);
+ mnoc_bw,
+ (axi_port->ib_bw_voting_needed ? mnoc_bw : 0),
+ rc);
goto unlock_axi_port;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h
index f93d036ecfcf..8e016191edb2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -149,6 +149,7 @@ struct cam_cpas_bus_client {
* @camnoc_bus: CAMNOC bus client info for this port
* @mnoc_bus: MNOC bus client info for this port
* @axi_port_name: Name of this AXI port
+ * @ib_bw_voting_needed: if this port can update ib bw dynamically
* @axi_port_node: Node representing this AXI Port
* @axi_port_mnoc_node: Node representing mnoc in this AXI Port
* @axi_port_camnoc_node: Node representing camnoc in this AXI Port
@@ -161,6 +162,7 @@ struct cam_cpas_axi_port {
struct cam_cpas_bus_client camnoc_bus;
struct cam_cpas_bus_client mnoc_bus;
const char *axi_port_name;
+ bool ib_bw_voting_needed;
struct device_node *axi_port_node;
struct device_node *axi_port_mnoc_node;
struct device_node *axi_port_camnoc_node;
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
index 8f89c4b7b5fd..49774f24ba20 100644
--- a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,9 +20,11 @@
#include "cam_io_util.h"
#include "cam_cpas_soc.h"
#include "cpastop100.h"
+#include "cpastop_v150_100.h"
#include "cpastop_v170_110.h"
#include "cpastop_v175_100.h"
#include "cpastop_v175_101.h"
+#include "cpastop_v175_120.h"
struct cam_camnoc_info *camnoc_info;
@@ -104,6 +106,17 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw,
(hw_caps->cpas_version.minor == 0) &&
(hw_caps->cpas_version.incr == 1))
soc_info->hw_version = CAM_CPAS_TITAN_175_V101;
+ else if ((hw_caps->cpas_version.major == 1) &&
+ (hw_caps->cpas_version.minor == 2) &&
+ (hw_caps->cpas_version.incr == 0))
+ soc_info->hw_version = CAM_CPAS_TITAN_175_V120;
+ } else if ((hw_caps->camera_version.major == 1) &&
+ (hw_caps->camera_version.minor == 5) &&
+ (hw_caps->camera_version.incr == 0)) {
+ if ((hw_caps->cpas_version.major == 1) &&
+ (hw_caps->cpas_version.minor == 0) &&
+ (hw_caps->cpas_version.incr == 0))
+ soc_info->hw_version = CAM_CPAS_TITAN_150_V100;
}
CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version);
@@ -642,6 +655,12 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
case CAM_CPAS_TITAN_175_V101:
camnoc_info = &cam175_cpas101_camnoc_info;
break;
+ case CAM_CPAS_TITAN_175_V120:
+ camnoc_info = &cam175_cpas120_camnoc_info;
+ break;
+ case CAM_CPAS_TITAN_150_V100:
+ camnoc_info = &cam150_cpas100_camnoc_info;
+ break;
default:
CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d",
hw_caps->camera_version.major,
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h
new file mode 100644
index 000000000000..cf9f82d07b20
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_100.h
@@ -0,0 +1,537 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CPASTOP_V150_100_H_
+#define _CPASTOP_V150_100_H_
+
+#define TEST_IRQ_ENABLE 0
+
+static struct cam_camnoc_irq_sbm cam_cpas_v150_100_irq_sbm = {
+ .sbm_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2040, /* SBM_FAULTINEN0_LOW */
+ .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/
+ 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+ 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */
+ 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */
+ 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */
+ 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */
+ (TEST_IRQ_ENABLE ?
+ 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */
+ 0x0),
+ },
+ .sbm_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */
+ },
+ .sbm_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */
+ .value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
+ }
+};
+
+static struct cam_camnoc_irq_err
+ cam_cpas_v150_100_irq_err[] = {
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
+ .enable = true,
+ .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x5a0, /* SPECIFIC_IFE02_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x590, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x598, /* SPECIFIC_IFE02_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x9a0, /* SPECIFIC_IFE13_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x990, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x998, /* SPECIFIC_IFE13_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0xd20, /* SPECIFIC_IBL_RD_DECERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0xd10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0xd18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x11a0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x1190,
+ /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x1198, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT,
+ .enable = true,
+ .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST,
+ .enable = TEST_IRQ_ENABLE ? true : false,
+ .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x5,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+};
+
+static struct cam_camnoc_specific
+ cam_cpas_v150_100_camnoc_specific[] = {
+ {
+ .port_type = CAM_CAMNOC_CDM,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */
+ .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
+ .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
+ .value = 0x2,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE02,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */
+ /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */
+ .value = 0x1,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE13,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */
+ /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */
+ .value = 0x1,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x0,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 0x5,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_JPEG,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */
+ .value = 0x22,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_FD,
+ .enable = false,
+ },
+ {
+ .port_type = CAM_CAMNOC_ICP,
+ .enable = true,
+ .flag_out_set0_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_WRITE,
+ .masked_value = 0,
+ .offset = 0x2088,
+ .value = 0x100000,
+ },
+ },
+};
+
+static struct cam_camnoc_err_logger_info cam150_cpas100_err_logger_offsets = {
+ .mainctrl = 0x2708, /* ERRLOGGER_MAINCTL_LOW */
+ .errvld = 0x2710, /* ERRLOGGER_ERRVLD_LOW */
+ .errlog0_low = 0x2720, /* ERRLOGGER_ERRLOG0_LOW */
+ .errlog0_high = 0x2724, /* ERRLOGGER_ERRLOG0_HIGH */
+ .errlog1_low = 0x2728, /* ERRLOGGER_ERRLOG1_LOW */
+ .errlog1_high = 0x272c, /* ERRLOGGER_ERRLOG1_HIGH */
+ .errlog2_low = 0x2730, /* ERRLOGGER_ERRLOG2_LOW */
+ .errlog2_high = 0x2734, /* ERRLOGGER_ERRLOG2_HIGH */
+ .errlog3_low = 0x2738, /* ERRLOGGER_ERRLOG3_LOW */
+ .errlog3_high = 0x273c, /* ERRLOGGER_ERRLOG3_HIGH */
+};
+
+static struct cam_cpas_hw_errata_wa_list cam150_cpas100_errata_wa_list = {
+ .camnoc_flush_slave_pending_trans = {
+ .enable = false,
+ .data.reg_info = {
+ .access_type = CAM_REG_TYPE_READ,
+ .offset = 0x2100, /* SidebandManager_SenseIn0_Low */
+ .mask = 0xE0000, /* Bits 17, 18, 19 */
+ .value = 0, /* expected to be 0 */
+ },
+ },
+};
+
+static struct cam_camnoc_info cam150_cpas100_camnoc_info = {
+ .specific = &cam_cpas_v150_100_camnoc_specific[0],
+ .specific_size = sizeof(cam_cpas_v150_100_camnoc_specific) /
+ sizeof(cam_cpas_v150_100_camnoc_specific[0]),
+ .irq_sbm = &cam_cpas_v150_100_irq_sbm,
+ .irq_err = &cam_cpas_v150_100_irq_err[0],
+ .irq_err_size = sizeof(cam_cpas_v150_100_irq_err) /
+ sizeof(cam_cpas_v150_100_irq_err[0]),
+ .err_logger = &cam150_cpas100_err_logger_offsets,
+ .errata_wa_list = &cam150_cpas100_errata_wa_list,
+};
+
+#endif /* _CPASTOP_V150_100_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h
new file mode 100644
index 000000000000..7212bb30940a
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v175_120.h
@@ -0,0 +1,769 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CPASTOP_V175_120_H_
+#define _CPASTOP_V175_120_H_
+
+#define TEST_IRQ_ENABLE 0
+
+static struct cam_camnoc_irq_sbm cam_cpas_v175_120_irq_sbm = {
+ .sbm_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2240, /* SBM_FAULTINEN0_LOW */
+ .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/
+ 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+ 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */
+ 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */
+ 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */
+ 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */
+ (TEST_IRQ_ENABLE ?
+ 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */
+ 0x0),
+ },
+ .sbm_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2248, /* SBM_FAULTINSTATUS0_LOW */
+ },
+ .sbm_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2280, /* SBM_FLAGOUTCLR0_LOW */
+ .value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
+ }
+};
+
+static struct cam_camnoc_irq_err
+ cam_cpas_v175_120_irq_err[] = {
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
+ .enable = true,
+ .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x4F08, /* ERRORLOGGER_MAINCTL_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x4F10, /* ERRORLOGGER_ERRVLD_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x4F18, /* ERRORLOGGER_ERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE0_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x3BA0, /* SPECIFIC_IFE02_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x3B90, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x3B98, /* SPECIFIC_IFE02_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x55a0, /* SPECIFIC_IFE13_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x5590, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x5598, /* SPECIFIC_IFE13_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2F20, /* SPECIFIC_IBL_RD_DECERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2F10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2F18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR,
+ .enable = true,
+ .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2Ba0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */
+ .value = 1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2B90,
+ /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */
+ },
+ .err_clear = {
+ .access_type = CAM_REG_TYPE_WRITE,
+ .enable = true,
+ .offset = 0x2B98, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT,
+ .enable = true,
+ .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2288, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x1,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2290, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2,
+ .enable = false,
+ },
+ {
+ .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST,
+ .enable = TEST_IRQ_ENABLE ? true : false,
+ .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */
+ .err_enable = {
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .enable = true,
+ .offset = 0x2288, /* SBM_FLAGOUTSET0_LOW */
+ .value = 0x5,
+ },
+ .err_status = {
+ .access_type = CAM_REG_TYPE_READ,
+ .enable = true,
+ .offset = 0x2290, /* SBM_FLAGOUTSTATUS0_LOW */
+ },
+ .err_clear = {
+ .enable = false,
+ },
+ },
+};
+
+static struct cam_camnoc_specific
+ cam_cpas_v175_120_camnoc_specific[] = {
+ {
+ .port_type = CAM_CAMNOC_CDM,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4230, /* SPECIFIC_CDM_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4234, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ /* cdm_main_SpecificToNttpTr_Urgency_Low */
+ .offset = 0x4238,
+ .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */
+ .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */
+ .value = 0x2,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4240, /* SPECIFIC_CDM_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x4248, /* SPECIFIC_CDM_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE0123_RDI_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IFE0123_PRIORITYLUT_LOW */
+ .offset = 0x3630,
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IFE0123_PRIORITYLUT_HIGH */
+ .offset = 0x3634,
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x3638, /* SPECIFIC_IFE0123_URGENCY_LOW */
+ /* SPECIFIC_IFE0123_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE0123_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3640, /* SPECIFIC_IFE0123_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3648, /* SPECIFIC_IFE0123_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE0_NRDI_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3A30, /* SPECIFIC_IFE0_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3A34, /* SPECIFIC_IFE0_PRIORITYLUT_HIGH */
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x3A38, /* SPECIFIC_IFE0_URGENCY_LOW */
+ /* SPECIFIC_IFE0_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE0_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3A40, /* SPECIFIC_IFE0_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3A48, /* SPECIFIC_IFE0_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3B88, /* SPECIFIC_IFE0_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ /* IFE0/1 RDI READ PATH */
+ .port_type = CAM_CAMNOC_IFE01_RDI_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3230, /* SPECIFIC_IFE1_PRIORITYLUT_LOW */
+ .value = 0x44443333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3234, /* SPECIFIC_IFE1_PRIORITYLUT_HIGH */
+ .value = 0x66665555,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x3238, /* SPECIFIC_IFE1_URGENCY_LOW */
+ /* SPECIFIC_IFE1_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IFE1_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x0,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3240, /* SPECIFIC_IFE1_DANGERLUT_LOW */
+ .value = 0x00000000,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x3248, /* SPECIFIC_IFE1_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IFE1_NRDI_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x5430, /* SPECIFIC_IFE1_WR_PRIORITYLUT_LOW */
+ .value = 0x66665433,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IFE1_WR_PRIORITYLUT_HIGH */
+ .offset = 0x5434,
+ .value = 0x66666666,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x5438, /* SPECIFIC_IFE1_WR_URGENCY_LOW */
+ /* SPECIFIC_IFE1_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IFE1_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x5440, /* SPECIFIC_IFE1_WR_DANGERLUT_LOW */
+ .value = 0xFFFFFF00,
+ },
+ .safe_lut = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .offset = 0x5448, /* SPECIFIC_IFE1_WR_SAFELUT_LOW */
+ .value = 0xF,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x5588, /* SPECIFIC_IFE1_WR_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x2E38, /* SPECIFIC_IBL_RD_URGENCY_LOW */
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */
+ .mask = 0x7,
+ /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x0,
+ .value = 0x3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2E48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2F08, /* SPECIFIC_IBL_RD_DECCTL_LOW */
+ .value = 1,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A30, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A34, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ .offset = 0x2A38, /* SPECIFIC_IBL_WR_URGENCY_LOW */
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */
+ .shift = 0x4,
+ .value = 0x3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A40, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2A48, /* SPECIFIC_IBL_WR_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2B88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 0,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_IPE_VID_DISP_WRITE,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_LOW */
+ .offset = 0x5E30,
+ .value = 0x33333333,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IPE_VID_DISP_PRIORITYLUT_HIGH */
+ .offset = 0x5E34,
+ .value = 0x33333333,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 1,
+ /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW */
+ .offset = 0x5E38,
+ /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW_READ_MASK */
+ .mask = 0x70,
+ /* SPECIFIC_IPE_VID_DISP_URGENCY_LOW_READ_SHIFT */
+ .shift = 0x4,
+ .value = 3,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC__IPE_VID_DISP_DANGERLUT_LOW */
+ .offset = 0x5E40,
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ /* SPECIFIC_IPE_VID_DISP_SAFELUT_LOW */
+ .offset = 0x5E48,
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ /*
+ * Do not explicitly set ubwc config register.
+ * Power on default values are taking care of required
+ * register settings.
+ */
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x5F88, /* SPECIFIC_IBL_WR_ENCCTL_LOW */
+ .value = 1,
+ },
+ },
+
+ {
+ .port_type = CAM_CAMNOC_JPEG,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2630, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */
+ .value = 0x22222222,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2634, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */
+ .value = 0x22222222,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2638, /* SPECIFIC_JPEG_URGENCY_LOW */
+ .value = 0x22,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2640, /* SPECIFIC_JPEG_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x2648, /* SPECIFIC_JPEG_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+ },
+ {
+ .port_type = CAM_CAMNOC_FD,
+ .enable = true,
+ .priority_lut_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E30, /* SPECIFIC_FD_PRIORITYLUT_LOW */
+ .value = 0x44444444,
+ },
+ .priority_lut_high = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E34, /* SPECIFIC_FD_PRIORITYLUT_HIGH */
+ .value = 0x44444444,
+ },
+ .urgency = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E38, /* SPECIFIC_FD_URGENCY_LOW */
+ .value = 0x44,
+ },
+ .danger_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E40, /* SPECIFIC_FD_DANGERLUT_LOW */
+ .value = 0x0,
+ },
+ .safe_lut = {
+ .enable = false,
+ .access_type = CAM_REG_TYPE_READ_WRITE,
+ .masked_value = 0,
+ .offset = 0x3E48, /* SPECIFIC_FD_SAFELUT_LOW */
+ .value = 0x0,
+ },
+ .ubwc_ctl = {
+ .enable = false,
+ },
+
+ },
+ {
+ /*SidebandManager_main_SidebandManager_FlagOutSet0_Low*/
+ .port_type = CAM_CAMNOC_ICP,
+ .enable = true,
+ .flag_out_set0_low = {
+ .enable = true,
+ .access_type = CAM_REG_TYPE_WRITE,
+ .masked_value = 0,
+ .offset = 0x2288,
+ .value = 0x100000,
+ },
+ },
+};
+
+static struct cam_camnoc_err_logger_info cam175_cpas120_err_logger_offsets = {
+ .mainctrl = 0x4F08, /* ERRLOGGER_MAINCTL_LOW */
+ .errvld = 0x4F10, /* ERRLOGGER_ERRVLD_LOW */
+ .errlog0_low = 0x4F20, /* ERRLOGGER_ERRLOG0_LOW */
+ .errlog0_high = 0x4F24, /* ERRLOGGER_ERRLOG0_HIGH */
+ .errlog1_low = 0x4F28, /* ERRLOGGER_ERRLOG1_LOW */
+ .errlog1_high = 0x4F2c, /* ERRLOGGER_ERRLOG1_HIGH */
+ .errlog2_low = 0x4F30, /* ERRLOGGER_ERRLOG2_LOW */
+ .errlog2_high = 0x4F34, /* ERRLOGGER_ERRLOG2_HIGH */
+ .errlog3_low = 0x4F38, /* ERRLOGGER_ERRLOG3_LOW */
+ .errlog3_high = 0x4F3c, /* ERRLOGGER_ERRLOG3_HIGH */
+};
+
+static struct cam_cpas_hw_errata_wa_list cam175_cpas120_errata_wa_list = {
+ .camnoc_flush_slave_pending_trans = {
+ .enable = false,
+ .data.reg_info = {
+ .access_type = CAM_REG_TYPE_READ,
+ .offset = 0x2300, /* SidebandManager_SenseIn0_Low */
+ .mask = 0xE0000, /* Bits 17, 18, 19 */
+ .value = 0, /* expected to be 0 */
+ },
+ },
+};
+
+static struct cam_camnoc_info cam175_cpas120_camnoc_info = {
+ .specific = &cam_cpas_v175_120_camnoc_specific[0],
+ .specific_size = sizeof(cam_cpas_v175_120_camnoc_specific) /
+ sizeof(cam_cpas_v175_120_camnoc_specific[0]),
+ .irq_sbm = &cam_cpas_v175_120_irq_sbm,
+ .irq_err = &cam_cpas_v175_120_irq_err[0],
+ .irq_err_size = sizeof(cam_cpas_v175_120_irq_err) /
+ sizeof(cam_cpas_v175_120_irq_err[0]),
+ .err_logger = &cam175_cpas120_err_logger_offsets,
+ .errata_wa_list = &cam175_cpas120_errata_wa_list,
+};
+
+#endif /* _CPASTOP_V175_120_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/Makefile b/drivers/media/platform/msm/camera_v3/cam_fd/Makefile
index ed896e511963..2e4511d2b48f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw_mgr/
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile
index d6e76d18e799..61c255e75158 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += fd_hw/
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index ec0a906cb99a..8403d4dbe533 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,8 @@
static struct cam_fd_hw_mgr g_fd_hw_mgr;
-static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet)
+static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet,
+ size_t remain_len)
{
struct cam_cmd_buf_desc *cmd_desc = NULL;
int i, rc;
@@ -50,7 +51,7 @@ static int cam_fd_mgr_util_packet_validate(struct cam_packet *packet)
packet->patch_offset, packet->num_patches,
packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index);
- if (cam_packet_util_validate_packet(packet)) {
+ if (cam_packet_util_validate_packet(packet, remain_len)) {
CAM_ERR(CAM_FD, "invalid packet:%d %d %d %d %d",
packet->kmd_cmd_buf_index,
packet->num_cmd_buf, packet->cmd_buf_offset,
@@ -162,8 +163,10 @@ static int cam_fd_mgr_util_put_frame_req(
mutex_lock(&g_fd_hw_mgr.frame_req_mutex);
req_ptr = *frame_req;
- if (req_ptr)
+ if (req_ptr) {
+ list_del_init(&req_ptr->list);
list_add_tail(&req_ptr->list, src_list);
+ }
*frame_req = NULL;
mutex_unlock(&g_fd_hw_mgr.frame_req_mutex);
@@ -608,7 +611,13 @@ static int cam_fd_mgr_util_prepare_io_buf_info(int32_t iommu_hdl,
rc);
return rc;
}
-
+ if (io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_FD,
+ "Invalid cpu buf %d %d %d",
+ io_cfg[i].direction,
+ io_cfg[i].resource_type, plane);
+ return -EINVAL;
+ }
cpu_addr[plane] += io_cfg[i].offsets[plane];
}
@@ -1444,6 +1453,16 @@ unlock_dev_flush_ctx:
for (i = 0; i < flush_args->num_req_pending; i++) {
flush_req = (struct cam_fd_mgr_frame_request *)
flush_args->flush_req_pending[i];
+ CAM_DBG(CAM_FD, "flush pending req %llu",
+ flush_req->request_id);
+ cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list,
+ &flush_req);
+ }
+
+ for (i = 0; i < flush_args->num_req_active; i++) {
+ flush_req = (struct cam_fd_mgr_frame_request *)
+ flush_args->flush_req_active[i];
+ CAM_DBG(CAM_FD, "flush active req %llu", flush_req->request_id);
cam_fd_mgr_util_put_frame_req(&hw_mgr->frame_free_list,
&flush_req);
}
@@ -1559,7 +1578,8 @@ static int cam_fd_mgr_hw_prepare_update(void *hw_mgr_priv,
goto error;
}
- rc = cam_fd_mgr_util_packet_validate(prepare->packet);
+ rc = cam_fd_mgr_util_packet_validate(prepare->packet,
+ prepare->remain_len);
if (rc) {
CAM_ERR(CAM_FD, "Error in packet validation %d", rc);
goto error;
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile
index 7fe5a4067d02..389ca4c66b8d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += cam_fd_hw_dev.o cam_fd_hw_core.o cam_fd_hw_soc.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
index 12d3c6bf1060..4084c43c2902 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -427,6 +427,7 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
unsigned long flags;
int i;
+ mutex_lock(&fd_hw->hw_mutex);
spin_lock_irqsave(&fd_core->spin_lock, flags);
if ((fd_core->core_state != CAM_FD_CORE_STATE_IDLE) ||
(fd_core->results_valid == false) ||
@@ -436,6 +437,7 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
fd_core->core_state, fd_core->results_valid,
fd_core->hw_req_private);
spin_unlock_irqrestore(&fd_core->spin_lock, flags);
+ mutex_unlock(&fd_hw->hw_mutex);
return -EINVAL;
}
fd_core->core_state = CAM_FD_CORE_STATE_READING_RESULTS;
@@ -516,6 +518,7 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
fd_core->hw_req_private = NULL;
fd_core->core_state = CAM_FD_CORE_STATE_IDLE;
spin_unlock_irqrestore(&fd_core->spin_lock, flags);
+ mutex_unlock(&fd_hw->hw_mutex);
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
index c7ef37c65659..d4c9326ed5ab 100644
--- a/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -206,6 +206,10 @@ static const struct of_device_id cam_fd_hw_dt_match[] = {
.compatible = "qcom,fd501",
.data = &cam_fd_wrapper200_core501_info,
},
+ {
+ .compatible = "qcom,fd501",
+ .data = &cam_fd_wrapper200_core501_info,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cam_fd_hw_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h
index 38137b89295e..9f81c9c7feb0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/fw_inc/hfi_session_defs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -472,7 +472,6 @@ struct ica_stab_params {
struct frame_set {
struct frame_buffer buffers[IPE_IO_IMAGES_MAX];
- struct ica_stab_params ica_params;
uint32_t cdm_ica1_addr;
uint32_t cdm_ica2_addr;
} __packed;
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c b/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
index da1bf9e52ce8..bf80938985f1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,6 +42,9 @@
#define HFI_MAX_POLL_TRY 5
+#define HFI_MAX_PC_POLL_TRY 150
+#define HFI_POLL_TRY_SLEEP 2
+
static struct hfi_info *g_hfi;
unsigned int g_icp_mmu_hdl;
static DEFINE_MUTEX(hfi_cmd_q_mutex);
@@ -513,8 +516,8 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
uint32_t val;
uint32_t try = 0;
- while (try < HFI_MAX_POLL_TRY) {
- data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
+ while (try < HFI_MAX_PC_POLL_TRY) {
+ data = cam_io_r_mb(icp_base + HFI_REG_A5_CSR_A5_STATUS);
CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);
if (data & ICP_CSR_A5_STATUS_WFI)
@@ -523,7 +526,7 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
* and Host can the proceed. No interrupt is expected from FW
* at this time.
*/
- msleep(100);
+ msleep_interruptible(HFI_POLL_TRY_SLEEP);
try++;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c
index b969c92ccbc8..a330cff293d6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -226,6 +226,13 @@ static int cam_bps_cmd_reset(struct cam_hw_soc_info *soc_info,
bool reset_bps_top_fail = false;
CAM_DBG(CAM_ICP, "CAM_ICP_BPS_CMD_RESET");
+
+ if (!core_info->clk_enable || !core_info->cpas_start) {
+ CAM_ERR(CAM_ICP, "BPS reset failed. clk_en %d cpas_start %d",
+ core_info->clk_enable, core_info->cpas_start);
+ return -EINVAL;
+ }
+
/* Reset BPS CDM core*/
cam_io_w_mb((uint32_t)0xF,
soc_info->reg_map[0].mem_base + BPS_CDM_RST_CMD);
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 73e42de3fa03..3a2d854fb1f4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -62,6 +62,8 @@
static struct cam_icp_hw_mgr icp_hw_mgr;
+static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl);
+
static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
{
struct cam_hw_intf *a5_dev_intf = NULL;
@@ -1834,12 +1836,13 @@ static int cam_icp_mgr_process_fatal_error(
if (event_notify->event_id == HFI_EVENT_SYS_ERROR) {
CAM_INFO(CAM_ICP, "received HFI_EVENT_SYS_ERROR");
rc = cam_icp_mgr_trigger_recovery(hw_mgr);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
}
return rc;
}
-static void cam_icp_mgr_process_dbg_buf(void)
+static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl)
{
uint32_t *msg_ptr = NULL, *pkt_ptr = NULL;
struct hfi_msg_debug *dbg_msg;
@@ -1861,6 +1864,8 @@ static void cam_icp_mgr_process_dbg_buf(void)
timestamp = ((((uint64_t)(dbg_msg->timestamp_hi) << 32)
| dbg_msg->timestamp_lo) >> 16);
trace_cam_icp_fw_dbg(dbg_buf, timestamp/2);
+ if (!debug_lvl)
+ CAM_INFO(CAM_ICP, "FW_DBG:%s", dbg_buf);
}
size_processed += (pkt_ptr[ICP_PACKET_SIZE] >>
BYTE_WORD_SHIFT);
@@ -1986,9 +1991,7 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data)
}
}
- if (icp_hw_mgr.a5_debug_type ==
- HFI_DEBUG_MODE_QUEUE)
- cam_icp_mgr_process_dbg_buf();
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
if ((task_data->irq_status & A5_WDT_0) ||
(task_data->irq_status & A5_WDT_1)) {
@@ -2469,7 +2472,7 @@ static int cam_icp_mgr_abort_handle(
int rc = 0;
unsigned long rem_jiffies;
size_t packet_size;
- int timeout = 100;
+ int timeout = 1000;
struct hfi_cmd_ipebps_async *abort_cmd;
packet_size =
@@ -2508,6 +2511,7 @@ static int cam_icp_mgr_abort_handle(
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command");
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -2519,7 +2523,7 @@ static int cam_icp_mgr_destroy_handle(
struct cam_icp_hw_ctx_data *ctx_data)
{
int rc = 0;
- int timeout = 100;
+ int timeout = 1000;
unsigned long rem_jiffies;
size_t packet_size;
struct hfi_cmd_ipebps_async *destroy_cmd;
@@ -2562,9 +2566,7 @@ static int cam_icp_mgr_destroy_handle(
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timeout: %d for %u",
rc, ctx_data->ctx_id);
- if (icp_hw_mgr.a5_debug_type ==
- HFI_DEBUG_MODE_QUEUE)
- cam_icp_mgr_process_dbg_buf();
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
kfree(destroy_cmd);
@@ -2871,6 +2873,7 @@ static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
@@ -3122,6 +3125,7 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -3333,12 +3337,32 @@ static int cam_icp_mgr_pkt_validation(struct cam_packet *packet)
return 0;
}
+static int cam_icp_mgr_put_cmd_buf(struct cam_packet *packet)
+{
+ int i = 0;
+ struct cam_cmd_buf_desc *cmd_desc = NULL;
+
+ 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_FW) {
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_ICP, "put cmd buf failed: 0x%x",
+ cmd_desc[i].mem_handle);
+ }
+ }
+
+ 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;
@@ -3352,32 +3376,39 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
*fw_cmd_buf_iova_addr = 0;
- for (i = 0; i < packet->num_cmd_buf; i++) {
+ 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);
- return rc;
+ goto rel_cmd_buf;
}
*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) {
+ if (rc || !cpu_addr) {
CAM_ERR(CAM_ICP, "get cmd buf failed %x",
hw_mgr->iommu_hdl);
*fw_cmd_buf_iova_addr = 0;
- return rc;
+ goto rel_cmd_buf;
+ }
+ 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");
+ goto rel_cmd_buf;
}
cpu_addr = cpu_addr + cmd_desc[i].offset;
}
}
if (!cpu_addr) {
- CAM_ERR(CAM_ICP, "Invalid cpu addr");
+ CAM_ERR(CAM_ICP, "invalid number of cmd buf");
return -EINVAL;
}
@@ -3425,6 +3456,18 @@ static int cam_icp_mgr_process_cmd_desc(struct cam_icp_hw_mgr *hw_mgr,
}
return rc;
+
+rel_cmd_buf:
+ for (i = num_cmd_buf; i >= 0; i--) {
+ if (cmd_desc[i].type == CAM_CMD_BUF_FW) {
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle)) {
+ CAM_WARN(CAM_ICP, "put cmd buf failed 0x%x",
+ cmd_desc[i].mem_handle);
+ }
+ }
+ }
+
+ return rc;
}
static int cam_icp_mgr_process_io_cfg(struct cam_icp_hw_mgr *hw_mgr,
@@ -3847,9 +3890,12 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet,
}
CAM_INFO(CAM_ICP,
- "pln %d w %d h %d size %d addr 0x%x offset 0x%x memh %x",
- j, io_cfg[i].planes[j].width,
+ "pln %d dir %d w %d h %d s %u sh %u sz %d addr 0x%x off 0x%x memh %x",
+ j, io_cfg[i].direction,
+ io_cfg[i].planes[j].width,
io_cfg[i].planes[j].height,
+ io_cfg[i].planes[j].plane_stride,
+ io_cfg[i].planes[j].slice_height,
(int32_t)src_buf_size,
(unsigned int)iova_addr,
io_cfg[i].offsets[j],
@@ -3936,6 +3982,9 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
packet = prepare_args->packet;
+ if (cam_packet_util_validate_packet(packet, prepare_args->remain_len))
+ return -EINVAL;
+
rc = cam_icp_mgr_pkt_validation(packet);
if (rc) {
mutex_unlock(&ctx_data->ctx_mutex);
@@ -3992,6 +4041,7 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u",
packet->header.request_id, ctx_data->ctx_id);
+ cam_icp_mgr_put_cmd_buf(packet);
mutex_unlock(&ctx_data->ctx_mutex);
return rc;
}
@@ -4300,6 +4350,7 @@ static int cam_icp_mgr_create_handle(uint32_t dev_type,
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -4346,6 +4397,7 @@ static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data)
if (!rem_jiffies) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
cam_hfi_queue_dump();
}
@@ -4619,6 +4671,7 @@ get_io_buf_failed:
hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
acquire_info_failed:
cam_icp_mgr_put_ctx(ctx_data);
+ cam_icp_mgr_process_dbg_buf(icp_hw_mgr.a5_dbg_lvl);
mutex_unlock(&ctx_data->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
@@ -4898,6 +4951,7 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
hw_mgr->iommu_sec_hdl,
hw_cmd_args->u.pf_args.buf_info,
hw_cmd_args->u.pf_args.mem_found);
+
break;
default:
CAM_ERR(CAM_ICP, "Invalid cmd");
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 234643e3d105..5a93df33925f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -128,11 +128,11 @@ struct clk_work_data {
};
/**
- * struct icp_frame_info
- * @request_id: request id
- * @io_config: the address of io config
- * @hfi_cfg_io_cmd: command struct to be sent to hfi
- */
+ * struct icp_frame_info
+ * @request_id: request id
+ * @io_config: the address of io config
+ * @hfi_cfg_io_cmd: command struct to be sent to hfi
+ */
struct icp_frame_info {
uint64_t request_id;
uint64_t io_config;
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index 7bb9b9ed18a2..2ebe41417d1d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,7 +23,7 @@
#define CAM_ICP_A5_BW_BYTES_VOTE 40000000
-#define CAM_ICP_CTX_MAX 36
+#define CAM_ICP_CTX_MAX 54
#define CPAS_IPE1_BIT 0x2000
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c
index 142fcdc6017d..1f71c7d4cd36 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -222,6 +222,12 @@ static int cam_ipe_cmd_reset(struct cam_hw_soc_info *soc_info,
bool reset_ipe_top_fail = false;
CAM_DBG(CAM_ICP, "CAM_ICP_IPE_CMD_RESET");
+ if (!core_info->clk_enable || !core_info->cpas_start) {
+ CAM_ERR(CAM_HFI, "IPE reset failed. clk_en %d cpas_start %d",
+ core_info->clk_enable, core_info->cpas_start);
+ return -EINVAL;
+ }
+
/* IPE CDM core reset*/
cam_io_w_mb((uint32_t)0xF,
soc_info->reg_map[0].mem_base + IPE_CDM_RST_CMD);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
index 113e1a8d5298..3e8fe117ac2d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -29,16 +29,6 @@
static const char isp_dev_name[] = "isp";
-char *substate_name[8] = {
- "CAM_ISP_CTX_ACTIVATED_SOF",
- "CAM_ISP_CTX_ACTIVATED_APPLIED",
- "CAM_ISP_CTX_ACTIVATED_EPOCH",
- "CAM_ISP_CTX_ACTIVATED_BUBBLE",
- "CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED",
- "CAM_ISP_CTX_ACTIVATED_HW_ERROR",
- "CAM_ISP_CTX_ACTIVATED_HALT",
- "CAM_ISP_CTX_ACTIVATED_MAX",
-};
#define INC_STATE_MONITOR_HEAD(head) \
(atomic64_add_return(1, head) % \
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES)
@@ -139,6 +129,8 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
size_t len = 0;
uint32_t *buf_addr;
uint32_t *buf_start, *buf_end;
+ size_t remain_len = 0;
+ bool need_put = false;
for (i = 0; i < req_isp->num_cfg; i++) {
rc = cam_packet_util_get_cmd_mem_addr(
@@ -148,17 +140,35 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
"Failed to get_cmd_mem_addr, rc=%d",
rc);
} else {
+ if (req_isp->cfg[i].offset >= len) {
+ CAM_ERR(CAM_ISP, "Invalid offset");
+ need_put = true;
+ goto put;
+ }
+ remain_len = len - req_isp->cfg[i].offset;
+
+ if (req_isp->cfg[i].len > remain_len) {
+ CAM_ERR(CAM_ISP, "Invalid offset");
+ need_put = true;
+ }
+put:
+ if (need_put) {
+ if (cam_mem_put_cpu_buf(req_isp->cfg[i].handle))
+ CAM_WARN(CAM_ISP,
+ "Failed to put cpu buf: 0x%x",
+ req_isp->cfg[i].handle);
+ need_put = false;
+ continue;
+ }
+
buf_start = (uint32_t *)((uint8_t *) buf_addr +
req_isp->cfg[i].offset);
buf_end = (uint32_t *)((uint8_t *) buf_start +
req_isp->cfg[i].len - 1);
- if (len < (buf_end - buf_start + 1)) {
- CAM_DBG(CAM_ISP,
- "Invalid len %zu, buf_start-end=%d",
- len, (buf_end - buf_start + 1));
- continue;
- }
cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
+ if (cam_mem_put_cpu_buf(req_isp->cfg[i].handle))
+ CAM_WARN(CAM_ISP, "Failed to put cpu buf: 0x%x",
+ req_isp->cfg[i].handle);
}
}
}
@@ -426,11 +436,12 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
}
if (!req_isp->bubble_detected) {
- CAM_INFO(CAM_ISP,
- "Sync with success: req %lld res 0x%x fd 0x%x",
+ CAM_DBG(CAM_ISP,
+ "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u",
req->request_id,
req_isp->fence_map_out[j].resource_handle,
- req_isp->fence_map_out[j].sync_id);
+ req_isp->fence_map_out[j].sync_id,
+ ctx->ctx_id);
rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
CAM_SYNC_STATE_SIGNALED_SUCCESS);
@@ -438,11 +449,12 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
rc);
} else if (!req_isp->bubble_report) {
- CAM_INFO(CAM_ISP,
- "Sync with failure: req %lld res 0x%x fd 0x%x",
+ CAM_ERR(CAM_ISP,
+ "Sync with failure: req %lld res 0x%x fd 0x%x, ctx %u",
req->request_id,
req_isp->fence_map_out[j].resource_handle,
- req_isp->fence_map_out[j].sync_id);
+ req_isp->fence_map_out[j].sync_id,
+ ctx->ctx_id);
rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
CAM_SYNC_STATE_SIGNALED_ERROR);
@@ -463,9 +475,9 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
continue;
}
- CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x",
+ CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x ctx %u",
req->request_id,
- req_isp->fence_map_out[j].sync_id);
+ req_isp->fence_map_out[j].sync_id, ctx->ctx_id);
if (!rc) {
req_isp->num_acked++;
req_isp->fence_map_out[j].sync_id = -1;
@@ -475,9 +487,9 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
if (req_isp->num_acked > req_isp->num_fence_map_out) {
/* Should not happen */
CAM_ERR(CAM_ISP,
- "WARNING: req_id %lld num_acked %d > map_out %d",
+ "WARNING: req_id %lld num_acked %d > map_out %d, ctx %u",
req->request_id, req_isp->num_acked,
- req_isp->num_fence_map_out);
+ req_isp->num_fence_map_out, ctx->ctx_id);
WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out);
}
@@ -491,17 +503,18 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
req_isp->bubble_detected = false;
list_del_init(&req->list);
list_add(&req->list, &ctx->pending_req_list);
+ atomic_set(&ctx_isp->process_bubble, 0);
CAM_DBG(CAM_REQ,
- "Move active request %lld to pending list(cnt = %d) [bubble recovery]",
- req->request_id, ctx_isp->active_req_cnt);
+ "Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
} else {
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->free_req_list);
CAM_DBG(CAM_REQ,
- "Move active request %lld to free list(cnt = %d) [all fences done]",
- req->request_id, ctx_isp->active_req_cnt);
+ "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
}
end:
@@ -571,7 +584,6 @@ static void __cam_isp_ctx_send_sof_timestamp(
static int __cam_isp_ctx_reg_upd_in_epoch_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
- CAM_INFO(CAM_ISP, "state = %s IRQ is RUP", substate_name[ctx_isp->substate_activated]);
if (ctx_isp->frame_id == 1)
CAM_DBG(CAM_ISP, "Reg update for early PCR");
else
@@ -589,7 +601,6 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_ctx_req *req_isp;
- CAM_INFO(CAM_ISP, "state = %s IRQ is RUP", substate_name[ctx_isp->substate_activated]);
if (list_empty(&ctx->wait_req_list)) {
CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
goto end;
@@ -602,14 +613,15 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
if (req_isp->num_fence_map_out != 0) {
list_add_tail(&req->list, &ctx->active_req_list);
ctx_isp->active_req_cnt++;
- CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
+ CAM_DBG(CAM_REQ,
+ "move request %lld to active list(cnt = %d), ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
} else {
/* no io config, so the request is completed. */
list_add_tail(&req->list, &ctx->free_req_list);
CAM_DBG(CAM_ISP,
- "move active request %lld to free list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
+ "move active request %lld to free list(cnt = %d), ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
}
/*
@@ -617,7 +629,6 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
* state so change substate here.
*/
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
@@ -633,7 +644,6 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
struct cam_ctx_request *req;
uint64_t request_id = 0;
- CAM_INFO(CAM_ISP, "state = %s IRQ is EPOCH", substate_name[ctx_isp->substate_activated]);
/*
* notify reqmgr with sof signal. Note, due to scheduling delay
* we can run into situation that two active requests has already
@@ -650,8 +660,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
notify.trigger = CAM_TRIGGER_POINT_SOF;
ctx->ctx_crm_intf->notify_trigger(&notify);
- CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
- ctx_isp->frame_id);
+ CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld ctx %u",
+ ctx_isp->frame_id, ctx->ctx_id);
}
list_for_each_entry(req, &ctx->active_req_list, list) {
@@ -668,7 +678,9 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
} else {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Can not notify SOF to CRM for ctx %u",
+ ctx->ctx_id);
rc = -EFAULT;
}
@@ -693,14 +705,14 @@ static int __cam_isp_ctx_notify_eof_in_activated_state(
notify.trigger = CAM_TRIGGER_POINT_EOF;
ctx->ctx_crm_intf->notify_trigger(&notify);
- CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld\n",
- ctx_isp->frame_id);
+ CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld ctx %u",
+ ctx_isp->frame_id, ctx->ctx_id);
} else {
- CAM_ERR(CAM_ISP, "Can not notify EOF to CRM");
+ CAM_ERR(CAM_ISP, "Can not notify EOF to CRM for ctx %u",
+ ctx->ctx_id);
rc = -EFAULT;
}
- CAM_INFO(CAM_ISP, "state = %s IRQ is EOF", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -708,7 +720,6 @@ static int __cam_isp_ctx_reg_upd_in_hw_error(
struct cam_isp_context *ctx_isp, void *evt_data)
{
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return 0;
}
@@ -733,11 +744,8 @@ static int __cam_isp_ctx_sof_in_activated_state(
ctx_isp->boot_timestamp = sof_event_data->boot_time;
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
- CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
- ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
- CAM_INFO(CAM_ISP, "state = %s IRQ is SOF frame_id = %lld",
- substate_name[ctx_isp->substate_activated], ctx_isp->frame_id);
-
+ CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u",
+ ctx_isp->frame_id, ctx_isp->sof_timestamp_val, ctx->ctx_id);
return rc;
}
@@ -775,7 +783,6 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
req->request_id);
}
- CAM_INFO(CAM_ISP, "state = %s IRQ is RUP", substate_name[ctx_isp->substate_activated]);
end:
return rc;
}
@@ -788,7 +795,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
- CAM_INFO(CAM_ISP, "state = %s IRQ is EPOCH", substate_name[ctx_isp->substate_activated]);
if (list_empty(&ctx->wait_req_list)) {
/*
* If no wait req in epoch, this is an error case.
@@ -796,7 +802,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
*/
CAM_ERR(CAM_ISP, "No wait request");
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* Send SOF event as empty frame*/
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
@@ -820,8 +825,9 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
notify.req_id = req->request_id;
notify.error = CRM_KMD_ERR_BUBBLE;
ctx->ctx_crm_intf->notify_err(&notify);
- CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
- ctx_isp->frame_id);
+ atomic_set(&ctx_isp->process_bubble, 1);
+ CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld, ctx %u",
+ ctx_isp->frame_id, ctx->ctx_id);
} else {
req_isp->bubble_report = 0;
}
@@ -830,8 +836,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
* Always move the request to active list. Let buf done
* function handles the rest.
*/
- CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
- req->request_id, ctx_isp->active_req_cnt);
+ CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d), ctx %u",
+ req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
ctx_isp->active_req_cnt++;
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->active_req_list);
@@ -844,7 +850,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
CAM_REQ_MGR_SOF_EVENT_ERROR);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
end:
@@ -868,7 +873,6 @@ static int __cam_isp_ctx_buf_done_in_applied(struct cam_isp_context *ctx_isp,
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
return rc;
}
@@ -882,9 +886,6 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
struct cam_ctx_request *req;
- CAM_INFO(CAM_ISP, "SURESH: state = %s IRQ is SOF frame_id = %lld",
- substate_name[ctx_isp->substate_activated], ctx_isp->frame_id);
-
if (!evt_data) {
CAM_ERR(CAM_ISP, "in valid sof event data");
return -EINVAL;
@@ -898,7 +899,6 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
else
CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
req = list_last_entry(&ctx->active_req_list,
struct cam_ctx_request, list);
@@ -919,7 +919,6 @@ static int __cam_isp_ctx_buf_done_in_epoch(struct cam_isp_context *ctx_isp,
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
return rc;
}
@@ -931,7 +930,6 @@ static int __cam_isp_ctx_buf_done_in_bubble(
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
return rc;
}
@@ -944,7 +942,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
struct cam_context *ctx = ctx_isp->base;
uint64_t request_id = 0;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
/*
* This means we missed the reg upd ack. So we need to
* transition to BUBBLE state again.
@@ -960,7 +957,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
goto end;
}
@@ -979,8 +975,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
notify.error = CRM_KMD_ERR_BUBBLE;
ctx->ctx_crm_intf->notify_err(&notify);
CAM_DBG(CAM_REQ,
- "Notify CRM about Bubble req_id %llu frame %lld",
- req->request_id, ctx_isp->frame_id);
+ "Notify CRM about Bubble req_id %llu frame %lld, ctx %u",
+ req->request_id, ctx_isp->frame_id, ctx->ctx_id);
} else {
req_isp->bubble_report = 0;
}
@@ -989,7 +985,7 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
* Always move the request to active list. Let buf done
* function handles the rest.
*/
- CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
+ CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d) ctx %u",
req->request_id, ctx_isp->active_req_cnt);
ctx_isp->active_req_cnt++;
list_del_init(&req->list);
@@ -1009,7 +1005,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request,
@@ -1027,7 +1022,6 @@ static int __cam_isp_ctx_buf_done_in_bubble_applied(
struct cam_isp_hw_done_event_data *done =
(struct cam_isp_hw_done_event_data *) evt_data;
- CAM_INFO(CAM_ISP, "state = %s IRQ is BUF_DONE", substate_name[ctx_isp->substate_activated]);
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
@@ -1050,6 +1044,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
struct cam_req_mgr_error_notify notify;
uint64_t error_request_id = 0;
struct cam_hw_fence_map_entry *fence_map_out = NULL;
+ struct cam_req_mgr_message req_msg;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_hw_error_event_data *error_event_data =
@@ -1084,7 +1079,9 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
}
req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv;
- cam_isp_ctx_dump_req(req_isp);
+
+ if (error_event_data->enable_reg_dump)
+ cam_isp_ctx_dump_req(req_isp);
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req_to_dump->request_id);
@@ -1096,9 +1093,11 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
for (i = 0; i < req_isp->num_fence_map_out; i++) {
fence_map_out =
&req_isp->fence_map_out[i];
- CAM_ERR(CAM_ISP, "req %llu, Sync fd %x",
+ CAM_ERR(CAM_ISP,
+ "req %llu, Sync fd 0x%x ctx %u",
req->request_id,
- req_isp->fence_map_out[i].sync_id);
+ req_isp->fence_map_out[i].sync_id,
+ ctx->ctx_id);
if (req_isp->fence_map_out[i].sync_id != -1) {
rc = cam_sync_signal(
fence_map_out->sync_id,
@@ -1125,9 +1124,11 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
for (i = 0; i < req_isp->num_fence_map_out; i++) {
fence_map_out =
&req_isp->fence_map_out[i];
- CAM_ERR(CAM_ISP, "req %llu, Sync fd %x",
+ CAM_ERR(CAM_ISP,
+ "req %llu, Sync fd 0x%x ctx %u",
req->request_id,
- req_isp->fence_map_out[i].sync_id);
+ req_isp->fence_map_out[i].sync_id,
+ ctx->ctx_id);
if (req_isp->fence_map_out[i].sync_id != -1) {
rc = cam_sync_signal(
fence_map_out->sync_id,
@@ -1214,14 +1215,39 @@ end:
notify.error = CRM_KMD_ERR_FATAL;
}
- CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld\n",
- error_request_id, ctx_isp->frame_id);
+ CAM_WARN(CAM_ISP, "Notify CRM: req %lld, frame %lld ctx %u",
+ error_request_id, ctx_isp->frame_id, ctx->ctx_id);
ctx->ctx_crm_intf->notify_err(&notify);
+
+ /*
+ * Need to send error occurred in KMD
+ * This will help UMD to take necessary action
+ * and to dump relevant info
+ */
+
+ if (notify.error == CRM_KMD_ERR_OVERFLOW) {
+ req_msg.session_hdl = ctx_isp->base->session_hdl;
+ req_msg.u.err_msg.device_hdl = ctx_isp->base->dev_hdl;
+ req_msg.u.err_msg.error_type =
+ CAM_REQ_MGR_ERROR_TYPE_RECOVERY;
+ req_msg.u.err_msg.link_hdl = ctx_isp->base->link_hdl;
+ req_msg.u.err_msg.request_id = error_request_id;
+ req_msg.u.err_msg.resource_size = 0x0;
+
+ if (cam_req_mgr_notify_message(&req_msg,
+ V4L_EVENT_CAM_REQ_MGR_ERROR,
+ V4L_EVENT_CAM_REQ_MGR_EVENT))
+ CAM_ERR(CAM_ISP,
+ "Error in notifying the error time for req id:%lld ctx %u",
+ ctx_isp->last_applied_req_id,
+ ctx->ctx_id);
+ }
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HW_ERROR;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
} else {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify ERRROR to CRM");
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Can not notify ERRROR to CRM for ctx %u",
+ ctx->ctx_id);
rc = -EFAULT;
}
@@ -1230,6 +1256,236 @@ end:
return rc;
}
+static int __cam_isp_ctx_fs2_sof_in_sof_state(
+ struct cam_isp_context *ctx_isp, void *evt_data)
+{
+ int rc = 0;
+ struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
+ struct cam_ctx_request *req;
+ struct cam_context *ctx = ctx_isp->base;
+ struct cam_req_mgr_trigger_notify notify;
+ uint64_t request_id = 0;
+
+
+ req = list_last_entry(&ctx->pending_req_list,
+ struct cam_ctx_request, list);
+
+ if (!evt_data) {
+ CAM_ERR(CAM_ISP, "in valid sof event data");
+ return -EINVAL;
+ }
+
+ ctx_isp->frame_id++;
+ ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+ ctx_isp->boot_timestamp = sof_event_data->boot_time;
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
+ CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+ ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+ if (!(list_empty(&ctx->wait_req_list)))
+ goto end;
+
+ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
+ ctx_isp->active_req_cnt <= 2) {
+ if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
+ notify.link_hdl = ctx->link_hdl;
+ notify.dev_hdl = ctx->dev_hdl;
+ notify.frame_id = ctx_isp->frame_id;
+ notify.trigger = CAM_TRIGGER_POINT_SOF;
+
+ ctx->ctx_crm_intf->notify_trigger(&notify);
+ CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
+ ctx_isp->frame_id);
+ }
+
+ list_for_each_entry(req, &ctx->active_req_list, list) {
+ if (req->request_id > ctx_isp->reported_req_id) {
+ request_id = req->request_id;
+ ctx_isp->reported_req_id = request_id;
+ break;
+ }
+ }
+
+ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+ CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ } else {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
+ rc = -EFAULT;
+ }
+
+end:
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_buf_done(struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+ struct cam_isp_hw_done_event_data *done =
+ (struct cam_isp_hw_done_event_data *) evt_data;
+ struct cam_context *ctx = ctx_isp->base;
+ int prev_active_req_cnt = 0;
+ int curr_req_id = 0;
+ struct cam_ctx_request *req;
+
+ prev_active_req_cnt = ctx_isp->active_req_cnt;
+ req = list_first_entry(&ctx->active_req_list,
+ struct cam_ctx_request, list);
+ if (req)
+ curr_req_id = req->request_id;
+
+ rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
+
+ if (prev_active_req_cnt == ctx_isp->active_req_cnt + 1) {
+ if (list_empty(&ctx->wait_req_list) &&
+ list_empty(&ctx->active_req_list)) {
+ CAM_DBG(CAM_ISP, "No request, move to SOF");
+ ctx_isp->substate_activated =
+ CAM_ISP_CTX_ACTIVATED_SOF;
+ if (ctx_isp->reported_req_id < curr_req_id) {
+ ctx_isp->reported_req_id = curr_req_id;
+ __cam_isp_ctx_send_sof_timestamp(ctx_isp,
+ curr_req_id,
+ CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_buf_done_in_epoch(struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+
+ rc = __cam_isp_ctx_fs2_buf_done(ctx_isp, evt_data);
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_buf_done_in_applied(
+ struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+
+ rc = __cam_isp_ctx_fs2_buf_done(ctx_isp, evt_data);
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
+ void *evt_data)
+{
+ int rc = 0;
+ struct cam_ctx_request *req = NULL;
+ struct cam_isp_ctx_req *req_isp;
+ struct cam_context *ctx = ctx_isp->base;
+
+ if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
+ CAM_DBG(CAM_ISP, "invalid RUP");
+ goto end;
+ }
+
+ /*
+ * This is for the first update. The initial setting will
+ * cause the reg_upd in the first frame.
+ */
+ if (!list_empty(&ctx->wait_req_list)) {
+ req = list_first_entry(&ctx->wait_req_list,
+ struct cam_ctx_request, list);
+ list_del_init(&req->list);
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ if (req_isp->num_fence_map_out == req_isp->num_acked)
+ list_add_tail(&req->list, &ctx->free_req_list);
+ else
+ CAM_ERR(CAM_ISP,
+ "receive rup in unexpected state");
+ }
+ if (req != NULL) {
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
+ req->request_id);
+ }
+end:
+ return rc;
+}
+
+static int __cam_isp_ctx_fs2_reg_upd_in_applied_state(
+ struct cam_isp_context *ctx_isp, void *evt_data)
+{
+ int rc = 0;
+ struct cam_ctx_request *req = NULL;
+ struct cam_context *ctx = ctx_isp->base;
+ struct cam_isp_ctx_req *req_isp;
+ struct cam_req_mgr_trigger_notify notify;
+ uint64_t request_id = 0;
+
+ if (list_empty(&ctx->wait_req_list)) {
+ CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request");
+ goto end;
+ }
+ req = list_first_entry(&ctx->wait_req_list,
+ struct cam_ctx_request, list);
+ list_del_init(&req->list);
+
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ if (req_isp->num_fence_map_out != 0) {
+ list_add_tail(&req->list, &ctx->active_req_list);
+ ctx_isp->active_req_cnt++;
+ CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
+ req->request_id, ctx_isp->active_req_cnt);
+ } else {
+ /* no io config, so the request is completed. */
+ list_add_tail(&req->list, &ctx->free_req_list);
+ }
+
+ /*
+ * This function only called directly from applied and bubble applied
+ * state so change substate here.
+ */
+ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
+ if (req_isp->num_fence_map_out != 1)
+ goto end;
+
+ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
+ ctx_isp->active_req_cnt <= 2) {
+ list_for_each_entry(req, &ctx->active_req_list, list) {
+ if (req->request_id > ctx_isp->reported_req_id) {
+ request_id = req->request_id;
+ ctx_isp->reported_req_id = request_id;
+ break;
+ }
+ }
+
+ __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
+ CAM_REQ_MGR_SOF_EVENT_SUCCESS);
+
+ if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
+ notify.link_hdl = ctx->link_hdl;
+ notify.dev_hdl = ctx->dev_hdl;
+ notify.frame_id = ctx_isp->frame_id;
+ notify.trigger = CAM_TRIGGER_POINT_SOF;
+
+ ctx->ctx_crm_intf->notify_trigger(&notify);
+ CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
+ ctx_isp->frame_id);
+ }
+ } else {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
+ rc = -EFAULT;
+ }
+
+ CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
+end:
+ if (req != NULL && !rc) {
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
+ req->request_id);
+ }
+ return rc;
+}
+
static struct cam_isp_ctx_irq_ops
cam_isp_ctx_activated_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
/* SOF */
@@ -1303,6 +1559,79 @@ static struct cam_isp_ctx_irq_ops
},
};
+static struct cam_isp_ctx_irq_ops
+ cam_isp_ctx_fs2_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
+ /* SOF */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_fs2_sof_in_sof_state,
+ __cam_isp_ctx_fs2_reg_upd_in_sof,
+ __cam_isp_ctx_fs2_sof_in_sof_state,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ NULL,
+ },
+ },
+ /* APPLIED */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_activated_state,
+ __cam_isp_ctx_fs2_reg_upd_in_applied_state,
+ __cam_isp_ctx_epoch_in_applied,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ __cam_isp_ctx_fs2_buf_done_in_applied,
+ },
+ },
+ /* EPOCH */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_epoch,
+ __cam_isp_ctx_reg_upd_in_epoch_state,
+ __cam_isp_ctx_notify_sof_in_activated_state,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ __cam_isp_ctx_fs2_buf_done_in_epoch,
+ },
+ },
+ /* BUBBLE */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_activated_state,
+ NULL,
+ __cam_isp_ctx_notify_sof_in_activated_state,
+ __cam_isp_ctx_notify_eof_in_activated_state,
+ __cam_isp_ctx_buf_done_in_bubble,
+ },
+ },
+ /* Bubble Applied */
+ {
+ .irq_ops = {
+ __cam_isp_ctx_handle_error,
+ __cam_isp_ctx_sof_in_activated_state,
+ __cam_isp_ctx_reg_upd_in_activated_state,
+ __cam_isp_ctx_epoch_in_bubble_applied,
+ NULL,
+ __cam_isp_ctx_buf_done_in_bubble_applied,
+ },
+ },
+ /* HW ERROR */
+ {
+ .irq_ops = {
+ NULL,
+ __cam_isp_ctx_sof_in_activated_state,
+ __cam_isp_ctx_reg_upd_in_hw_error,
+ NULL,
+ NULL,
+ NULL,
+ },
+ },
+ /* HALT */
+ {
+ },
+};
+
static int __cam_isp_ctx_apply_req_in_activated_state(
struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
uint32_t next_state)
@@ -1330,6 +1659,14 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
*/
ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+ if (atomic_read(&ctx_isp->process_bubble)) {
+ CAM_DBG(CAM_ISP,
+ "Processing bubble cannot apply Request Id %llu",
+ apply->request_id);
+ rc = -EAGAIN;
+ goto end;
+ }
+
spin_lock_bh(&ctx->lock);
req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
list);
@@ -1347,15 +1684,16 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
goto end;
}
- CAM_DBG(CAM_REQ, "Apply request %lld in substate %d", req->request_id,
- ctx_isp->substate_activated);
+ CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u",
+ req->request_id, ctx_isp->substate_activated, ctx->ctx_id);
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
if (ctx_isp->active_req_cnt >= 2) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "Reject apply request (id %lld) due to congestion(cnt = %d)",
+ "Reject apply request (id %lld) due to congestion(cnt = %d) ctx %u",
req->request_id,
- ctx_isp->active_req_cnt);
+ ctx_isp->active_req_cnt,
+ ctx->ctx_id);
spin_lock_bh(&ctx->lock);
if (!list_empty(&ctx->active_req_list))
@@ -1391,7 +1729,6 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
} else {
spin_lock_bh(&ctx->lock);
ctx_isp->substate_activated = next_state;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
ctx_isp->last_applied_req_id = apply->request_id;
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->wait_req_list);
@@ -1420,7 +1757,6 @@ static int __cam_isp_ctx_apply_req_in_sof(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -1437,7 +1773,6 @@ static int __cam_isp_ctx_apply_req_in_epoch(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -1454,7 +1789,6 @@ static int __cam_isp_ctx_apply_req_in_bubble(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -1528,13 +1862,10 @@ static int __cam_isp_ctx_flush_req_in_top_state(
struct cam_context *ctx,
struct cam_req_mgr_flush_request *flush_req)
{
- struct cam_isp_context *ctx_isp =
- (struct cam_isp_context *) ctx->ctx_priv;
- struct cam_isp_stop_args stop_isp;
- struct cam_hw_stop_args stop_args;
- struct cam_isp_start_args start_isp;
int rc = 0;
+ 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);
@@ -1546,47 +1877,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
spin_unlock_bh(&ctx->lock);
- if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
- /* if active and wait list are empty, return */
- spin_lock_bh(&ctx->lock);
- if ((list_empty(&ctx->wait_req_list)) &&
- (list_empty(&ctx->active_req_list))) {
- spin_unlock_bh(&ctx->lock);
- CAM_DBG(CAM_ISP, "active and wait list are empty");
- goto end;
- }
- spin_unlock_bh(&ctx->lock);
-
- /* Stop hw first before active list flush */
- stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
- stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY;
- stop_isp.stop_only = true;
- stop_args.args = (void *)&stop_isp;
- ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
- &stop_args);
-
- spin_lock_bh(&ctx->lock);
- CAM_DBG(CAM_ISP, "try to flush wait list");
- rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list,
- flush_req);
- CAM_DBG(CAM_ISP, "try to flush active list");
- rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list,
- flush_req);
- ctx_isp->active_req_cnt = 0;
- spin_unlock_bh(&ctx->lock);
-
- /* Start hw */
- start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx;
- start_isp.start_only = true;
- start_isp.hw_config.priv = NULL;
-
- rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
- &start_isp);
- }
-
-end:
- CAM_DBG(CAM_ISP, "Flush request in top state %d",
- ctx->state);
+ atomic_set(&ctx_isp->process_bubble, 0);
return rc;
}
@@ -1664,6 +1955,58 @@ static struct cam_ctx_ops
},
};
+static struct cam_ctx_ops
+ cam_isp_ctx_fs2_state_machine[CAM_ISP_CTX_ACTIVATED_MAX] = {
+ /* SOF */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {
+ .apply_req = __cam_isp_ctx_apply_req_in_sof,
+ },
+ .irq_ops = NULL,
+ },
+ /* APPLIED */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+ /* EPOCH */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {
+ .apply_req = __cam_isp_ctx_apply_req_in_epoch,
+ },
+ .irq_ops = NULL,
+ },
+ /* BUBBLE */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {
+ .apply_req = __cam_isp_ctx_apply_req_in_bubble,
+ },
+ .irq_ops = NULL,
+ },
+ /* Bubble Applied */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+ /* HW ERROR */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+ /* HALT */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
+};
+
static int __cam_isp_ctx_rdi_only_sof_in_top_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
@@ -1718,7 +2061,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state(
else
CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
return rc;
@@ -1741,7 +2083,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_applied_state(
ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
return 0;
@@ -1780,7 +2121,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
*/
CAM_ERR(CAM_ISP, "No wait request");
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* Send SOF event as empty frame*/
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
@@ -1835,7 +2175,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
/* change the state to bubble, as reg update has not come */
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
return 0;
@@ -1906,7 +2245,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
@@ -1924,7 +2262,6 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
uint64_t request_id = 0;
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* notify reqmgr with sof signal*/
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
if (list_empty(&ctx->wait_req_list)) {
@@ -1986,7 +2323,6 @@ error:
* to SOF sub state
*/
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return 0;
}
@@ -2069,7 +2405,6 @@ static int __cam_isp_ctx_rdi_only_apply_req_top_state(
rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
CAM_ISP_CTX_ACTIVATED_APPLIED);
CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
return rc;
}
@@ -2125,9 +2460,8 @@ static struct cam_ctx_ops
},
};
-/* top level state machine */
-static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
- struct cam_release_dev_cmd *cmd)
+static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
+ void *cmd)
{
int rc = 0;
struct cam_hw_release_args rel_arg;
@@ -2135,28 +2469,16 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
(struct cam_isp_context *) ctx->ctx_priv;
struct cam_req_mgr_flush_request flush_req;
- if (ctx->link_hdl != -1) {
- CAM_ERR(CAM_ISP, "ctx expects release dev after unlink");
- rc = -EAGAIN;
- return rc;
- }
-
- if (cmd && ctx_isp->hw_ctx && ctx_isp->split_acquire) {
- CAM_ERR(CAM_ISP, "ctx expects release HW before release dev");
- return rc;
- }
-
if (ctx_isp->hw_ctx) {
rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
&rel_arg);
ctx_isp->hw_ctx = NULL;
+ } else {
+ CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx");
}
- ctx->session_hdl = -1;
- ctx->dev_hdl = -1;
- ctx->link_hdl = -1;
- ctx->ctx_crm_intf = NULL;
+ ctx->last_flush_req = 0;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 0;
@@ -2168,7 +2490,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
* But we still add some sanity check code here to help the debug
*/
if (!list_empty(&ctx->active_req_list))
- CAM_ERR(CAM_ISP, "Active list is not empty");
+ CAM_WARN(CAM_ISP, "Active list is not empty");
/* Flush all the pending request list */
flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
@@ -2179,7 +2501,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
spin_lock_bh(&ctx->lock);
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
spin_unlock_bh(&ctx->lock);
- ctx->state = CAM_CTX_AVAILABLE;
+ ctx->state = CAM_CTX_ACQUIRED;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP, "Release device success[%u] next state %d",
@@ -2187,8 +2509,9 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
return rc;
}
-static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
- void *cmd)
+/* top level state machine */
+static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
+ struct cam_release_dev_cmd *cmd)
{
int rc = 0;
struct cam_hw_release_args rel_arg;
@@ -2196,15 +2519,23 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
(struct cam_isp_context *) ctx->ctx_priv;
struct cam_req_mgr_flush_request flush_req;
+ if (cmd && ctx_isp->hw_ctx) {
+ CAM_ERR(CAM_ISP, "releasing hw");
+ __cam_isp_ctx_release_hw_in_top_state(ctx, NULL);
+ }
+
if (ctx_isp->hw_ctx) {
rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
&rel_arg);
ctx_isp->hw_ctx = NULL;
- } else {
- CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx");
}
+ ctx->session_hdl = -1;
+ ctx->dev_hdl = -1;
+ ctx->link_hdl = -1;
+ ctx->ctx_crm_intf = NULL;
+ ctx->last_flush_req = 0;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 0;
@@ -2216,7 +2547,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
* But we still add some sanity check code here to help the debug
*/
if (!list_empty(&ctx->active_req_list))
- CAM_WARN(CAM_ISP, "Active list is not empty");
+ CAM_ERR(CAM_ISP, "Active list is not empty");
/* Flush all the pending request list */
flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
@@ -2227,7 +2558,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
spin_lock_bh(&ctx->lock);
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
spin_unlock_bh(&ctx->lock);
- ctx->state = CAM_CTX_ACQUIRED;
+ ctx->state = CAM_CTX_AVAILABLE;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP, "Release device success[%u] next state %d",
@@ -2244,6 +2575,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
uintptr_t packet_addr;
struct cam_packet *packet;
size_t len = 0;
+ size_t remain_len = 0;
struct cam_hw_prepare_update_args cfg;
struct cam_req_mgr_add_request add_req;
struct cam_isp_context *ctx_isp =
@@ -2262,8 +2594,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
if (!req) {
CAM_ERR(CAM_ISP, "No more request obj free");
- rc = -ENOMEM;
- goto end;
+ return -ENOMEM;
}
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
@@ -2278,6 +2609,15 @@ static int __cam_isp_ctx_config_dev_in_top_state(
goto free_req;
}
+ remain_len = len;
+ if ((len < sizeof(struct cam_packet)) ||
+ ((size_t)cmd->offset >= len - sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_ISP, "invalid buff length: %zu or offset", len);
+ rc = -EINVAL;
+ goto free_cpu_buf;
+ }
+
+ remain_len -= (size_t)cmd->offset;
packet = (struct cam_packet *)(packet_addr + (uint32_t)cmd->offset);
CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle);
CAM_DBG(CAM_ISP, "packet address is 0x%zx", packet_addr);
@@ -2288,20 +2628,19 @@ static int __cam_isp_ctx_config_dev_in_top_state(
CAM_DBG(CAM_ISP, "Packet size 0x%x", packet->header.size);
CAM_DBG(CAM_ISP, "packet op %d", packet->header.op_code);
- if (packet->header.request_id <= ctx->last_flush_req) {
+ if ((((packet->header.op_code + 1) & 0xF) == CAM_ISP_PACKET_UPDATE_DEV)
+ && (packet->header.request_id <= ctx->last_flush_req)) {
CAM_INFO(CAM_ISP,
"request %lld has been flushed, reject packet",
packet->header.request_id);
rc = -EINVAL;
- goto free_req;
+ goto free_cpu_buf;
}
- if (packet->header.request_id > ctx->last_flush_req)
- ctx->last_flush_req = 0;
-
/* preprocess the configuration */
memset(&cfg, 0, sizeof(cfg));
cfg.packet = packet;
+ cfg.remain_len = remain_len;
cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
cfg.max_hw_update_entries = CAM_ISP_CTX_CFG_MAX;
cfg.hw_update_entries = req_isp->cfg;
@@ -2319,7 +2658,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
if (rc != 0) {
CAM_ERR(CAM_ISP, "Prepare config packet failed in HW layer");
rc = -EFAULT;
- goto free_req;
+ goto free_cpu_buf;
}
req_isp->num_cfg = cfg.num_hw_update_entries;
req_isp->num_fence_map_out = cfg.num_out_map_entries;
@@ -2380,6 +2719,10 @@ static int __cam_isp_ctx_config_dev_in_top_state(
if (rc)
goto put_ref;
+ if (cam_mem_put_cpu_buf((int32_t) cmd->packet_handle))
+ CAM_WARN(CAM_ISP, "Can not put packet address : %llu",
+ cmd->packet_handle);
+
CAM_DBG(CAM_REQ,
"Preprocessing Config req_id %lld successful on ctx %u",
req->request_id, ctx->ctx_id);
@@ -2388,16 +2731,19 @@ static int __cam_isp_ctx_config_dev_in_top_state(
put_ref:
for (--i; i >= 0; i--) {
- rc = cam_sync_put_obj_ref(req_isp->fence_map_out[i].sync_id);
- if (rc)
+ if (cam_sync_put_obj_ref(req_isp->fence_map_out[i].sync_id))
CAM_ERR(CAM_CTXT, "Failed to put ref of fence %d",
req_isp->fence_map_out[i].sync_id);
}
+free_cpu_buf:
+ if (cam_mem_put_cpu_buf((int32_t) cmd->packet_handle))
+ CAM_WARN(CAM_ISP, "Can not put packet address: %llu",
+ cmd->packet_handle);
free_req:
spin_lock_bh(&ctx->lock);
list_add_tail(&req->list, &ctx->free_req_list);
spin_unlock_bh(&ctx->lock);
-end:
+
return rc;
}
@@ -2476,7 +2822,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
- isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_CTX_TYPE;
hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2485,7 +2831,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
goto free_hw;
}
- if (isp_hw_cmd_args.u.is_rdi_only_context) {
+ if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) {
/*
* this context has rdi only resource assign rdi only
* state machine
@@ -2496,6 +2842,13 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_rdi_only_activated_state_machine;
+ ctx_isp->rdi_only_context = true;
+ } else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
+ CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+ ctx_isp->substate_machine_irq =
+ cam_isp_ctx_fs2_state_machine_irq;
+ ctx_isp->substate_machine =
+ cam_isp_ctx_fs2_state_machine;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@@ -2504,7 +2857,6 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
cam_isp_ctx_activated_state_machine;
}
- ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true;
ctx_isp->split_acquire = false;
@@ -2622,7 +2974,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
/* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
- isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
+ isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_CTX_TYPE;
hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
&hw_cmd_args);
@@ -2631,7 +2983,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
goto free_hw;
}
- if (isp_hw_cmd_args.u.is_rdi_only_context) {
+ if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) {
/*
* this context has rdi only resource assign rdi only
* state machine
@@ -2642,6 +2994,13 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_rdi_only_activated_state_machine;
+ ctx_isp->rdi_only_context = true;
+ } else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
+ CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
+ ctx_isp->substate_machine_irq =
+ cam_isp_ctx_fs2_state_machine_irq;
+ ctx_isp->substate_machine =
+ cam_isp_ctx_fs2_state_machine;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@@ -2650,16 +3009,14 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
cam_isp_ctx_activated_state_machine;
}
- ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP,
- "Acquire success on session_hdl 0x%xs RDI only %d ctx %u",
- ctx->session_hdl,
- (isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
+ "Acquire success on session_hdl 0x%xs ctx_type %d ctx_id %u",
+ ctx->session_hdl, isp_hw_cmd_args.u.ctx_type, ctx->ctx_id);
kfree(acquire_hw_info);
return rc;
@@ -2807,6 +3164,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
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;
@@ -2814,7 +3172,6 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
CAM_ISP_CTX_ACTIVATED_APPLIED :
(req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH :
CAM_ISP_CTX_ACTIVATED_SOF;
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/*
* Only place to change state before calling the hw due to
@@ -2876,7 +3233,6 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock(
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT;
spin_unlock_bh(&ctx->lock);
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
- CAM_INFO(CAM_ISP, "state changed to %s", substate_name[ctx_isp->substate_activated]);
/* stop hw first */
if (ctx_isp->hw_ctx) {
@@ -2944,9 +3300,16 @@ 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;
+ atomic_set(&ctx_isp->process_bubble, 0);
CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u",
ctx->state, ctx->ctx_id);
+
+ if (!stop_cmd) {
+ rc = __cam_isp_ctx_unlink_in_ready(ctx, NULL);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Unlink failed rc=%d", rc);
+ }
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h
index 5ebd82ead470..4954f2034144 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -144,6 +144,8 @@ struct cam_isp_context_state_monitor {
* @base: Common context object pointer
* @frame_id: Frame id tracking for the isp context
* @substate_actiavted: Current substate for the activated state.
+ * @process_bubble: Atomic variable to check if ctx is still
+ * processing bubble.
* @substate_machine: ISP substate machine for external interface
* @substate_machine_irq: ISP substate machine for irq handling
* @req_base: Common request object storage
@@ -170,6 +172,7 @@ struct cam_isp_context {
int64_t frame_id;
uint32_t substate_activated;
+ atomic_t process_bubble;
struct cam_ctx_ops *substate_machine;
struct cam_isp_ctx_irq_ops *substate_machine_irq;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index a6c96bd8929c..582d4858e18b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -43,7 +43,7 @@
(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)
#define CAM_ISP_GENERIC_BLOB_TYPE_MAX \
- (CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG + 1)
+ (CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG + 1)
static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
CAM_ISP_HW_CMD_GET_HFR_UPDATE,
@@ -51,6 +51,7 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
CAM_ISP_HW_CMD_BW_UPDATE,
CAM_ISP_HW_CMD_UBWC_UPDATE,
CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
+ CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG,
};
static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -316,6 +317,11 @@ static void cam_ife_hw_mgr_deinit_hw(
cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
}
+ /* Deint IFE RD */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+ }
+
/* Deinit IFE OUT */
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
@@ -366,6 +372,18 @@ static int cam_ife_hw_mgr_init_hw(
}
}
+ /* INIT IFE BUS RD */
+ CAM_DBG(CAM_ISP, "INIT IFE BUS RD in ctx id:%d",
+ ctx->ctx_index);
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not IFE BUS RD (%d)",
+ hw_mgr_res->res_id);
+ return rc;
+ }
+ }
+
/* INIT IFE OUT */
CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
ctx->ctx_index);
@@ -500,6 +518,13 @@ static int cam_ife_hw_mgr_release_hw_for_ctx(
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_free_hw_res(&ife_ctx->res_list_ife_out[i]);
+ /* ife bus rd resource */
+ list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
+ &ife_ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_free_hw_res(hw_mgr_res);
+ cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &hw_mgr_res);
+ }
+
/* ife source resource */
list_for_each_entry_safe(hw_mgr_res, hw_mgr_res_temp,
&ife_ctx->res_list_ife_src, list) {
@@ -645,6 +670,91 @@ static int cam_ife_mgr_process_base_info(
return 0;
}
+static int cam_ife_hw_mgr_acquire_res_bus_rd(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_in_port_info *in_port)
+{
+ int rc = -EINVAL;
+ struct cam_vfe_acquire_args vfe_acquire;
+ struct cam_ife_hw_mgr_res *ife_in_rd_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_ife_hw_mgr_res *ife_src_res;
+ int i;
+
+ CAM_DBG(CAM_ISP, "Enter");
+
+ list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) {
+ if (ife_src_res->res_id != CAM_ISP_HW_VFE_IN_RD)
+ continue;
+
+ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
+ &ife_in_rd_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+ goto err;
+ }
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd,
+ &ife_in_rd_res);
+
+ vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+ vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+ vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
+ vfe_acquire.vfe_out.ctx = ife_ctx;
+ vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index;
+ vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_vfe;
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!ife_src_res->hw_res[i])
+ continue;
+
+ hw_intf = ife_src_res->hw_res[i]->hw_intf;
+ if (i == CAM_ISP_HW_SPLIT_LEFT) {
+ vfe_acquire.vfe_out.split_id =
+ CAM_ISP_HW_SPLIT_LEFT;
+ if (ife_src_res->is_dual_vfe) {
+ /*TBD */
+ vfe_acquire.vfe_out.is_master = 1;
+ vfe_acquire.vfe_out.dual_slave_core =
+ (hw_intf->hw_idx == 0) ? 1 : 0;
+ } else {
+ vfe_acquire.vfe_out.is_master = 0;
+ vfe_acquire.vfe_out.dual_slave_core =
+ 0;
+ }
+ } else {
+ vfe_acquire.vfe_out.split_id =
+ CAM_ISP_HW_SPLIT_RIGHT;
+ vfe_acquire.vfe_out.is_master = 0;
+ vfe_acquire.vfe_out.dual_slave_core =
+ (hw_intf->hw_idx == 0) ? 1 : 0;
+ }
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &vfe_acquire,
+ sizeof(struct cam_vfe_acquire_args));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire out resource 0x%x",
+ vfe_acquire.rsrc_type);
+ goto err;
+ }
+
+ ife_in_rd_res->hw_res[i] =
+ vfe_acquire.vfe_out.rsrc_node;
+ CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x",
+ ife_in_rd_res->hw_res[i]->res_type,
+ ife_in_rd_res->hw_res[i]->res_id);
+
+ }
+ ife_in_rd_res->is_dual_vfe = in_port->usage_type;
+ ife_in_rd_res->res_type = (enum cam_ife_hw_mgr_res_type)
+ CAM_ISP_RESOURCE_VFE_BUS_RD;
+ }
+
+ return 0;
+err:
+ CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
+ return rc;
+}
+
static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_ife_hw_mgr_res *ife_src_res,
@@ -724,6 +834,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
ife_out_res->res_type = (enum cam_ife_hw_mgr_res_type)
CAM_ISP_RESOURCE_VFE_OUT;
ife_src_res->child[ife_src_res->num_children++] = ife_out_res;
+ CAM_DBG(CAM_ISP, "IFE SRC num_children = %d",
+ ife_src_res->num_children);
return 0;
err:
@@ -817,6 +929,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_out_pixel(
ife_out_res->res_id = out_port->res_type;
ife_out_res->parent = ife_src_res;
ife_src_res->child[ife_src_res->num_children++] = ife_out_res;
+ CAM_DBG(CAM_ISP, "IFE SRC num_children = %d",
+ ife_src_res->num_children);
}
return 0;
@@ -839,6 +953,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_out(
switch (ife_src_res->res_id) {
case CAM_ISP_HW_VFE_IN_CAMIF:
case CAM_ISP_HW_VFE_IN_CAMIF_LITE:
+ case CAM_ISP_HW_VFE_IN_RD:
rc = cam_ife_hw_mgr_acquire_res_ife_out_pixel(ife_ctx,
ife_src_res, in_port);
break;
@@ -864,6 +979,132 @@ err:
return rc;
}
+static int cam_ife_hw_mgr_acquire_res_ife_rd_src(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_in_port_info *in_port)
+{
+ int rc = -1;
+ struct cam_ife_hw_mgr_res *csid_res;
+ struct cam_ife_hw_mgr_res *ife_src_res;
+ struct cam_vfe_acquire_args vfe_acquire;
+ struct cam_hw_intf *hw_intf;
+ struct cam_ife_hw_mgr *ife_hw_mgr;
+ int vfe_idx = -1, i = 0;
+
+ ife_hw_mgr = ife_ctx->hw_mgr;
+
+ CAM_DBG(CAM_ISP, "Enter");
+ list_for_each_entry(csid_res, &ife_ctx->res_list_ife_csid, list) {
+ if (csid_res->res_id != CAM_IFE_PIX_PATH_RES_RDI_0) {
+ CAM_DBG(CAM_ISP, "not RDI0: %d", csid_res->res_id);
+ continue;
+ }
+
+ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
+ &ife_src_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+ goto err;
+ }
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src,
+ &ife_src_res);
+
+ CAM_DBG(CAM_ISP, "csid_res_id %d", csid_res->res_id);
+ vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
+ vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
+ vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
+ vfe_acquire.vfe_in.in_port = in_port;
+ vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RD;
+ vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
+
+ ife_src_res->res_type =
+ (enum cam_ife_hw_mgr_res_type)vfe_acquire.rsrc_type;
+ ife_src_res->res_id = vfe_acquire.vfe_in.res_id;
+ ife_src_res->is_dual_vfe = csid_res->is_dual_vfe;
+
+ hw_intf =
+ ife_hw_mgr->ife_devices[csid_res->hw_res[
+ CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx];
+
+ vfe_idx = csid_res->hw_res[
+ CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx;
+
+ /*
+ * fill in more acquire information as needed
+ */
+ if (ife_src_res->is_dual_vfe)
+ vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
+
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &vfe_acquire,
+ sizeof(struct cam_vfe_acquire_args));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire IFE HW res %d",
+ csid_res->res_id);
+ goto err;
+ }
+ ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] =
+ vfe_acquire.vfe_in.rsrc_node;
+ CAM_DBG(CAM_ISP,
+ "acquire success IFE:%d res type :0x%x res id:0x%x",
+ hw_intf->hw_idx,
+ ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_type,
+ ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_id);
+
+ if (!ife_src_res->is_dual_vfe)
+ goto acq;
+
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (i == CAM_ISP_HW_SPLIT_LEFT) {
+ CAM_DBG(CAM_ISP, "vfe_idx %d is acquired",
+ vfe_idx);
+ continue;
+ }
+
+ hw_intf = ife_hw_mgr->ife_devices[i];
+
+ /* fill in more acquire information as needed */
+ if (i == CAM_ISP_HW_SPLIT_RIGHT)
+ vfe_acquire.vfe_in.sync_mode =
+ CAM_ISP_HW_SYNC_SLAVE;
+
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &vfe_acquire,
+ sizeof(struct cam_vfe_acquire_args));
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire IFE HW res %d",
+ csid_res->res_id);
+ goto err;
+ }
+ ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
+ CAM_DBG(CAM_ISP,
+ "acquire success IFE:%d res type :0x%x res id:0x%x",
+ hw_intf->hw_idx,
+ ife_src_res->hw_res[i]->res_type,
+ ife_src_res->hw_res[i]->res_id);
+ }
+acq:
+ /*
+ * It should be one to one mapping between
+ * csid resource and ife source resource
+ */
+ csid_res->child[0] = ife_src_res;
+ ife_src_res->parent = csid_res;
+ csid_res->child[csid_res->num_children++] = ife_src_res;
+ CAM_DBG(CAM_ISP,
+ "csid_res=%d CSID num_children=%d ife_src_res=%d",
+ csid_res->res_id, csid_res->num_children,
+ ife_src_res->res_id);
+ }
+
+err:
+ /* release resource at the entry function */
+ CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
+ return rc;
+}
+
static int cam_ife_hw_mgr_acquire_res_ife_src(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port)
@@ -976,7 +1217,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src(
csid_res->child[0] = ife_src_res;
ife_src_res->parent = csid_res;
csid_res->child[csid_res->num_children++] = ife_src_res;
- CAM_DBG(CAM_ISP, "csid_res=%d num_children=%d ife_src_res=%d",
+ CAM_DBG(CAM_ISP,
+ "csid_res=%d CSID num_children=%d ife_src_res=%d",
csid_res->res_id, csid_res->num_children,
ife_src_res->res_id);
}
@@ -991,7 +1233,7 @@ static int cam_ife_mgr_acquire_cid_res(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
struct cam_ife_hw_mgr_res **cid_res,
- enum cam_ife_pix_path_res_id csid_path)
+ enum cam_ife_pix_path_res_id path_res_id)
{
int rc = -1;
int i, j;
@@ -1015,8 +1257,8 @@ static int cam_ife_mgr_acquire_cid_res(
csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
csid_acquire.in_port = in_port;
- csid_acquire.res_id = csid_path;
- CAM_DBG(CAM_ISP, "path %d", csid_path);
+ csid_acquire.res_id = path_res_id;
+ CAM_DBG(CAM_ISP, "path_res_id %d", path_res_id);
if (in_port->num_out_res)
out_port = &(in_port->data[0]);
@@ -1049,12 +1291,12 @@ static int cam_ife_mgr_acquire_cid_res(
csid_acquire.node_res;
CAM_DBG(CAM_ISP,
- "acquired csid(%s)=%d CID rsrc successfully",
+ "acquired from old csid(%s)=%d CID rsrc successfully",
(i == 0) ? "left" : "right",
hw_intf->hw_idx);
if (in_port->usage_type && acquired_cnt == 1 &&
- csid_path == CAM_IFE_PIX_PATH_RES_IPP)
+ path_res_id == CAM_IFE_PIX_PATH_RES_IPP)
/*
* Continue to acquire Right for IPP.
* Dual IFE for RDI and PPP is not currently
@@ -1074,28 +1316,53 @@ static int cam_ife_mgr_acquire_cid_res(
}
/* Acquire Left if not already acquired */
- for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) {
- if (!ife_hw_mgr->csid_devices[i])
- continue;
+ if (ife_ctx->is_fe_enable) {
+ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+ if (!ife_hw_mgr->csid_devices[i])
+ continue;
- hw_intf = ife_hw_mgr->csid_devices[i];
- rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
- sizeof(csid_acquire));
- if (rc)
- continue;
- else {
- cid_res_temp->hw_res[acquired_cnt++] =
- csid_acquire.node_res;
- break;
+ hw_intf = ife_hw_mgr->csid_devices[i];
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc)
+ continue;
+ else {
+ cid_res_temp->hw_res[acquired_cnt++] =
+ csid_acquire.node_res;
+ break;
+ }
}
- }
+ if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire ife cid resource for path %d",
+ path_res_id);
+ goto put_res;
+ }
+ } else {
+ for (i = CAM_IFE_CSID_HW_NUM_MAX - 1; i >= 0; i--) {
+ if (!ife_hw_mgr->csid_devices[i])
+ continue;
- if (i == -1 || !csid_acquire.node_res) {
- CAM_ERR(CAM_ISP, "Can not acquire ife cid resource for path %d",
- csid_path);
- goto put_res;
+ hw_intf = ife_hw_mgr->csid_devices[i];
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc)
+ continue;
+ else {
+ cid_res_temp->hw_res[acquired_cnt++] =
+ csid_acquire.node_res;
+ break;
+ }
+ }
+ if (i == -1 || !csid_acquire.node_res) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire ife cid resource for path %d",
+ path_res_id);
+ goto put_res;
+ }
}
+
acquire_successful:
CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d",
in_port->usage_type);
@@ -1114,7 +1381,7 @@ acquire_successful:
* Acquire Right if not already acquired.
* Dual IFE for RDI and PPP is not currently supported.
*/
- if (cid_res_temp->is_dual_vfe && csid_path
+ if (cid_res_temp->is_dual_vfe && path_res_id
== CAM_IFE_PIX_PATH_RES_IPP && acquired_cnt == 1) {
csid_acquire.node_res = NULL;
csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
@@ -1147,6 +1414,8 @@ acquire_successful:
cid_res_temp->parent = &ife_ctx->res_list_ife_in;
ife_ctx->res_list_ife_in.child[
ife_ctx->res_list_ife_in.num_children++] = cid_res_temp;
+ CAM_DBG(CAM_ISP, "IFE IN num_children = %d",
+ ife_ctx->res_list_ife_in.num_children);
return 0;
put_res:
@@ -1205,6 +1474,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
}
+ CAM_DBG(CAM_ISP, "CSID Acq: E");
/* IPP resource needs to be from same HW as CID resource */
for (i = 0; i <= csid_res->is_dual_vfe; i++) {
CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_vfe);
@@ -1255,8 +1525,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl(
csid_res->parent = cid_res;
cid_res->child[cid_res->num_children++] = csid_res;
- CAM_DBG(CAM_ISP, "acquire res %d", csid_acquire.res_id);
-
+ CAM_DBG(CAM_ISP, "acquire res %d CID children = %d",
+ csid_acquire.res_id, cid_res->num_children);
return 0;
put_res:
cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
@@ -1269,6 +1539,7 @@ static enum cam_ife_pix_path_res_id
uint32_t out_port_type)
{
enum cam_ife_pix_path_res_id path_id;
+ CAM_DBG(CAM_ISP, "out_port_type %x", out_port_type);
switch (out_port_type) {
case CAM_ISP_IFE_OUT_RES_RDI_0:
@@ -1289,7 +1560,7 @@ static enum cam_ife_pix_path_res_id
break;
}
- CAM_DBG(CAM_ISP, "out_port %d path_id %d", out_port_type, path_id);
+ CAM_DBG(CAM_ISP, "out_port %x path_id %d", out_port_type, path_id);
return path_id;
}
@@ -1307,20 +1578,20 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
struct cam_hw_intf *hw_intf;
struct cam_isp_out_port_info *out_port;
struct cam_csid_hw_reserve_resource_args csid_acquire;
- enum cam_ife_pix_path_res_id path_type;
+ enum cam_ife_pix_path_res_id path_res_id;
ife_hw_mgr = ife_ctx->hw_mgr;
for (i = 0; i < in_port->num_out_res; i++) {
out_port = &in_port->data[i];
- path_type = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+ path_res_id = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
out_port->res_type);
- if (path_type == CAM_IFE_PIX_PATH_RES_MAX)
+ if (path_res_id == CAM_IFE_PIX_PATH_RES_MAX)
continue;
/* get cid resource */
rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
- path_type);
+ path_res_id);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
goto end;
@@ -1335,8 +1606,7 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
}
memset(&csid_acquire, 0, sizeof(csid_acquire));
- csid_acquire.res_id = path_type;
-
+ csid_acquire.res_id = path_res_id;
csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
csid_acquire.cid = cid_res->hw_res[0]->res_id;
csid_acquire.in_port = in_port;
@@ -1368,11 +1638,11 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
csid_res->is_dual_vfe = 0;
csid_res->hw_res[0] = csid_acquire.node_res;
csid_res->hw_res[1] = NULL;
- CAM_DBG(CAM_ISP, "acquire res %d",
- csid_acquire.res_id);
csid_res->parent = cid_res;
cid_res->child[cid_res->num_children++] =
csid_res;
+ CAM_DBG(CAM_ISP, "acquire res %d CID children = %d",
+ csid_acquire.res_id, cid_res->num_children);
cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
}
@@ -1395,7 +1665,8 @@ static int cam_ife_hw_mgr_acquire_res_root(
ife_ctx->res_list_ife_in.res_type = CAM_IFE_HW_MGR_RES_ROOT;
ife_ctx->res_list_ife_in.res_id = in_port->res_type;
ife_ctx->res_list_ife_in.is_dual_vfe = in_port->usage_type;
- } else if (ife_ctx->res_list_ife_in.res_id != in_port->res_type) {
+ } else if ((ife_ctx->res_list_ife_in.res_id !=
+ in_port->res_type) && (!ife_ctx->is_fe_enable)) {
CAM_ERR(CAM_ISP, "No Free resource for this context");
goto err;
} else {
@@ -1407,35 +1678,85 @@ err:
return rc;
}
-static int cam_ife_hw_mgr_preprocess_out_port(
+static int cam_ife_mgr_check_and_update_fe(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_acquire_hw_info *acquire_hw_info)
+{
+ int i;
+ struct cam_isp_in_port_info *in_port = NULL;
+ uint32_t in_port_length = 0;
+ uint32_t total_in_port_length = 0;
+
+ in_port = (struct cam_isp_in_port_info *)
+ ((uint8_t *)&acquire_hw_info->data +
+ acquire_hw_info->input_info_offset);
+ for (i = 0; i < acquire_hw_info->num_inputs; i++) {
+ in_port_length = sizeof(struct cam_isp_in_port_info) +
+ (in_port->num_out_res - 1) *
+ sizeof(struct cam_isp_out_port_info);
+ total_in_port_length += in_port_length;
+
+ if (total_in_port_length > acquire_hw_info->input_info_size) {
+ CAM_ERR(CAM_ISP, "buffer size is not enough");
+ return -EINVAL;
+ }
+ CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
+ in_port->res_type);
+ if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+ ife_ctx->is_fe_enable = true;
+ break;
+ }
+
+ in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port +
+ in_port_length);
+ }
+ CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
+
+ return 0;
+}
+
+static int cam_ife_hw_mgr_preprocess_port(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
int *ipp_count,
int *rdi_count,
- int *ppp_count)
+ int *ppp_count,
+ int *ife_rd_count)
{
int ipp_num = 0;
int rdi_num = 0;
int ppp_num = 0;
+ int ife_rd_num = 0;
uint32_t i;
struct cam_isp_out_port_info *out_port;
struct cam_ife_hw_mgr *ife_hw_mgr;
ife_hw_mgr = ife_ctx->hw_mgr;
- for (i = 0; i < in_port->num_out_res; i++) {
- out_port = &in_port->data[i];
- if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
- rdi_num++;
- else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
- ppp_num++;
- else
- ipp_num++;
+ if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
+ ife_rd_num++;
+ } else {
+ for (i = 0; i < in_port->num_out_res; i++) {
+ out_port = &in_port->data[i];
+ if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
+ rdi_num++;
+ else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
+ ppp_num++;
+ else {
+ CAM_DBG(CAM_ISP, "out_res_type %d",
+ out_port->res_type);
+ ipp_num++;
+ }
+ }
}
*ipp_count = ipp_num;
*rdi_count = rdi_num;
*ppp_count = ppp_num;
+ *ife_rd_count = ife_rd_num;
+
+ CAM_DBG(CAM_ISP, "rdi: %d ipp: %d ppp: %d ife_rd: %d",
+ rdi_num, ipp_num, ppp_num, ife_rd_num);
return 0;
}
@@ -1450,6 +1771,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
int ipp_count = 0;
int rdi_count = 0;
int ppp_count = 0;
+ int ife_rd_count = 0;
is_dual_vfe = in_port->usage_type;
@@ -1460,11 +1782,11 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
goto err;
}
- cam_ife_hw_mgr_preprocess_out_port(ife_ctx, in_port,
- &ipp_count, &rdi_count, &ppp_count);
+ cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port,
+ &ipp_count, &rdi_count, &ppp_count, &ife_rd_count);
- if (!ipp_count && !rdi_count && !ppp_count) {
- CAM_ERR(CAM_ISP, "No PIX or RDI or PPP resource");
+ if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count) {
+ CAM_ERR(CAM_ISP, "No PIX or RDI or PPP or IFE RD resource");
return -EINVAL;
}
@@ -1502,19 +1824,26 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
/* get ife src resource */
- rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
+ if (ife_rd_count) {
+ rc = cam_ife_hw_mgr_acquire_res_ife_rd_src(ife_ctx, in_port);
+ rc = cam_ife_hw_mgr_acquire_res_bus_rd(ife_ctx, in_port);
+ } else {
+ rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, in_port);
+ }
+
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE SRC resource Failed");
goto err;
}
+ CAM_DBG(CAM_ISP, "Acquiring IFE OUT resource...");
rc = cam_ife_hw_mgr_acquire_res_ife_out(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE OUT resource Failed");
goto err;
}
- *num_pix_port += ipp_count + ppp_count;
+ *num_pix_port += ipp_count + ppp_count + ife_rd_count;
*num_rdi_port += rdi_count;
return 0;
@@ -1538,8 +1867,8 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
complete(&ctx->config_done_complete);
CAM_DBG(CAM_ISP,
- "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
- handle, userdata, status, cookie);
+ "Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
+ handle, userdata, status, cookie, ctx->ctx_index);
} else {
CAM_WARN(CAM_ISP,
"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
@@ -1618,8 +1947,22 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
((uint8_t *)&acquire_hw_info->data +
acquire_hw_info->input_info_offset);
+ rc = cam_ife_mgr_check_and_update_fe(ife_ctx, acquire_hw_info);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "buffer size is not enough");
+ goto free_ctx;
+ }
+
/* acquire HW resources */
for (i = 0; i < acquire_hw_info->num_inputs; i++) {
+
+ if (in_port->num_out_res > CAM_IFE_HW_OUT_RES_MAX) {
+ CAM_ERR(CAM_ISP, "too many output res %d",
+ in_port->num_out_res);
+ rc = -EINVAL;
+ goto free_res;
+ }
+
in_port_length = sizeof(struct cam_isp_in_port_info) +
(in_port->num_out_res - 1) *
sizeof(struct cam_isp_out_port_info);
@@ -1630,6 +1973,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
rc = -EINVAL;
goto free_res;
}
+ CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type);
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
&num_pix_port_per_in, &num_rdi_port_per_in);
total_pix_port += num_pix_port_per_in;
@@ -1745,6 +2089,8 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args)
if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT)
continue;
+ CAM_DBG(CAM_ISP, "acquire no = %d total = %d", i,
+ acquire_args->num_acq);
CAM_DBG(CAM_ISP,
"start copy from user handle %lld with len = %d",
isp_resource[i].res_hdl,
@@ -1882,7 +2228,8 @@ static int cam_isp_blob_bw_update(
if (!hw_mgr_res->hw_res[i])
continue;
- if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
+ if ((hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
+ || (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_RD))
if (i == CAM_ISP_HW_SPLIT_LEFT) {
if (camif_l_bw_updated)
continue;
@@ -2013,8 +2360,9 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
}
}
- CAM_DBG(CAM_ISP, "Enter ctx id:%d num_hw_upd_entries %d",
- ctx->ctx_index, cfg->num_hw_update_entries);
+ CAM_DBG(CAM_ISP,
+ "Enter ctx id:%d num_hw_upd_entries %d request id: %llu",
+ ctx->ctx_index, cfg->num_hw_update_entries, cfg->request_id);
if (cfg->num_hw_update_entries > 0) {
cdm_cmd = ctx->cdm_cmd;
@@ -2047,21 +2395,21 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
msecs_to_jiffies(30));
if (rc <= 0) {
CAM_ERR(CAM_ISP,
- "config done completion timeout for req_id=%llu rc = %d",
- cfg->request_id, rc);
+ "config done completion timeout for req_id=%llu rc=%d ctx_index %d",
+ cfg->request_id, rc, ctx->ctx_index);
if (rc == 0)
rc = -ETIMEDOUT;
} else {
rc = 0;
CAM_DBG(CAM_ISP,
- "config done Success for req_id=%llu",
- cfg->request_id);
+ "config done Success for req_id=%llu ctx_index %d",
+ cfg->request_id, ctx->ctx_index);
}
}
} else {
CAM_ERR(CAM_ISP, "No commands to config");
}
- CAM_DBG(CAM_ISP, "Exit");
+ CAM_DBG(CAM_ISP, "Exit: Config Done: %llu", cfg->request_id);
return rc;
}
@@ -2134,6 +2482,11 @@ static int cam_ife_mgr_stop_hw_in_overflow(void *stop_hw_args)
cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
}
+ /* IFE bus rd resources */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+ }
+
/* IFE out resources */
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
@@ -2236,11 +2589,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
CAM_DBG(CAM_ISP, "Halting CSIDs");
- CAM_DBG(CAM_ISP, "Going to stop IFE Out");
-
- /* IFE out resources */
- for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
- cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
/* get master base index first */
for (i = 0; i < ctx->num_base; i++) {
if (ctx->base[i].split_id == CAM_ISP_HW_SPLIT_LEFT) {
@@ -2249,15 +2597,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
}
}
- CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
-
- /* IFE mux in resources */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
- cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
- }
-
- cam_tasklet_stop(ctx->common.tasklet_info);
-
/*
* If Context does not have PIX resources and has only RDI resource
* then take the first base index.
@@ -2297,6 +2636,26 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
ctx->base[i].idx, csid_halt_type);
}
+ CAM_DBG(CAM_ISP, "Going to stop IFE Out");
+
+ /* IFE out resources */
+ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
+ cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
+
+ /* IFE bus rd resources */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+ }
+
+ CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
+
+ /* IFE mux in resources */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
+ }
+
+ cam_tasklet_stop(ctx->common.tasklet_info);
+
cam_ife_mgr_pause_hw(ctx);
if (stop_isp->stop_only)
@@ -2386,6 +2745,17 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
}
CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d", ctx->ctx_index);
+
+ /* Start IFE BUS RD device */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+ hw_mgr_res->res_id);
+ goto err;
+ }
+ }
+
/* Start the IFE mux in devices */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
@@ -2536,6 +2906,18 @@ start_only:
}
}
+ CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d",
+ ctx->ctx_index);
+ /* Start the IFE mux in devices */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
+ hw_mgr_res->res_id);
+ goto err;
+ }
+ }
+
CAM_DBG(CAM_ISP, "START IFE SRC ... in ctx id:%d",
ctx->ctx_index);
/* Start the IFE mux in devices */
@@ -2595,7 +2977,6 @@ safe_disable:
deinit_hw:
cam_ife_hw_mgr_deinit_hw(ctx);
- ctx->init_done = false;
tasklet_stop:
cam_tasklet_stop(ctx->common.tasklet_info);
@@ -2667,6 +3048,78 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
return rc;
}
+static int cam_isp_blob_fe_update(
+ uint32_t blob_type,
+ struct cam_isp_generic_blob_info *blob_info,
+ struct cam_fe_config *fe_config,
+ struct cam_hw_prepare_update_args *prepare)
+{
+ struct cam_ife_hw_mgr_ctx *ctx = NULL;
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ int rc = -EINVAL;
+ uint32_t i;
+ struct cam_vfe_fe_update_args fe_upd_args;
+
+ ctx = prepare->ctxt_to_hw_map;
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ if (hw_intf && hw_intf->hw_ops.process_cmd) {
+ fe_upd_args.node_res =
+ hw_mgr_res->hw_res[i];
+
+ memcpy(&fe_upd_args.fe_config, fe_config,
+ sizeof(struct cam_fe_config));
+
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
+ &fe_upd_args,
+ sizeof(
+ struct cam_fe_config));
+ if (rc)
+ CAM_ERR(CAM_ISP, "fs Update failed");
+ } else
+ CAM_WARN(CAM_ISP, "NULL hw_intf!");
+ }
+ }
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_RD)
+ continue;
+
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ if (hw_intf && hw_intf->hw_ops.process_cmd) {
+ fe_upd_args.node_res =
+ hw_mgr_res->hw_res[i];
+
+ memcpy(&fe_upd_args.fe_config, fe_config,
+ sizeof(struct cam_fe_config));
+
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
+ &fe_upd_args,
+ sizeof(
+ struct cam_vfe_fe_update_args));
+ if (rc)
+ CAM_ERR(CAM_ISP, "fe Update failed");
+ } else
+ CAM_WARN(CAM_ISP, "NULL hw_intf!");
+ }
+ }
+ return rc;
+}
+
static int cam_isp_blob_ubwc_update(
uint32_t blob_type,
struct cam_isp_generic_blob_info *blob_info,
@@ -3004,7 +3457,7 @@ static int cam_isp_blob_clock_update(
camif_r_clk_updated = true;
}
} else if ((hw_mgr_res->res_id >=
- CAM_ISP_HW_VFE_IN_RDI0) && (hw_mgr_res->res_id
+ CAM_ISP_HW_VFE_IN_RD) && (hw_mgr_res->res_id
<= CAM_ISP_HW_VFE_IN_RDI3))
for (j = 0; j < clock_config->num_rdi; j++)
clk_rate = max(clock_config->rdi_hz[j],
@@ -3043,6 +3496,53 @@ static int cam_isp_blob_clock_update(
return rc;
}
+void fill_res_bitmap(uint32_t resource_type, unsigned long *res_bitmap)
+{
+
+ switch (resource_type) {
+ case CAM_ISP_IFE_OUT_RES_FULL:
+ case CAM_ISP_IFE_OUT_RES_DS4:
+ case CAM_ISP_IFE_OUT_RES_DS16:
+ case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
+ case CAM_ISP_IFE_OUT_RES_FD:
+ case CAM_ISP_IFE_OUT_RES_PDAF:
+ case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
+ case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
+ case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
+ case CAM_ISP_IFE_OUT_RES_STATS_BF:
+ case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
+ case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
+ case CAM_ISP_IFE_OUT_RES_STATS_RS:
+ case CAM_ISP_IFE_OUT_RES_STATS_CS:
+ case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
+ case CAM_ISP_IFE_OUT_RES_FULL_DISP:
+ case CAM_ISP_IFE_OUT_RES_DS4_DISP:
+ case CAM_ISP_IFE_OUT_RES_DS16_DISP:
+ case CAM_ISP_IFE_IN_RES_RD:
+ set_bit(CAM_IFE_REG_UPD_CMD_PIX_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_0:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI0_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_1:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI1_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_2:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI2_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_RDI_3:
+ set_bit(CAM_IFE_REG_UPD_CMD_RDI3_BIT, res_bitmap);
+ break;
+ case CAM_ISP_IFE_OUT_RES_2PD:
+ set_bit(CAM_IFE_REG_UPD_CMD_DUAL_PD_BIT,
+ res_bitmap);
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "Invalid resource");
+ break;
+ }
+}
+
static int cam_isp_packet_generic_blob_handler(void *user_data,
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{
@@ -3051,8 +3551,8 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
struct cam_hw_prepare_update_args *prepare = NULL;
if (!blob_data || (blob_size == 0) || !blob_info) {
- CAM_ERR(CAM_ISP, "Invalid info blob %pK %d prepare %pK",
- blob_data, blob_size, prepare);
+ CAM_ERR(CAM_ISP, "Invalid args data %pK size %d info %pK",
+ blob_data, blob_size, blob_info);
return -EINVAL;
}
@@ -3069,10 +3569,32 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
return -EINVAL;
}
+ CAM_DBG(CAM_ISP, "FS2: BLOB Type: %d", blob_type);
switch (blob_type) {
case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: {
- struct cam_isp_resource_hfr_config *hfr_config =
- (struct cam_isp_resource_hfr_config *)blob_data;
+ 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) {
+ CAM_ERR(CAM_ISP, "Invalid num_ports %u in hfr config",
+ hfr_config->num_ports);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + hfr_config->num_ports *
+ sizeof(struct cam_isp_port_hfr_config))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size, sizeof(uint32_t) * 2 +
+ sizeof(struct cam_isp_port_hfr_config) *
+ hfr_config->num_ports);
+ return -EINVAL;
+ }
rc = cam_isp_blob_hfr_update(blob_type, blob_info,
hfr_config, prepare);
@@ -3081,8 +3603,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: {
- struct cam_isp_clock_config *clock_config =
- (struct cam_isp_clock_config *)blob_data;
+ 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;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + sizeof(uint64_t) *
+ (clock_config->num_rdi + 2))) {
+ 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);
@@ -3091,10 +3634,31 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
- struct cam_isp_bw_config *bw_config =
- (struct cam_isp_bw_config *)blob_data;
+ struct cam_isp_bw_config *bw_config;
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
+ 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;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + (bw_config->num_rdi + 2)
+ * sizeof(struct cam_isp_bw_vote))) {
+ CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+ blob_size,
+ sizeof(uint32_t) * 2 + (bw_config->num_rdi + 2)
+ * 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");
@@ -3112,8 +3676,29 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG: {
- struct cam_ubwc_config *ubwc_config =
- (struct cam_ubwc_config *)blob_data;
+ 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_ISP_IFE_OUT_RES_MAX) {
+ CAM_ERR(CAM_ISP, "Invalid num_ports %u in ubwc config",
+ ubwc_config->num_ports);
+ return -EINVAL;
+ }
+
+ if (blob_size < (sizeof(uint32_t) * 2 + ubwc_config->num_ports *
+ sizeof(struct cam_ubwc_plane_cfg_v1) * 2)) {
+ CAM_ERR(CAM_ISP, "Invalid blob_size %u expected %lu",
+ blob_size,
+ sizeof(uint32_t) * 2 + ubwc_config->num_ports *
+ sizeof(struct cam_ubwc_plane_cfg_v1) * 2);
+ return -EINVAL;
+ }
rc = cam_isp_blob_ubwc_update(blob_type, blob_info,
ubwc_config, prepare);
@@ -3122,8 +3707,16 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG: {
- struct cam_isp_csid_clock_config *clock_config =
- (struct cam_isp_csid_clock_config *)blob_data;
+ 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);
@@ -3131,6 +3724,24 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
CAM_ERR(CAM_ISP, "Clock Update Failed");
}
break;
+ case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: {
+ struct cam_fe_config *fe_config;
+
+ 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;
+
default:
CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
break;
@@ -3166,7 +3777,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map;
hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv;
- rc = cam_packet_util_validate_packet(prepare->packet);
+ rc = cam_packet_util_validate_packet(prepare->packet,
+ prepare->remain_len);
if (rc)
return rc;
@@ -3227,7 +3839,10 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
hw_mgr->mgr_common.img_iommu_hdl_secure,
prepare, ctx->base[i].idx,
&kmd_buf, ctx->res_list_ife_out,
- CAM_IFE_HW_OUT_RES_MAX, fill_fence);
+ &ctx->res_list_ife_in_rd,
+ CAM_IFE_HW_OUT_RES_MAX, fill_fence,
+ &ctx->res_bitmap,
+ fill_res_bitmap);
if (rc) {
CAM_ERR(CAM_ISP,
@@ -3268,7 +3883,8 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
/*Add reg update */
rc = cam_isp_add_reg_update(prepare, &ctx->res_list_ife_src,
- ctx->base[i].idx, &kmd_buf);
+ ctx->base[i].idx, &kmd_buf, ctx->is_fe_enable,
+ ctx->res_bitmap);
if (rc) {
CAM_ERR(CAM_ISP,
"Add Reg_update cmd Failed i=%d, idx=%d, rc=%d",
@@ -3276,6 +3892,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
goto end;
}
}
+ ctx->res_bitmap = 0;
end:
return rc;
@@ -3356,7 +3973,8 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
if (!io_cfg[i].mem_handle[j])
break;
- if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
+ if (pf_buf_info &&
+ GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
GET_FD_FROM_HANDLE(pf_buf_info)) {
CAM_INFO(CAM_ISP,
"Found PF at port: 0x%x mem 0x%x fd: 0x%x",
@@ -3391,9 +4009,10 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet,
}
CAM_INFO(CAM_ISP,
- "pln %d w %d h %d s 0x%x addr 0x%x end_addr 0x%x offset %x memh %x",
+ "pln %d w %d h %d s %u size 0x%x addr 0x%x end_addr 0x%x offset %x memh %x",
j, io_cfg[i].planes[j].width,
io_cfg[i].planes[j].height,
+ io_cfg[i].planes[j].plane_stride,
(unsigned int)src_buf_size,
(unsigned int)iova_addr,
(unsigned int)iova_addr +
@@ -3434,12 +4053,6 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
hw_cmd_args->u.internal_args;
switch (isp_hw_cmd_args->cmd_type) {
- case CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT:
- if (ctx->is_rdi_only_context)
- isp_hw_cmd_args->u.is_rdi_only_context = 1;
- else
- isp_hw_cmd_args->u.is_rdi_only_context = 0;
- break;
case CAM_ISP_HW_MGR_CMD_PAUSE_HW:
cam_ife_mgr_pause_hw(ctx);
break;
@@ -3450,6 +4063,14 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
cam_ife_mgr_sof_irq_debug(ctx,
isp_hw_cmd_args->u.sof_irq_enable);
break;
+ case CAM_ISP_HW_MGR_CMD_CTX_TYPE:
+ if (ctx->is_fe_enable)
+ isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_FS2;
+ else if (ctx->is_rdi_only_context)
+ isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_RDI;
+ else
+ isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_PIX;
+ break;
default:
CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
hw_cmd_args->cmd_type);
@@ -3485,17 +4106,25 @@ static int cam_ife_mgr_cmd_get_sof_timestamp(
list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
- if (!hw_mgr_res->hw_res[i] ||
- (i == CAM_ISP_HW_SPLIT_RIGHT))
+ if (!hw_mgr_res->hw_res[i])
continue;
+
/*
* Get the SOF time stamp from left resource only.
* Left resource is master for dual vfe case and
* Rdi only context case left resource only hold
* the RDI resource
*/
+
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf->hw_ops.process_cmd) {
+ /*
+ * Single VFE case, Get the time stamp from
+ * available one csid hw in the context
+ * Dual VFE case, get the time stamp from
+ * master(left) would be sufficient
+ */
+
csid_get_time.node_res =
hw_mgr_res->hw_res[i];
rc = hw_intf->hw_ops.process_cmd(
@@ -3504,23 +4133,16 @@ static int cam_ife_mgr_cmd_get_sof_timestamp(
&csid_get_time,
sizeof(
struct cam_csid_get_time_stamp_args));
- if (!rc) {
+ if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) {
*time_stamp =
csid_get_time.time_stamp_val;
*boot_time_stamp =
csid_get_time.boot_timestamp;
}
- /*
- * Single VFE case, Get the time stamp from available
- * one csid hw in the context
- * Dual VFE case, get the time stamp from master(left)
- * would be sufficient
- */
- goto end;
}
}
}
-end:
+
if (rc)
CAM_ERR(CAM_ISP, "Getting sof time stamp failed");
@@ -3790,6 +4412,8 @@ static int cam_ife_hw_mgr_get_err_type(
core_idx = evt_payload->core_index;
evt_payload->evt_id = CAM_ISP_HW_EVENT_ERROR;
+ evt_payload->enable_reg_dump =
+ g_ife_hw_mgr.debug_cfg.enable_reg_dump;
list_for_each_entry(isp_ife_camif_res,
&ife_hwr_mgr_ctx->res_list_ife_src, list) {
@@ -3860,23 +4484,26 @@ static int cam_ife_hw_mgr_handle_camif_error(
error_status = cam_ife_hw_mgr_get_err_type(ife_hwr_mgr_ctx,
evt_payload);
-
- if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
- return error_status;
+ if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) {
+ rc = error_status;
+ goto end;
+ }
switch (error_status) {
case CAM_ISP_HW_ERROR_OVERFLOW:
case CAM_ISP_HW_ERROR_P2I_ERROR:
case CAM_ISP_HW_ERROR_VIOLATION:
CAM_ERR(CAM_ISP, "Enter: error_type (%d)", error_status);
- rc = -EFAULT;
-
+ rc = error_status;
if (g_ife_hw_mgr.debug_cfg.enable_recovery)
error_event_data.recovery_enabled = true;
error_event_data.error_type =
CAM_ISP_HW_ERROR_OVERFLOW;
+ error_event_data.enable_reg_dump =
+ g_ife_hw_mgr.debug_cfg.enable_reg_dump;
+
cam_ife_hw_mgr_find_affected_ctx(ife_hwr_mgr_ctx,
&error_event_data,
core_idx,
@@ -3897,6 +4524,7 @@ static int cam_ife_hw_mgr_handle_camif_error(
break;
}
+end:
return rc;
}
@@ -3946,6 +4574,7 @@ static int cam_ife_hw_mgr_handle_reg_update(
case CAM_ISP_HW_VFE_IN_CAMIF_LITE:
break;
case CAM_ISP_HW_VFE_IN_CAMIF:
+ case CAM_ISP_HW_VFE_IN_RD:
if (ife_src_res->is_dual_vfe)
/* It checks for slave core RUP ACK*/
hw_res = ife_src_res->hw_res[1];
@@ -3999,7 +4628,8 @@ static int cam_ife_hw_mgr_handle_reg_update(
rup_status = hw_res->bottom_half_handler(
hw_res, evt_payload);
- if (!ife_hwr_mgr_ctx->is_rdi_only_context)
+ if (ife_hwr_mgr_ctx->is_rdi_only_context == 0 &&
+ ife_hwr_mgr_ctx->is_fe_enable == false)
continue;
if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending))
@@ -4106,9 +4736,10 @@ static int cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(
list_for_each_entry(isp_ife_camif_res,
&ife_hwr_mgr_ctx->res_list_ife_src, list) {
if ((isp_ife_camif_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
- || (isp_ife_camif_res->res_id !=
- CAM_ISP_HW_VFE_IN_CAMIF))
+ || (isp_ife_camif_res->res_id >
+ CAM_ISP_HW_VFE_IN_RD)) {
continue;
+ }
hw_res_l = isp_ife_camif_res->hw_res[0];
hw_res_r = isp_ife_camif_res->hw_res[1];
@@ -4341,7 +4972,8 @@ static int cam_ife_hw_mgr_handle_sof(
hw_res, evt_payload);
/* check if it is rdi only context */
- if (ife_hw_mgr_ctx->is_rdi_only_context) {
+ if (ife_hw_mgr_ctx->is_fe_enable ||
+ ife_hw_mgr_ctx->is_rdi_only_context) {
if (!sof_status && !sof_sent) {
cam_ife_mgr_cmd_get_sof_timestamp(
ife_hw_mgr_ctx,
@@ -4352,7 +4984,7 @@ static int cam_ife_hw_mgr_handle_sof(
ife_hw_mgr_ctx->common.cb_priv,
CAM_ISP_HW_EVENT_SOF,
&sof_done_event_data);
- CAM_DBG(CAM_ISP, "sof_status = %d",
+ CAM_DBG(CAM_ISP, "RDI sof_status = %d",
sof_status);
sof_sent = true;
@@ -4362,6 +4994,7 @@ static int cam_ife_hw_mgr_handle_sof(
break;
case CAM_ISP_HW_VFE_IN_CAMIF:
+ case CAM_ISP_HW_VFE_IN_RD:
sof_status = cam_ife_hw_mgr_process_camif_sof(
ife_src_res, ife_hw_mgr_ctx, evt_payload);
if (!sof_status && !sof_sent) {
@@ -4832,6 +5465,14 @@ static int cam_ife_hw_mgr_debug_register(void)
return -ENOMEM;
}
+ if (!debugfs_create_u32("enable_reg_dump",
+ 0644,
+ g_ife_hw_mgr.debug_cfg.dentry,
+ &g_ife_hw_mgr.debug_cfg.enable_reg_dump)) {
+ CAM_ERR(CAM_ISP, "failed to create enable_reg_dump");
+ goto err;
+ }
+
if (!debugfs_create_file("ife_csid_debug",
0644,
g_ife_hw_mgr.debug_cfg.dentry, NULL,
@@ -4975,6 +5616,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_cid);
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_csid);
INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_src);
+ INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_in_rd);
ctx_pool = &g_ife_hw_mgr.ctx_pool[i];
for (j = 0; j < CAM_IFE_HW_OUT_RES_MAX; j++) {
res_list_ife_out = &ctx_pool->res_list_ife_out[j];
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index cf1e425558f3..bf5f1527caa4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@ enum cam_ife_hw_mgr_res_type {
CAM_IFE_HW_MGR_RES_CID,
CAM_IFE_HW_MGR_RES_CSID,
CAM_IFE_HW_MGR_RES_IFE_SRC,
+ CAM_IFE_HW_MGR_RES_IFE_IN_RD,
CAM_IFE_HW_MGR_RES_IFE_OUT,
};
@@ -87,6 +88,7 @@ struct ctx_base_info {
* @csid_debug: csid debug information
* @enable_recovery: enable recovery
* @enable_diag_sensor_status: enable sensor diagnosis status
+ * @enable_reg_dump: enable register dump on error
*
*/
struct cam_ife_hw_mgr_debug {
@@ -94,6 +96,7 @@ struct cam_ife_hw_mgr_debug {
uint64_t csid_debug;
uint32_t enable_recovery;
uint32_t camif_debug;
+ uint32_t enable_reg_dump;
};
/**
@@ -108,6 +111,7 @@ struct cam_ife_hw_mgr_debug {
* one.
* @res_list_csid: CSID resource list
* @res_list_ife_src: IFE input resource list
+ * @res_list_ife_in_rd IFE input resource list for read path
* @res_list_ife_out: IFE output resoruces array
* @free_res_list: Free resources list for the branch node
* @res_pool: memory storage for the free resource list
@@ -128,6 +132,8 @@ struct cam_ife_hw_mgr_debug {
* @is_rdi_only_context flag to specify the context has only rdi resource
* @config_done_complete indicator for configuration complete
* @init_done indicate whether init hw is done
+ * @is_fe_enable indicate whether fetch engine\read path is enabled
+ * @res_bitmap fill resource bitmap for which rup to be set
*/
struct cam_ife_hw_mgr_ctx {
struct list_head list;
@@ -141,6 +147,7 @@ struct cam_ife_hw_mgr_ctx {
struct list_head res_list_ife_cid;
struct list_head res_list_ife_csid;
struct list_head res_list_ife_src;
+ struct list_head res_list_ife_in_rd;
struct cam_ife_hw_mgr_res res_list_ife_out[
CAM_IFE_HW_OUT_RES_MAX];
@@ -162,6 +169,8 @@ struct cam_ife_hw_mgr_ctx {
uint32_t is_rdi_only_context;
struct completion config_done_complete;
bool init_done;
+ bool is_fe_enable;
+ unsigned long res_bitmap;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index cd1d024148ff..0b3c3874a704 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -105,7 +105,7 @@ static int cam_isp_update_dual_config(
struct cam_isp_hw_dual_isp_update_args dual_isp_update_args;
uint32_t outport_id;
uint32_t ports_plane_idx;
- size_t len = 0;
+ size_t len = 0, remain_len = 0;
uint32_t *cpu_addr;
uint32_t i, j;
@@ -117,9 +117,22 @@ static int cam_isp_update_dual_config(
if (rc)
return rc;
+ if ((len < sizeof(struct cam_isp_dual_config)) ||
+ (cmd_desc->offset >=
+ (len - sizeof(struct cam_isp_dual_config)))) {
+ CAM_ERR(CAM_UTIL, "not enough buffer provided");
+ return -EINVAL;
+ }
+ remain_len = len - cmd_desc->offset;
cpu_addr += (cmd_desc->offset / 4);
dual_config = (struct cam_isp_dual_config *)cpu_addr;
+ if ((dual_config->num_ports *
+ sizeof(struct cam_isp_dual_stripe_config)) >
+ (remain_len - offsetof(struct cam_isp_dual_config, stripes))) {
+ CAM_ERR(CAM_UTIL, "not enough buffer for all the dual configs");
+ return -EINVAL;
+ }
for (i = 0; i < dual_config->num_ports; i++) {
if (i >= CAM_ISP_IFE_OUT_RES_MAX) {
@@ -430,8 +443,11 @@ int cam_isp_add_io_buffers(
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info,
struct cam_ife_hw_mgr_res *res_list_isp_out,
+ struct list_head *res_list_ife_in_rd,
uint32_t size_isp_out,
- bool fill_fence)
+ bool fill_fence,
+ unsigned long *res_bitmap,
+ cam_fill_res_bitmap fill_res_bitmap)
{
int rc = 0;
uint64_t io_addr[CAM_PACKET_MAX_PLANES];
@@ -440,6 +456,7 @@ int cam_isp_add_io_buffers(
struct cam_ife_hw_mgr_res *hw_mgr_res;
struct cam_isp_hw_get_cmd_update update_buf;
struct cam_isp_hw_get_wm_update wm_update;
+ struct cam_isp_hw_get_wm_update bus_rd_update;
struct cam_hw_fence_map_entry *out_map_entries;
struct cam_hw_fence_map_entry *in_map_entries;
uint32_t kmd_buf_remain_size;
@@ -517,6 +534,15 @@ int cam_isp_add_io_buffers(
CAM_DBG(CAM_ISP,
"configure input io with fill fence %d",
fill_fence);
+ if (!list_empty(res_list_ife_in_rd)) {
+ hw_mgr_res =
+ list_first_entry(res_list_ife_in_rd,
+ struct cam_ife_hw_mgr_res, list);
+ } else {
+ CAM_ERR(CAM_ISP,
+ "No IFE in Read resource");
+ return -EINVAL;
+ }
in_map_entries =
&prepare->in_map_entries[num_in_buf];
if (fill_fence) {
@@ -533,7 +559,6 @@ int cam_isp_add_io_buffers(
return -EINVAL;
}
}
- continue;
} else {
CAM_ERR(CAM_ISP, "Invalid io config direction :%d",
io_cfg[i].direction);
@@ -541,7 +566,8 @@ int cam_isp_add_io_buffers(
}
CAM_DBG(CAM_ISP, "setup mem io");
- for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+ for (j = 0; j < CAM_ISP_HW_SPLIT_MAX &&
+ io_cfg[i].direction == CAM_BUF_OUTPUT; j++) {
if (!hw_mgr_res->hw_res[j])
continue;
@@ -656,6 +682,118 @@ int cam_isp_add_io_buffers(
}
io_cfg_used_bytes += update_buf.cmd.used_bytes;
}
+ for (j = 0; j < CAM_ISP_HW_SPLIT_MAX &&
+ io_cfg[i].direction == CAM_BUF_INPUT; j++) {
+ if (!hw_mgr_res->hw_res[j])
+ continue;
+
+ if (hw_mgr_res->hw_res[j]->hw_intf->hw_idx != base_idx)
+ continue;
+
+ res = hw_mgr_res->hw_res[j];
+
+ memset(io_addr, 0, sizeof(io_addr));
+
+ for (plane_id = 0; plane_id < CAM_PACKET_MAX_PLANES;
+ plane_id++) {
+ if (!io_cfg[i].mem_handle[plane_id])
+ break;
+
+ hdl = io_cfg[i].mem_handle[plane_id];
+ if (res->process_cmd(res,
+ CAM_ISP_HW_CMD_GET_SECURE_MODE,
+ &mode,
+ sizeof(bool)))
+ return -EINVAL;
+
+ is_buf_secure = cam_mem_is_secure_buf(hdl);
+ if ((mode == CAM_SECURE_MODE_SECURE) &&
+ is_buf_secure) {
+ mmu_hdl = sec_iommu_hdl;
+ } else if (
+ (mode == CAM_SECURE_MODE_NON_SECURE) &&
+ (!is_buf_secure)) {
+ mmu_hdl = iommu_hdl;
+ } else {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Invalid hdl: port mode[%u], buf mode[%u]",
+ mode, is_buf_secure);
+ return -EINVAL;
+ }
+
+ rc = cam_mem_get_io_buf(
+ io_cfg[i].mem_handle[plane_id],
+ mmu_hdl, &io_addr[plane_id], &size);
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "no io addr for plane%d",
+ plane_id);
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ /* need to update with offset */
+ io_addr[plane_id] +=
+ io_cfg[i].offsets[plane_id];
+ CAM_DBG(CAM_ISP,
+ "get io_addr for plane %d: 0x%llx, mem_hdl=0x%x",
+ plane_id, io_addr[plane_id],
+ io_cfg[i].mem_handle[plane_id]);
+
+ CAM_DBG(CAM_ISP,
+ "mmu_hdl=0x%x, size=%d, end=0x%x",
+ mmu_hdl, (int)size,
+ io_addr[plane_id]+size);
+
+ }
+ if (!plane_id) {
+ CAM_ERR(CAM_ISP, "No valid planes for res%d",
+ res->res_id);
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ if ((kmd_buf_info->used_bytes + io_cfg_used_bytes) <
+ kmd_buf_info->size) {
+ kmd_buf_remain_size = kmd_buf_info->size -
+ (kmd_buf_info->used_bytes +
+ io_cfg_used_bytes);
+ } else {
+ CAM_ERR(CAM_ISP,
+ "no free kmd memory for base %d",
+ base_idx);
+ rc = -ENOMEM;
+ return rc;
+ }
+ update_buf.res = res;
+ update_buf.cmd_type = CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM;
+ update_buf.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr +
+ kmd_buf_info->used_bytes/4 +
+ io_cfg_used_bytes/4;
+ bus_rd_update.image_buf = io_addr;
+ bus_rd_update.num_buf = plane_id;
+ bus_rd_update.io_cfg = &io_cfg[i];
+ update_buf.cmd.size = kmd_buf_remain_size;
+ update_buf.rm_update = &bus_rd_update;
+
+ CAM_DBG(CAM_ISP, "cmd buffer 0x%pK, size %d",
+ update_buf.cmd.cmd_buf_addr,
+ update_buf.cmd.size);
+ rc = res->hw_intf->hw_ops.process_cmd(
+ res->hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM, &update_buf,
+ sizeof(struct cam_isp_hw_get_cmd_update));
+
+ if (rc) {
+ CAM_ERR(CAM_ISP, "get buf cmd error:%d",
+ res->res_id);
+ rc = -ENOMEM;
+ return rc;
+ }
+ io_cfg_used_bytes += update_buf.cmd.used_bytes;
+ }
+
+ fill_res_bitmap(io_cfg[i].resource_type, res_bitmap);
}
CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d",
@@ -694,13 +832,16 @@ int cam_isp_add_reg_update(
struct cam_hw_prepare_update_args *prepare,
struct list_head *res_list_isp_src,
uint32_t base_idx,
- struct cam_kmd_buf_info *kmd_buf_info)
+ struct cam_kmd_buf_info *kmd_buf_info,
+ bool is_fe_en,
+ unsigned long res_bitmap)
{
int rc = -EINVAL;
struct cam_isp_resource_node *res;
struct cam_ife_hw_mgr_res *hw_mgr_res;
struct cam_hw_update_entry *hw_entry;
struct cam_isp_hw_get_cmd_update get_regup;
+ struct cam_isp_hw_rup_data rup_data;
uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size;
hw_entry = prepare->hw_update_entries;
@@ -746,6 +887,9 @@ int cam_isp_add_reg_update(
get_regup.cmd.size = kmd_buf_remain_size;
get_regup.cmd_type = CAM_ISP_HW_CMD_GET_REG_UPDATE;
get_regup.res = res;
+ rup_data.is_fe_enable = is_fe_en;
+ rup_data.res_bitmap = res_bitmap;
+ get_regup.rup_data = &rup_data;
rc = res->hw_intf->hw_ops.process_cmd(
res->hw_intf->hw_priv,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
index 9c1caa03e06c..806c2c657165 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -123,8 +123,11 @@ int cam_isp_add_command_buffers(
* @base_idx: Base or dev index of the IFE/VFE HW instance
* @kmd_buf_info: Kmd buffer to store the change base command
* @res_list_isp_out: IFE /VFE out resource list
+ * @res_list_ife_in_rd: IFE /VFE in rd resource list
* @size_isp_out: Size of the res_list_isp_out array
* @fill_fence: If true, Fence map table will be filled
+ * @res_bitmap resource bitmap to be set for rup
+ * @fill_res_bitmap callback function to set resource bitmap
*
* @return: 0 for success
* -EINVAL for Fail
@@ -136,8 +139,11 @@ int cam_isp_add_io_buffers(
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info,
struct cam_ife_hw_mgr_res *res_list_isp_out,
+ struct list_head *res_list_ife_in_rd,
uint32_t size_isp_out,
- bool fill_fence);
+ bool fill_fence,
+ unsigned long *res_bitmap,
+ cam_fill_res_bitmap fill_res_bitmap);
/*
* cam_isp_add_reg_update()
@@ -150,6 +156,9 @@ int cam_isp_add_io_buffers(
* @res_list_isp_src: Resource list for IFE/VFE source
* @base_idx: Base or dev index of the IFE/VFE HW instance
* @kmd_buf_info: Kmd buffer to store the change base command
+ * @is_fe_enable If fetch engine enable
+ * @res_bitmap resource bitmap to be set for rup
+ *
* @return: 0 for success
* -EINVAL for Fail
*/
@@ -157,6 +166,8 @@ int cam_isp_add_reg_update(
struct cam_hw_prepare_update_args *prepare,
struct list_head *res_list_isp_src,
uint32_t base_idx,
- struct cam_kmd_buf_info *kmd_buf_info);
+ struct cam_kmd_buf_info *kmd_buf_info,
+ bool is_fe_enable,
+ unsigned long res_bitmap);
#endif /*_CAM_ISP_HW_PARSER_H */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index e418fa97081d..c5808d45b0b1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -617,7 +617,7 @@ static void cam_irq_controller_th_processing(
evt_handler->bottom_half, &bh_cmd);
if (rc || !bh_cmd) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "Can't get bh payload");
+ "No payload, IRQ handling frozen");
continue;
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index 1a0f1ecab7b6..e9bcc98a8956 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,16 @@
#include <uapi/media/cam_isp.h>
#include "cam_hw_mgr_intf.h"
+/*
+ * bit position in resource bitmap
+ */
+#define CAM_IFE_REG_UPD_CMD_PIX_BIT 0
+#define CAM_IFE_REG_UPD_CMD_RDI0_BIT 1
+#define CAM_IFE_REG_UPD_CMD_RDI1_BIT 2
+#define CAM_IFE_REG_UPD_CMD_RDI2_BIT 3
+#define CAM_IFE_REG_UPD_CMD_RDI3_BIT 4
+#define CAM_IFE_REG_UPD_CMD_DUAL_PD_BIT 5
+
/* MAX IFE instance */
#define CAM_IFE_HW_NUM_MAX 4
#define CAM_IFE_RDI_NUM_MAX 4
@@ -186,11 +196,13 @@ struct cam_isp_hw_eof_event_data {
* @timestamp: Timestamp for the error event
* @recovery_enabled: Identifies if the context needs to recover & reapply
* this request
+ * @enable_reg_dump: enable register dump
*/
struct cam_isp_hw_error_event_data {
uint32_t error_type;
uint64_t timestamp;
bool recovery_enabled;
+ bool enable_reg_dump;
};
/* enum cam_isp_hw_mgr_command - Hardware manager command type */
@@ -199,20 +211,28 @@ enum cam_isp_hw_mgr_command {
CAM_ISP_HW_MGR_CMD_PAUSE_HW,
CAM_ISP_HW_MGR_CMD_RESUME_HW,
CAM_ISP_HW_MGR_CMD_SOF_DEBUG,
+ CAM_ISP_HW_MGR_CMD_CTX_TYPE,
CAM_ISP_HW_MGR_CMD_MAX,
};
+enum cam_isp_ctx_type {
+ CAM_ISP_CTX_FS2 = 1,
+ CAM_ISP_CTX_RDI,
+ CAM_ISP_CTX_PIX,
+ CAM_ISP_CTX_MAX,
+};
/**
* struct cam_isp_hw_cmd_args - Payload for hw manager command
*
* @cmd_type HW command type
- * @get_context Get context type information
+ * @sof_irq_enable To debug if SOF irq is enabled
+ * @ctx_type RDI_ONLY, PIX and RDI, or FS2
*/
struct cam_isp_hw_cmd_args {
- uint32_t cmd_type;
+ uint32_t cmd_type;
union {
- uint32_t is_rdi_only_context;
uint32_t sof_irq_enable;
+ uint32_t ctx_type;
} u;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c
deleted file mode 100644
index 70223f1427f5..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-
-#include <linux/module.h>
-#include "cam_ife_csid_core.h"
-#include "cam_ife_csid170.h"
-#include "cam_ife_csid_dev.h"
-
-#define CAM_CSID_DRV_NAME "csid_170"
-#define CAM_CSID_VERSION_V170 0x10070000
-
-static struct cam_ife_csid_hw_info cam_ife_csid170_hw_info = {
- .csid_reg = &cam_ife_csid_170_reg_offset,
- .hw_dts_version = CAM_CSID_VERSION_V170,
-};
-
-static const struct of_device_id cam_ife_csid170_dt_match[] = {
- {
- .compatible = "qcom,csid170",
- .data = &cam_ife_csid170_hw_info,
- },
- {}
-};
-
-MODULE_DEVICE_TABLE(of, cam_ife_csid170_dt_match);
-
-static struct platform_driver cam_ife_csid170_driver = {
- .probe = cam_ife_csid_probe,
- .remove = cam_ife_csid_remove,
- .driver = {
- .name = CAM_CSID_DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = cam_ife_csid170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_ife_csid170_init_module(void)
-{
- return platform_driver_register(&cam_ife_csid170_driver);
-}
-
-static void __exit cam_ife_csid170_exit_module(void)
-{
- platform_driver_unregister(&cam_ife_csid170_driver);
-}
-
-module_init(cam_ife_csid170_init_module);
-module_exit(cam_ife_csid170_exit_module);
-MODULE_DESCRIPTION("CAM IFE_CSID170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
index 85fec0f15dcd..576e8cb8d3b8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -222,6 +222,7 @@ static struct cam_ife_csid_csi2_rx_reg_offset
.csi2_capture_short_pkt_vc_shift = 15,
.csi2_capture_cphy_pkt_dt_shift = 20,
.csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x3,
};
static struct cam_ife_csid_csi2_tpg_reg_offset
@@ -273,6 +274,7 @@ static struct cam_ife_csid_common_reg_offset
.num_rdis = 3,
.num_pix = 1,
.num_ppp = 0,
+ .csid_reg_rst_stb = 1,
.csid_rst_stb = 0x1e,
.csid_rst_stb_sw_all = 0x1f,
.path_rst_stb_all = 0x7f,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
index 4fdc518c0385..42f0f290a166 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,56 +10,93 @@
* GNU General Public License for more details.
*/
-#ifndef _CAM_IFE_CSID_LITE170_H_
-#define _CAM_IFE_CSID_LITE170_H_
+#ifndef _CAM_IFE_CSID_175_H_
+#define _CAM_IFE_CSID_175_H_
+
#include "cam_ife_csid_core.h"
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_0_reg_offset = {
+static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_175_ipp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0x30,
+ .csid_pxl_irq_mask_addr = 0x34,
+ .csid_pxl_irq_clear_addr = 0x38,
+ .csid_pxl_irq_set_addr = 0x3c,
+
+ .csid_pxl_cfg0_addr = 0x200,
+ .csid_pxl_cfg1_addr = 0x204,
+ .csid_pxl_ctrl_addr = 0x208,
+ .csid_pxl_frm_drop_pattern_addr = 0x20c,
+ .csid_pxl_frm_drop_period_addr = 0x210,
+ .csid_pxl_irq_subsample_pattern_addr = 0x214,
+ .csid_pxl_irq_subsample_period_addr = 0x218,
+ .csid_pxl_hcrop_addr = 0x21c,
+ .csid_pxl_vcrop_addr = 0x220,
+ .csid_pxl_pix_drop_pattern_addr = 0x224,
+ .csid_pxl_pix_drop_period_addr = 0x228,
+ .csid_pxl_line_drop_pattern_addr = 0x22c,
+ .csid_pxl_line_drop_period_addr = 0x230,
+ .csid_pxl_rst_strobes_addr = 0x240,
+ .csid_pxl_status_addr = 0x254,
+ .csid_pxl_misr_val_addr = 0x258,
+ .csid_pxl_format_measure_cfg0_addr = 0x270,
+ .csid_pxl_format_measure_cfg1_addr = 0x274,
+ .csid_pxl_format_measure0_addr = 0x278,
+ .csid_pxl_format_measure1_addr = 0x27c,
+ .csid_pxl_format_measure2_addr = 0x280,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x290,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x294,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x298,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x29c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x2a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x2a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x2a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x2ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
+};
+
+static struct cam_ife_csid_pxl_reg_offset cam_ife_csid_175_ppp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0xa0,
+ .csid_pxl_irq_mask_addr = 0xa4,
+ .csid_pxl_irq_clear_addr = 0xa8,
+ .csid_pxl_irq_set_addr = 0xac,
- .csid_rdi_irq_status_addr = 0x30,
- .csid_rdi_irq_mask_addr = 0x34,
- .csid_rdi_irq_clear_addr = 0x38,
- .csid_rdi_irq_set_addr = 0x3c,
- .csid_rdi_cfg0_addr = 0x200,
- .csid_rdi_cfg1_addr = 0x204,
- .csid_rdi_ctrl_addr = 0x208,
- .csid_rdi_frm_drop_pattern_addr = 0x20c,
- .csid_rdi_frm_drop_period_addr = 0x210,
- .csid_rdi_irq_subsample_pattern_addr = 0x214,
- .csid_rdi_irq_subsample_period_addr = 0x218,
- .csid_rdi_rpp_hcrop_addr = 0x21c,
- .csid_rdi_rpp_vcrop_addr = 0x220,
- .csid_rdi_rpp_pix_drop_pattern_addr = 0x224,
- .csid_rdi_rpp_pix_drop_period_addr = 0x228,
- .csid_rdi_rpp_line_drop_pattern_addr = 0x22c,
- .csid_rdi_rpp_line_drop_period_addr = 0x230,
- .csid_rdi_rst_strobes_addr = 0x240,
- .csid_rdi_status_addr = 0x250,
- .csid_rdi_misr_val0_addr = 0x254,
- .csid_rdi_misr_val1_addr = 0x258,
- .csid_rdi_misr_val2_addr = 0x25c,
- .csid_rdi_misr_val3_addr = 0x260,
- .csid_rdi_format_measure_cfg0_addr = 0x270,
- .csid_rdi_format_measure_cfg1_addr = 0x274,
- .csid_rdi_format_measure0_addr = 0x278,
- .csid_rdi_format_measure1_addr = 0x27c,
- .csid_rdi_format_measure2_addr = 0x280,
- .csid_rdi_timestamp_curr0_sof_addr = 0x290,
- .csid_rdi_timestamp_curr1_sof_addr = 0x294,
- .csid_rdi_timestamp_prev0_sof_addr = 0x298,
- .csid_rdi_timestamp_prev1_sof_addr = 0x29c,
- .csid_rdi_timestamp_curr0_eof_addr = 0x2a0,
- .csid_rdi_timestamp_curr1_eof_addr = 0x2a4,
- .csid_rdi_timestamp_prev0_eof_addr = 0x2a8,
- .csid_rdi_timestamp_prev1_eof_addr = 0x2ac,
- .csid_rdi_byte_cntr_ping_addr = 0x2e0,
- .csid_rdi_byte_cntr_pong_addr = 0x2e4,
+ .csid_pxl_cfg0_addr = 0x700,
+ .csid_pxl_cfg1_addr = 0x704,
+ .csid_pxl_ctrl_addr = 0x708,
+ .csid_pxl_frm_drop_pattern_addr = 0x70c,
+ .csid_pxl_frm_drop_period_addr = 0x710,
+ .csid_pxl_irq_subsample_pattern_addr = 0x714,
+ .csid_pxl_irq_subsample_period_addr = 0x718,
+ .csid_pxl_hcrop_addr = 0x71c,
+ .csid_pxl_vcrop_addr = 0x720,
+ .csid_pxl_pix_drop_pattern_addr = 0x724,
+ .csid_pxl_pix_drop_period_addr = 0x728,
+ .csid_pxl_line_drop_pattern_addr = 0x72c,
+ .csid_pxl_line_drop_period_addr = 0x730,
+ .csid_pxl_rst_strobes_addr = 0x740,
+ .csid_pxl_status_addr = 0x754,
+ .csid_pxl_misr_val_addr = 0x758,
+ .csid_pxl_format_measure_cfg0_addr = 0x770,
+ .csid_pxl_format_measure_cfg1_addr = 0x774,
+ .csid_pxl_format_measure0_addr = 0x778,
+ .csid_pxl_format_measure1_addr = 0x77c,
+ .csid_pxl_format_measure2_addr = 0x780,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x790,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x794,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x798,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x79c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x7a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x7a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x7a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x7ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
};
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_1_reg_offset = {
+static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_175_rdi_0_reg_offset = {
.csid_rdi_irq_status_addr = 0x40,
.csid_rdi_irq_mask_addr = 0x44,
.csid_rdi_irq_clear_addr = 0x48,
@@ -100,9 +137,7 @@ static struct cam_ife_csid_rdi_reg_offset
.csid_rdi_byte_cntr_pong_addr = 0x3e4,
};
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_2_reg_offset = {
-
+static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_175_rdi_1_reg_offset = {
.csid_rdi_irq_status_addr = 0x50,
.csid_rdi_irq_mask_addr = 0x54,
.csid_rdi_irq_clear_addr = 0x58,
@@ -120,7 +155,6 @@ static struct cam_ife_csid_rdi_reg_offset
.csid_rdi_rpp_pix_drop_period_addr = 0x428,
.csid_rdi_rpp_line_drop_pattern_addr = 0x42c,
.csid_rdi_rpp_line_drop_period_addr = 0x430,
- .csid_rdi_yuv_chroma_conversion_addr = 0x434,
.csid_rdi_rst_strobes_addr = 0x440,
.csid_rdi_status_addr = 0x450,
.csid_rdi_misr_val0_addr = 0x454,
@@ -144,9 +178,7 @@ static struct cam_ife_csid_rdi_reg_offset
.csid_rdi_byte_cntr_pong_addr = 0x4e4,
};
-static struct cam_ife_csid_rdi_reg_offset
- cam_ife_csid_lite_170_rdi_3_reg_offset = {
-
+static struct cam_ife_csid_rdi_reg_offset cam_ife_csid_175_rdi_2_reg_offset = {
.csid_rdi_irq_status_addr = 0x60,
.csid_rdi_irq_mask_addr = 0x64,
.csid_rdi_irq_clear_addr = 0x68,
@@ -189,8 +221,7 @@ static struct cam_ife_csid_rdi_reg_offset
};
static struct cam_ife_csid_csi2_rx_reg_offset
- cam_ife_csid_lite_170_csi2_reg_offset = {
-
+ cam_ife_csid_175_csi2_reg_offset = {
.csid_csi2_rx_irq_status_addr = 0x20,
.csid_csi2_rx_irq_mask_addr = 0x24,
.csid_csi2_rx_irq_clear_addr = 0x28,
@@ -232,12 +263,11 @@ static struct cam_ife_csid_csi2_rx_reg_offset
.csi2_capture_short_pkt_vc_shift = 15,
.csi2_capture_cphy_pkt_dt_shift = 20,
.csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x3,
};
-
static struct cam_ife_csid_csi2_tpg_reg_offset
- cam_ife_csid_lite_170_tpg_reg_offset = {
-
+ cam_ife_csid_175_tpg_reg_offset = {
/*CSID TPG control */
.csid_tpg_ctrl_addr = 0x600,
.csid_tpg_vc_cfg0_addr = 0x604,
@@ -257,16 +287,14 @@ static struct cam_ife_csid_csi2_tpg_reg_offset
.csid_tpg_cgen_n_y1_addr = 0x664,
.csid_tpg_cgen_n_y2_addr = 0x668,
- /*configurations */
+ /* configurations */
.tpg_dtn_cfg_offset = 0xc,
.tpg_cgen_cfg_offset = 0x20,
.tpg_cpas_ife_reg_offset = 0x28,
};
-
static struct cam_ife_csid_common_reg_offset
- cam_csid_lite_170_cmn_reg_offset = {
-
+ cam_ife_csid_175_cmn_reg_offset = {
.csid_hw_version_addr = 0x0,
.csid_cfg0_addr = 0x4,
.csid_ctrl_addr = 0x8,
@@ -284,8 +312,10 @@ static struct cam_ife_csid_common_reg_offset
.major_version = 1,
.minor_version = 7,
.version_incr = 0,
- .no_rdis = 4,
- .no_pix = 0,
+ .num_rdis = 3,
+ .num_pix = 1,
+ .num_ppp = 1,
+ .csid_reg_rst_stb = 1,
.csid_rst_stb = 0x1e,
.csid_rst_stb_sw_all = 0x1f,
.path_rst_stb_all = 0x7f,
@@ -301,19 +331,23 @@ static struct cam_ife_csid_common_reg_offset
.crop_shift = 16,
.ipp_irq_mask_all = 0x7FFF,
.rdi_irq_mask_all = 0x7FFF,
+ .ppp_irq_mask_all = 0xFFFF,
+ .measure_en_hbi_vbi_cnt_mask = 0xC,
+ .format_measure_en_val = 1,
};
-struct cam_ife_csid_reg_offset cam_ife_csid_lite_170_reg_offset = {
- .cmn_reg = &cam_csid_lite_170_cmn_reg_offset,
- .csi2_reg = &cam_ife_csid_lite_170_csi2_reg_offset,
- .ipp_reg = NULL,
+static struct cam_ife_csid_reg_offset cam_ife_csid_175_reg_offset = {
+ .cmn_reg = &cam_ife_csid_175_cmn_reg_offset,
+ .csi2_reg = &cam_ife_csid_175_csi2_reg_offset,
+ .ipp_reg = &cam_ife_csid_175_ipp_reg_offset,
+ .ppp_reg = &cam_ife_csid_175_ppp_reg_offset,
.rdi_reg = {
- &cam_ife_csid_lite_170_rdi_0_reg_offset,
- &cam_ife_csid_lite_170_rdi_1_reg_offset,
- &cam_ife_csid_lite_170_rdi_2_reg_offset,
- &cam_ife_csid_lite_170_rdi_3_reg_offset,
+ &cam_ife_csid_175_rdi_0_reg_offset,
+ &cam_ife_csid_175_rdi_1_reg_offset,
+ &cam_ife_csid_175_rdi_2_reg_offset,
+ NULL,
},
- .tpg_reg = &cam_ife_csid_lite_170_tpg_reg_offset,
+ .tpg_reg = &cam_ife_csid_175_tpg_reg_offset,
};
-#endif /*_CAM_IFE_CSID_LITE170_H_ */
+#endif /*_CAM_IFE_CSID_175_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h
new file mode 100644
index 000000000000..8a78fe0b9b0d
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h
@@ -0,0 +1,369 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_IFE_CSID_175_200_H_
+#define _CAM_IFE_CSID_175_200_H_
+
+#include "cam_ife_csid_core.h"
+
+static struct cam_ife_csid_pxl_reg_offset
+ cam_ife_csid_175_200_ipp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0x30,
+ .csid_pxl_irq_mask_addr = 0x34,
+ .csid_pxl_irq_clear_addr = 0x38,
+ .csid_pxl_irq_set_addr = 0x3c,
+
+ .csid_pxl_cfg0_addr = 0x200,
+ .csid_pxl_cfg1_addr = 0x204,
+ .csid_pxl_ctrl_addr = 0x208,
+ .csid_pxl_frm_drop_pattern_addr = 0x20c,
+ .csid_pxl_frm_drop_period_addr = 0x210,
+ .csid_pxl_irq_subsample_pattern_addr = 0x214,
+ .csid_pxl_irq_subsample_period_addr = 0x218,
+ .csid_pxl_hcrop_addr = 0x21c,
+ .csid_pxl_vcrop_addr = 0x220,
+ .csid_pxl_pix_drop_pattern_addr = 0x224,
+ .csid_pxl_pix_drop_period_addr = 0x228,
+ .csid_pxl_line_drop_pattern_addr = 0x22c,
+ .csid_pxl_line_drop_period_addr = 0x230,
+ .csid_pxl_rst_strobes_addr = 0x240,
+ .csid_pxl_status_addr = 0x254,
+ .csid_pxl_misr_val_addr = 0x258,
+ .csid_pxl_format_measure_cfg0_addr = 0x270,
+ .csid_pxl_format_measure_cfg1_addr = 0x274,
+ .csid_pxl_format_measure0_addr = 0x278,
+ .csid_pxl_format_measure1_addr = 0x27c,
+ .csid_pxl_format_measure2_addr = 0x280,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x290,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x294,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x298,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x29c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x2a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x2a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x2a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x2ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_pxl_reg_offset
+ cam_ife_csid_175_200_ppp_reg_offset = {
+ .csid_pxl_irq_status_addr = 0xa0,
+ .csid_pxl_irq_mask_addr = 0xa4,
+ .csid_pxl_irq_clear_addr = 0xa8,
+ .csid_pxl_irq_set_addr = 0xac,
+
+ .csid_pxl_cfg0_addr = 0x700,
+ .csid_pxl_cfg1_addr = 0x704,
+ .csid_pxl_ctrl_addr = 0x708,
+ .csid_pxl_frm_drop_pattern_addr = 0x70c,
+ .csid_pxl_frm_drop_period_addr = 0x710,
+ .csid_pxl_irq_subsample_pattern_addr = 0x714,
+ .csid_pxl_irq_subsample_period_addr = 0x718,
+ .csid_pxl_hcrop_addr = 0x71c,
+ .csid_pxl_vcrop_addr = 0x720,
+ .csid_pxl_pix_drop_pattern_addr = 0x724,
+ .csid_pxl_pix_drop_period_addr = 0x728,
+ .csid_pxl_line_drop_pattern_addr = 0x72c,
+ .csid_pxl_line_drop_period_addr = 0x730,
+ .csid_pxl_rst_strobes_addr = 0x740,
+ .csid_pxl_status_addr = 0x754,
+ .csid_pxl_misr_val_addr = 0x758,
+ .csid_pxl_format_measure_cfg0_addr = 0x770,
+ .csid_pxl_format_measure_cfg1_addr = 0x774,
+ .csid_pxl_format_measure0_addr = 0x778,
+ .csid_pxl_format_measure1_addr = 0x77c,
+ .csid_pxl_format_measure2_addr = 0x780,
+ .csid_pxl_timestamp_curr0_sof_addr = 0x790,
+ .csid_pxl_timestamp_curr1_sof_addr = 0x794,
+ .csid_pxl_timestamp_perv0_sof_addr = 0x798,
+ .csid_pxl_timestamp_perv1_sof_addr = 0x79c,
+ .csid_pxl_timestamp_curr0_eof_addr = 0x7a0,
+ .csid_pxl_timestamp_curr1_eof_addr = 0x7a4,
+ .csid_pxl_timestamp_perv0_eof_addr = 0x7a8,
+ .csid_pxl_timestamp_perv1_eof_addr = 0x7ac,
+ /* configurations */
+ .pix_store_en_shift_val = 7,
+ .early_eof_en_shift_val = 29,
+ .ccif_violation_en = 1,
+};
+
+
+static struct cam_ife_csid_rdi_reg_offset
+ cam_ife_csid_175_200_rdi_0_reg_offset = {
+ .csid_rdi_irq_status_addr = 0x40,
+ .csid_rdi_irq_mask_addr = 0x44,
+ .csid_rdi_irq_clear_addr = 0x48,
+ .csid_rdi_irq_set_addr = 0x4c,
+ .csid_rdi_cfg0_addr = 0x300,
+ .csid_rdi_cfg1_addr = 0x304,
+ .csid_rdi_ctrl_addr = 0x308,
+ .csid_rdi_frm_drop_pattern_addr = 0x30c,
+ .csid_rdi_frm_drop_period_addr = 0x310,
+ .csid_rdi_irq_subsample_pattern_addr = 0x314,
+ .csid_rdi_irq_subsample_period_addr = 0x318,
+ .csid_rdi_rpp_hcrop_addr = 0x31c,
+ .csid_rdi_rpp_vcrop_addr = 0x320,
+ .csid_rdi_rpp_pix_drop_pattern_addr = 0x324,
+ .csid_rdi_rpp_pix_drop_period_addr = 0x328,
+ .csid_rdi_rpp_line_drop_pattern_addr = 0x32c,
+ .csid_rdi_rpp_line_drop_period_addr = 0x330,
+ .csid_rdi_rst_strobes_addr = 0x340,
+ .csid_rdi_status_addr = 0x350,
+ .csid_rdi_misr_val0_addr = 0x354,
+ .csid_rdi_misr_val1_addr = 0x358,
+ .csid_rdi_misr_val2_addr = 0x35c,
+ .csid_rdi_misr_val3_addr = 0x360,
+ .csid_rdi_format_measure_cfg0_addr = 0x370,
+ .csid_rdi_format_measure_cfg1_addr = 0x374,
+ .csid_rdi_format_measure0_addr = 0x378,
+ .csid_rdi_format_measure1_addr = 0x37c,
+ .csid_rdi_format_measure2_addr = 0x380,
+ .csid_rdi_timestamp_curr0_sof_addr = 0x390,
+ .csid_rdi_timestamp_curr1_sof_addr = 0x394,
+ .csid_rdi_timestamp_prev0_sof_addr = 0x398,
+ .csid_rdi_timestamp_prev1_sof_addr = 0x39c,
+ .csid_rdi_timestamp_curr0_eof_addr = 0x3a0,
+ .csid_rdi_timestamp_curr1_eof_addr = 0x3a4,
+ .csid_rdi_timestamp_prev0_eof_addr = 0x3a8,
+ .csid_rdi_timestamp_prev1_eof_addr = 0x3ac,
+ .csid_rdi_byte_cntr_ping_addr = 0x3e0,
+ .csid_rdi_byte_cntr_pong_addr = 0x3e4,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_rdi_reg_offset
+ cam_ife_csid_175_200_rdi_1_reg_offset = {
+ .csid_rdi_irq_status_addr = 0x50,
+ .csid_rdi_irq_mask_addr = 0x54,
+ .csid_rdi_irq_clear_addr = 0x58,
+ .csid_rdi_irq_set_addr = 0x5c,
+ .csid_rdi_cfg0_addr = 0x400,
+ .csid_rdi_cfg1_addr = 0x404,
+ .csid_rdi_ctrl_addr = 0x408,
+ .csid_rdi_frm_drop_pattern_addr = 0x40c,
+ .csid_rdi_frm_drop_period_addr = 0x410,
+ .csid_rdi_irq_subsample_pattern_addr = 0x414,
+ .csid_rdi_irq_subsample_period_addr = 0x418,
+ .csid_rdi_rpp_hcrop_addr = 0x41c,
+ .csid_rdi_rpp_vcrop_addr = 0x420,
+ .csid_rdi_rpp_pix_drop_pattern_addr = 0x424,
+ .csid_rdi_rpp_pix_drop_period_addr = 0x428,
+ .csid_rdi_rpp_line_drop_pattern_addr = 0x42c,
+ .csid_rdi_rpp_line_drop_period_addr = 0x430,
+ .csid_rdi_rst_strobes_addr = 0x440,
+ .csid_rdi_status_addr = 0x450,
+ .csid_rdi_misr_val0_addr = 0x454,
+ .csid_rdi_misr_val1_addr = 0x458,
+ .csid_rdi_misr_val2_addr = 0x45c,
+ .csid_rdi_misr_val3_addr = 0x460,
+ .csid_rdi_format_measure_cfg0_addr = 0x470,
+ .csid_rdi_format_measure_cfg1_addr = 0x474,
+ .csid_rdi_format_measure0_addr = 0x478,
+ .csid_rdi_format_measure1_addr = 0x47c,
+ .csid_rdi_format_measure2_addr = 0x480,
+ .csid_rdi_timestamp_curr0_sof_addr = 0x490,
+ .csid_rdi_timestamp_curr1_sof_addr = 0x494,
+ .csid_rdi_timestamp_prev0_sof_addr = 0x498,
+ .csid_rdi_timestamp_prev1_sof_addr = 0x49c,
+ .csid_rdi_timestamp_curr0_eof_addr = 0x4a0,
+ .csid_rdi_timestamp_curr1_eof_addr = 0x4a4,
+ .csid_rdi_timestamp_prev0_eof_addr = 0x4a8,
+ .csid_rdi_timestamp_prev1_eof_addr = 0x4ac,
+ .csid_rdi_byte_cntr_ping_addr = 0x4e0,
+ .csid_rdi_byte_cntr_pong_addr = 0x4e4,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_rdi_reg_offset
+ cam_ife_csid_175_200_rdi_2_reg_offset = {
+ .csid_rdi_irq_status_addr = 0x60,
+ .csid_rdi_irq_mask_addr = 0x64,
+ .csid_rdi_irq_clear_addr = 0x68,
+ .csid_rdi_irq_set_addr = 0x6c,
+ .csid_rdi_cfg0_addr = 0x500,
+ .csid_rdi_cfg1_addr = 0x504,
+ .csid_rdi_ctrl_addr = 0x508,
+ .csid_rdi_frm_drop_pattern_addr = 0x50c,
+ .csid_rdi_frm_drop_period_addr = 0x510,
+ .csid_rdi_irq_subsample_pattern_addr = 0x514,
+ .csid_rdi_irq_subsample_period_addr = 0x518,
+ .csid_rdi_rpp_hcrop_addr = 0x51c,
+ .csid_rdi_rpp_vcrop_addr = 0x520,
+ .csid_rdi_rpp_pix_drop_pattern_addr = 0x524,
+ .csid_rdi_rpp_pix_drop_period_addr = 0x528,
+ .csid_rdi_rpp_line_drop_pattern_addr = 0x52c,
+ .csid_rdi_rpp_line_drop_period_addr = 0x530,
+ .csid_rdi_yuv_chroma_conversion_addr = 0x534,
+ .csid_rdi_rst_strobes_addr = 0x540,
+ .csid_rdi_status_addr = 0x550,
+ .csid_rdi_misr_val0_addr = 0x554,
+ .csid_rdi_misr_val1_addr = 0x558,
+ .csid_rdi_misr_val2_addr = 0x55c,
+ .csid_rdi_misr_val3_addr = 0x560,
+ .csid_rdi_format_measure_cfg0_addr = 0x570,
+ .csid_rdi_format_measure_cfg1_addr = 0x574,
+ .csid_rdi_format_measure0_addr = 0x578,
+ .csid_rdi_format_measure1_addr = 0x57c,
+ .csid_rdi_format_measure2_addr = 0x580,
+ .csid_rdi_timestamp_curr0_sof_addr = 0x590,
+ .csid_rdi_timestamp_curr1_sof_addr = 0x594,
+ .csid_rdi_timestamp_prev0_sof_addr = 0x598,
+ .csid_rdi_timestamp_prev1_sof_addr = 0x59c,
+ .csid_rdi_timestamp_curr0_eof_addr = 0x5a0,
+ .csid_rdi_timestamp_curr1_eof_addr = 0x5a4,
+ .csid_rdi_timestamp_prev0_eof_addr = 0x5a8,
+ .csid_rdi_timestamp_prev1_eof_addr = 0x5ac,
+ .csid_rdi_byte_cntr_ping_addr = 0x5e0,
+ .csid_rdi_byte_cntr_pong_addr = 0x5e4,
+ .ccif_violation_en = 1,
+};
+
+static struct cam_ife_csid_csi2_rx_reg_offset
+ cam_ife_csid_175_200_csi2_reg_offset = {
+ .csid_csi2_rx_irq_status_addr = 0x20,
+ .csid_csi2_rx_irq_mask_addr = 0x24,
+ .csid_csi2_rx_irq_clear_addr = 0x28,
+ .csid_csi2_rx_irq_set_addr = 0x2c,
+
+ /*CSI2 rx control */
+ .csid_csi2_rx_cfg0_addr = 0x100,
+ .csid_csi2_rx_cfg1_addr = 0x104,
+ .csid_csi2_rx_capture_ctrl_addr = 0x108,
+ .csid_csi2_rx_rst_strobes_addr = 0x110,
+ .csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr = 0x120,
+ .csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr = 0x124,
+ .csid_csi2_rx_captured_short_pkt_0_addr = 0x128,
+ .csid_csi2_rx_captured_short_pkt_1_addr = 0x12c,
+ .csid_csi2_rx_captured_long_pkt_0_addr = 0x130,
+ .csid_csi2_rx_captured_long_pkt_1_addr = 0x134,
+ .csid_csi2_rx_captured_long_pkt_ftr_addr = 0x138,
+ .csid_csi2_rx_captured_cphy_pkt_hdr_addr = 0x13c,
+ .csid_csi2_rx_lane0_misr_addr = 0x150,
+ .csid_csi2_rx_lane1_misr_addr = 0x154,
+ .csid_csi2_rx_lane2_misr_addr = 0x158,
+ .csid_csi2_rx_lane3_misr_addr = 0x15c,
+ .csid_csi2_rx_total_pkts_rcvd_addr = 0x160,
+ .csid_csi2_rx_stats_ecc_addr = 0x164,
+ .csid_csi2_rx_total_crc_err_addr = 0x168,
+ .csid_csi2_rx_de_scramble_type3_cfg0_addr = 0x170,
+ .csid_csi2_rx_de_scramble_type3_cfg1_addr = 0x174,
+ .csid_csi2_rx_de_scramble_type2_cfg0_addr = 0x178,
+ .csid_csi2_rx_de_scramble_type2_cfg1_addr = 0x17c,
+ .csid_csi2_rx_de_scramble_type1_cfg0_addr = 0x180,
+ .csid_csi2_rx_de_scramble_type1_cfg1_addr = 0x184,
+ .csid_csi2_rx_de_scramble_type0_cfg0_addr = 0x188,
+ .csid_csi2_rx_de_scramble_type0_cfg1_addr = 0x18c,
+
+ .csi2_rst_srb_all = 0x3FFF,
+ .csi2_rst_done_shift_val = 27,
+ .csi2_irq_mask_all = 0xFFFFFFF,
+ .csi2_misr_enable_shift_val = 6,
+ .csi2_vc_mode_shift_val = 2,
+ .csi2_capture_long_pkt_en_shift = 0,
+ .csi2_capture_short_pkt_en_shift = 1,
+ .csi2_capture_cphy_pkt_en_shift = 2,
+ .csi2_capture_long_pkt_dt_shift = 4,
+ .csi2_capture_long_pkt_vc_shift = 10,
+ .csi2_capture_short_pkt_vc_shift = 15,
+ .csi2_capture_cphy_pkt_dt_shift = 20,
+ .csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x7,
+};
+
+static struct cam_ife_csid_csi2_tpg_reg_offset
+ cam_ife_csid_175_200_tpg_reg_offset = {
+ /*CSID TPG control */
+ .csid_tpg_ctrl_addr = 0x600,
+ .csid_tpg_vc_cfg0_addr = 0x604,
+ .csid_tpg_vc_cfg1_addr = 0x608,
+ .csid_tpg_lfsr_seed_addr = 0x60c,
+ .csid_tpg_dt_n_cfg_0_addr = 0x610,
+ .csid_tpg_dt_n_cfg_1_addr = 0x614,
+ .csid_tpg_dt_n_cfg_2_addr = 0x618,
+ .csid_tpg_color_bars_cfg_addr = 0x640,
+ .csid_tpg_color_box_cfg_addr = 0x644,
+ .csid_tpg_common_gen_cfg_addr = 0x648,
+ .csid_tpg_cgen_n_cfg_addr = 0x650,
+ .csid_tpg_cgen_n_x0_addr = 0x654,
+ .csid_tpg_cgen_n_x1_addr = 0x658,
+ .csid_tpg_cgen_n_x2_addr = 0x65c,
+ .csid_tpg_cgen_n_xy_addr = 0x660,
+ .csid_tpg_cgen_n_y1_addr = 0x664,
+ .csid_tpg_cgen_n_y2_addr = 0x668,
+
+ /* configurations */
+ .tpg_dtn_cfg_offset = 0xc,
+ .tpg_cgen_cfg_offset = 0x20,
+ .tpg_cpas_ife_reg_offset = 0x28,
+};
+
+static struct cam_ife_csid_common_reg_offset
+ cam_ife_csid_175_200_cmn_reg_offset = {
+ .csid_hw_version_addr = 0x0,
+ .csid_cfg0_addr = 0x4,
+ .csid_ctrl_addr = 0x8,
+ .csid_reset_addr = 0xc,
+ .csid_rst_strobes_addr = 0x10,
+
+ .csid_test_bus_ctrl_addr = 0x14,
+ .csid_top_irq_status_addr = 0x70,
+ .csid_top_irq_mask_addr = 0x74,
+ .csid_top_irq_clear_addr = 0x78,
+ .csid_top_irq_set_addr = 0x7c,
+ .csid_irq_cmd_addr = 0x80,
+
+ /*configurations */
+ .major_version = 1,
+ .minor_version = 7,
+ .version_incr = 5,
+ .num_rdis = 3,
+ .num_pix = 1,
+ .num_ppp = 1,
+ .csid_reg_rst_stb = 1,
+ .csid_rst_stb = 0x1e,
+ .csid_rst_stb_sw_all = 0x1f,
+ .path_rst_stb_all = 0x7f,
+ .path_rst_done_shift_val = 1,
+ .path_en_shift_val = 31,
+ .dt_id_shift_val = 27,
+ .vc_shift_val = 22,
+ .dt_shift_val = 16,
+ .fmt_shift_val = 12,
+ .plain_fmt_shit_val = 10,
+ .crop_v_en_shift_val = 6,
+ .crop_h_en_shift_val = 5,
+ .crop_shift = 16,
+ .ipp_irq_mask_all = 0xFFFF,
+ .rdi_irq_mask_all = 0xFFFF,
+ .ppp_irq_mask_all = 0xFFFF,
+ .measure_en_hbi_vbi_cnt_mask = 0xC,
+ .format_measure_en_val = 1,
+};
+
+static struct cam_ife_csid_reg_offset cam_ife_csid_175_200_reg_offset = {
+ .cmn_reg = &cam_ife_csid_175_200_cmn_reg_offset,
+ .csi2_reg = &cam_ife_csid_175_200_csi2_reg_offset,
+ .ipp_reg = &cam_ife_csid_175_200_ipp_reg_offset,
+ .ppp_reg = &cam_ife_csid_175_200_ppp_reg_offset,
+ .rdi_reg = {
+ &cam_ife_csid_175_200_rdi_0_reg_offset,
+ &cam_ife_csid_175_200_rdi_1_reg_offset,
+ &cam_ife_csid_175_200_rdi_2_reg_offset,
+ NULL,
+ },
+ .tpg_reg = &cam_ife_csid_175_200_tpg_reg_offset,
+};
+
+#endif /*_CAM_IFE_CSID_175_200_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
index f894daa846b9..80701bf6f8d0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid17x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,21 +14,42 @@
#include <linux/module.h>
#include "cam_ife_csid_core.h"
#include "cam_ife_csid170.h"
+#include "cam_ife_csid175.h"
+#include "cam_ife_csid175_200.h"
#include "cam_ife_csid_dev.h"
#define CAM_CSID_DRV_NAME "csid_17x"
#define CAM_CSID_VERSION_V170 0x10070000
+#define CAM_CSID_VERSION_V175 0x10070050
static struct cam_ife_csid_hw_info cam_ife_csid170_hw_info = {
.csid_reg = &cam_ife_csid_170_reg_offset,
.hw_dts_version = CAM_CSID_VERSION_V170,
};
+static struct cam_ife_csid_hw_info cam_ife_csid175_hw_info = {
+ .csid_reg = &cam_ife_csid_175_reg_offset,
+ .hw_dts_version = CAM_CSID_VERSION_V175,
+};
+
+static struct cam_ife_csid_hw_info cam_ife_csid175_200_hw_info = {
+ .csid_reg = &cam_ife_csid_175_200_reg_offset,
+ .hw_dts_version = CAM_CSID_VERSION_V175,
+};
+
static const struct of_device_id cam_ife_csid17x_dt_match[] = {
{
.compatible = "qcom,csid170",
.data = &cam_ife_csid170_hw_info,
},
+ {
+ .compatible = "qcom,csid175",
+ .data = &cam_ife_csid175_hw_info,
+ },
+ {
+ .compatible = "qcom,csid175_200",
+ .data = &cam_ife_csid175_200_hw_info,
+ },
{}
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index f3a15558bb1b..2d6e23cb7961 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -67,6 +67,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported(
case CAM_FORMAT_DPCM_12_8_12:
case CAM_FORMAT_DPCM_14_8_14:
case CAM_FORMAT_DPCM_14_10_14:
+ case CAM_FORMAT_DPCM_12_10_12:
rc = 0;
break;
default:
@@ -206,6 +207,10 @@ static int cam_ife_csid_get_format_rdi(
*decode_fmt = 0xC;
*plain_fmt = 0x1;
break;
+ case CAM_FORMAT_DPCM_12_10_12:
+ *decode_fmt = 0xD;
+ *plain_fmt = 0x1;
+ break;
default:
rc = -EINVAL;
break;
@@ -280,6 +285,10 @@ static int cam_ife_csid_get_format_ipp_ppp(
*decode_fmt = 0xC;
*plain_fmt = 0x1;
break;
+ case CAM_FORMAT_DPCM_12_10_12:
+ *decode_fmt = 0xD;
+ *plain_fmt = 0x1;
+ break;
default:
CAM_ERR(CAM_ISP, "Unsupported format %d",
in_format);
@@ -309,6 +318,9 @@ static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
if (cid_data->vc == vc && cid_data->dt == dt) {
cid_data->cnt++;
*res = &csid_hw->cid_res[i];
+ CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
+ csid_hw->hw_intf->hw_idx,
+ csid_hw->cid_res[i].res_id);
return 0;
}
}
@@ -418,8 +430,23 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
cam_io_w_mb(0x2, soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[i]->csid_rdi_cfg0_addr);
- /* perform the top CSID HW and SW registers reset */
- cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb_sw_all,
+ /* perform the top CSID HW registers reset */
+ cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb,
+ soc_info->reg_map[0].mem_base +
+ csid_reg->cmn_reg->csid_rst_strobes_addr);
+
+ rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
+ csid_reg->cmn_reg->csid_top_irq_status_addr,
+ status, (status & 0x1) == 0x1,
+ CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d",
+ csid_hw->hw_intf->hw_idx, rc);
+ rc = -ETIMEDOUT;
+ }
+
+ /* perform the SW registers reset */
+ cam_io_w_mb(csid_reg->cmn_reg->csid_reg_rst_stb,
soc_info->reg_map[0].mem_base +
csid_reg->cmn_reg->csid_rst_strobes_addr);
@@ -433,6 +460,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
rc = -ETIMEDOUT;
}
+ usleep_range(3000, 3010);
val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
if (val != 0)
@@ -647,12 +675,12 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
goto end;
}
- CAM_DBG(CAM_ISP, "HW version: %d", camera_hw_version);
+ CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version);
switch (camera_hw_version) {
case CAM_CPAS_TITAN_NONE:
case CAM_CPAS_TITAN_MAX:
- CAM_ERR(CAM_ISP, "Invalid HW version: %d", camera_hw_version);
+ CAM_ERR(CAM_ISP, "Invalid HW version: %x", camera_hw_version);
break;
case CAM_CPAS_TITAN_170_V100:
case CAM_CPAS_TITAN_170_V110:
@@ -1031,7 +1059,7 @@ 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_ife_csid_get_vote_level(soc_info, csid_hw->clk_rate);
+ 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);
@@ -1093,6 +1121,7 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
int rc = -EINVAL;
struct cam_hw_soc_info *soc_info;
const struct cam_ife_csid_reg_offset *csid_reg;
+ unsigned long flags;
/* Check for refcount */
if (!csid_hw->hw_info->open_count) {
@@ -1127,6 +1156,9 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed",
csid_hw->hw_intf->hw_idx);
+ spin_lock_irqsave(&csid_hw->lock_state, flags);
+ csid_hw->device_enabled = 0;
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
csid_hw->error_irq_count = 0;
@@ -1327,10 +1359,12 @@ static int cam_ife_csid_enable_csi2(
return rc;
/* rx cfg0 */
+ val = 0;
val = (csid_hw->csi2_rx_cfg.lane_num - 1) |
(csid_hw->csi2_rx_cfg.lane_cfg << 4) |
(csid_hw->csi2_rx_cfg.lane_type << 24);
- val |= (csid_hw->csi2_rx_cfg.phy_sel & 0x3) << 20;
+ val |= (csid_hw->csi2_rx_cfg.phy_sel &
+ csid_reg->csi2_reg->csi2_rx_phy_num_mask) << 20;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
@@ -1753,6 +1787,9 @@ static int cam_ife_csid_enable_pxl_path(
/* Enable the required pxl path interrupts */
val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
+ if (pxl_reg->ccif_violation_en)
+ val |= CSID_PATH_ERROR_CCIF_VIOLATION;
+
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
val |= CSID_PATH_INFO_INPUT_SOF;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
@@ -1775,6 +1812,7 @@ static int cam_ife_csid_disable_pxl_path(
enum cam_ife_csid_halt_cmd stop_cmd)
{
int rc = 0;
+ uint32_t val = 0;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
struct cam_ife_csid_path_cfg *path_data;
@@ -1835,6 +1873,17 @@ static int cam_ife_csid_disable_pxl_path(
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
pxl_reg->csid_pxl_irq_mask_addr);
+ if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
+ path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) {
+ /* configure Halt */
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ val &= ~0x3;
+ val |= stop_cmd;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ pxl_reg->csid_pxl_ctrl_addr);
+ }
+
return rc;
}
@@ -2063,6 +2112,9 @@ static int cam_ife_csid_enable_rdi_path(
/* Enable the required RDI interrupts */
val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
+ if (csid_reg->rdi_reg[id]->ccif_violation_en)
+ val |= CSID_PATH_ERROR_CCIF_VIOLATION;
+
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_SOF_IRQ)
val |= CSID_PATH_INFO_INPUT_SOF;
if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ)
@@ -2083,7 +2135,7 @@ static int cam_ife_csid_disable_rdi_path(
enum cam_ife_csid_halt_cmd stop_cmd)
{
int rc = 0;
- uint32_t id;
+ uint32_t id, val = 0;
const struct cam_ife_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
@@ -2128,6 +2180,62 @@ static int cam_ife_csid_disable_rdi_path(
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
+ /* Halt the RDI path */
+ val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
+ val &= ~0x3;
+ val |= stop_cmd;
+ cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+ csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
+
+ return rc;
+}
+
+static int cam_ife_csid_poll_stop_status(
+ struct cam_ife_csid_hw *csid_hw,
+ uint32_t res_mask)
+{
+ int rc = 0;
+ uint32_t csid_status_addr = 0, val = 0, res_id = 0;
+ const struct cam_ife_csid_reg_offset *csid_reg;
+ struct cam_hw_soc_info *soc_info;
+
+ csid_reg = csid_hw->csid_info->csid_reg;
+ soc_info = &csid_hw->hw_info->soc_info;
+
+ for (; res_id < CAM_IFE_PIX_PATH_RES_MAX; res_id++, res_mask >>= 1) {
+ if ((res_mask & 0x1) == 0)
+ continue;
+ val = 0;
+
+ if (res_id == CAM_IFE_PIX_PATH_RES_IPP) {
+ csid_status_addr =
+ csid_reg->ipp_reg->csid_pxl_status_addr;
+ } else if (res_id == CAM_IFE_PIX_PATH_RES_PPP) {
+ csid_status_addr =
+ csid_reg->ppp_reg->csid_pxl_status_addr;
+ } else {
+ csid_status_addr =
+ csid_reg->rdi_reg[res_id]->csid_rdi_status_addr;
+ }
+
+ CAM_DBG(CAM_ISP, "start polling CSID:%d res_id:%d",
+ csid_hw->hw_intf->hw_idx, res_id);
+
+ rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
+ csid_status_addr, val, (val & 0x1) == 0x1,
+ CAM_IFE_CSID_TIMEOUT_SLEEP_US,
+ CAM_IFE_CSID_TIMEOUT_ALL_US);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "CSID:%d res:%d halt failed rc %d",
+ csid_hw->hw_intf->hw_idx, res_id, rc);
+ rc = -ETIMEDOUT;
+ break;
+ }
+ CAM_DBG(CAM_ISP, "End polling CSID:%d res_id:%d",
+ csid_hw->hw_intf->hw_idx, res_id);
+ }
+
return rc;
}
@@ -2176,10 +2284,10 @@ static int cam_ife_csid_get_hbi_vbi(
rdi_reg->csid_rdi_format_measure2_addr);
}
- CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u HBI: 0x%x", res->res_id,
- hbi);
- CAM_INFO_RATE_LIMIT(CAM_ISP, "Resource %u VBI: 0x%x", res->res_id,
- vbi);
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "Device %s index %u Resource %u HBI: 0x%x VBI: 0x%x",
+ soc_info->dev_name, soc_info->index,
+ res->res_id, hbi, vbi);
return 0;
}
@@ -2506,6 +2614,7 @@ static int cam_ife_csid_init_hw(void *hw_priv,
struct cam_hw_info *csid_hw_info;
struct cam_isp_resource_node *res;
const struct cam_ife_csid_reg_offset *csid_reg;
+ unsigned long flags;
if (!hw_priv || !init_args ||
(arg_size != sizeof(struct cam_isp_resource_node))) {
@@ -2573,6 +2682,10 @@ static int cam_ife_csid_init_hw(void *hw_priv,
if (rc)
cam_ife_csid_disable_hw(csid_hw);
+
+ spin_lock_irqsave(&csid_hw->lock_state, flags);
+ csid_hw->device_enabled = 1;
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
end:
mutex_unlock(&csid_hw->hw_info->hw_mutex);
return rc;
@@ -2705,6 +2818,7 @@ static int cam_ife_csid_stop(void *hw_priv,
struct cam_isp_resource_node *res;
struct cam_csid_hw_stop_args *csid_stop;
uint32_t i;
+ uint32_t res_mask = 0;
if (!hw_priv || !stop_args ||
(arg_size != sizeof(struct cam_csid_hw_stop_args))) {
@@ -2736,6 +2850,7 @@ static int cam_ife_csid_stop(void *hw_priv,
rc = cam_ife_csid_tpg_stop(csid_hw, res);
break;
case CAM_ISP_RESOURCE_PIX_PATH:
+ res_mask |= (1 << res->res_id);
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP ||
res->res_id == CAM_IFE_PIX_PATH_RES_PPP)
rc = cam_ife_csid_disable_pxl_path(csid_hw,
@@ -2753,6 +2868,9 @@ static int cam_ife_csid_stop(void *hw_priv,
}
}
+ if (res_mask)
+ rc = cam_ife_csid_poll_stop_status(csid_hw, res_mask);
+
for (i = 0; i < csid_stop->num_res; i++) {
res = csid_stop->node_res[i];
res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
@@ -2920,6 +3038,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
uint32_t val, irq_status_ppp = 0;
bool fatal_err_detected = false;
uint32_t sof_irq_debug_en = 0;
+ unsigned long flags;
csid_hw = (struct cam_ife_csid_hw *)data;
@@ -2985,65 +3104,74 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
complete(&csid_hw->csid_csi2_complete);
}
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
- csid_hw->hw_intf->hw_idx);
- fatal_err_detected = true;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_EOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
- csid_hw->error_irq_count++;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_SOT_RECEPTION",
- csid_hw->hw_intf->hw_idx);
- csid_hw->error_irq_count++;
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_STREAM_UNDERFLOW",
- csid_hw->hw_intf->hw_idx);
- }
- if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
- CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
- csid_hw->hw_intf->hw_idx);
+ spin_lock_irqsave(&csid_hw->lock_state, flags);
+ if (csid_hw->device_enabled == 1) {
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 0 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 1 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 2 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d lane 3 over flow",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d TG OVER FLOW",
+ csid_hw->hw_intf->hw_idx);
+ fatal_err_detected = true;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "CSID:%d CPHY_EOT_RECEPTION",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "CSID:%d CPHY_SOT_RECEPTION",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CPHY_PH_CRC",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_CRC) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_CRC",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_ECC) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d ERROR_ECC",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_MMAPPED_VC_DT) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d MMAPPED_VC_DT",
+ csid_hw->hw_intf->hw_idx);
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_STREAM_UNDERFLOW) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "CSID:%d ERROR_STREAM_UNDERFLOW",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
+ if (irq_status_rx & CSID_CSI2_RX_ERROR_UNBOUNDED_FRAME) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d UNBOUNDED_FRAME",
+ csid_hw->hw_intf->hw_idx);
+ csid_hw->error_irq_count++;
+ }
}
+ spin_unlock_irqrestore(&csid_hw->lock_state, flags);
if (csid_hw->error_irq_count >
CAM_IFE_CSID_MAX_IRQ_ERROR_COUNT) {
@@ -3170,6 +3298,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d IPP EOF received",
csid_hw->hw_intf->hw_idx);
+ if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "CSID:%d IPP CCIF violation",
+ csid_hw->hw_intf->hw_idx);
+
if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d IPP fifo over flow",
@@ -3203,6 +3336,11 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP, "CSID:%d PPP EOF received",
csid_hw->hw_intf->hw_idx);
+ if ((irq_status_ipp & CSID_PATH_ERROR_CCIF_VIOLATION))
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "CSID:%d PPP CCIF violation",
+ csid_hw->hw_intf->hw_idx);
+
if (irq_status_ppp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d PPP fifo over flow",
@@ -3234,6 +3372,10 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
CAM_INFO_RATE_LIMIT(CAM_ISP,
"CSID RDI:%d EOF received", i);
+ if ((irq_status_rdi[i] & CSID_PATH_ERROR_CCIF_VIOLATION))
+ CAM_INFO_RATE_LIMIT(CAM_ISP,
+ "CSIDi RDI :%d CCIF violation", i);
+
if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
CAM_ERR_RATE_LIMIT(CAM_ISP,
"CSID:%d RDI fifo over flow",
@@ -3280,9 +3422,11 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
ife_csid_hw->hw_intf->hw_type, csid_idx);
+ ife_csid_hw->device_enabled = 0;
ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
mutex_init(&ife_csid_hw->hw_info->hw_mutex);
spin_lock_init(&ife_csid_hw->hw_info->hw_lock);
+ spin_lock_init(&ife_csid_hw->lock_state);
init_completion(&ife_csid_hw->hw_info->hw_complete);
init_completion(&ife_csid_hw->csid_top_complete);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index 43fd9b03132e..3a093d205f59 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -64,6 +64,7 @@
#define CSID_PATH_INFO_INPUT_SOF BIT(12)
#define CSID_PATH_ERROR_PIX_COUNT BIT(13)
#define CSID_PATH_ERROR_LINE_COUNT BIT(14)
+#define CSID_PATH_ERROR_CCIF_VIOLATION BIT(15)
/*
* Debug values enable the corresponding interrupts and debug logs provide
@@ -138,6 +139,8 @@ struct cam_ife_csid_pxl_reg_offset {
/* configuration */
uint32_t pix_store_en_shift_val;
uint32_t early_eof_en_shift_val;
+ uint32_t quad_cfa_bin_en_shift_val;
+ uint32_t ccif_violation_en;
};
struct cam_ife_csid_rdi_reg_offset {
@@ -182,6 +185,10 @@ struct cam_ife_csid_rdi_reg_offset {
uint32_t csid_rdi_timestamp_prev1_eof_addr;
uint32_t csid_rdi_byte_cntr_ping_addr;
uint32_t csid_rdi_byte_cntr_pong_addr;
+
+ /* configuration */
+ uint32_t packing_format;
+ uint32_t ccif_violation_en;
};
struct cam_ife_csid_csi2_rx_reg_offset {
@@ -194,7 +201,7 @@ struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csid_csi2_rx_capture_ctrl_addr;
uint32_t csid_csi2_rx_rst_strobes_addr;
uint32_t csid_csi2_rx_de_scramble_cfg0_addr;
- uint32_t csid_csi2_rx_de_scramble_cfg1_addr; /* */
+ uint32_t csid_csi2_rx_de_scramble_cfg1_addr;
uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr;
uint32_t csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr;
uint32_t csid_csi2_rx_captured_short_pkt_0_addr;
@@ -210,6 +217,14 @@ struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csid_csi2_rx_total_pkts_rcvd_addr;
uint32_t csid_csi2_rx_stats_ecc_addr;
uint32_t csid_csi2_rx_total_crc_err_addr;
+ uint32_t csid_csi2_rx_de_scramble_type3_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type3_cfg1_addr;
+ uint32_t csid_csi2_rx_de_scramble_type2_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type2_cfg1_addr;
+ uint32_t csid_csi2_rx_de_scramble_type1_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type1_cfg1_addr;
+ uint32_t csid_csi2_rx_de_scramble_type0_cfg0_addr;
+ uint32_t csid_csi2_rx_de_scramble_type0_cfg1_addr;
/*configurations */
uint32_t csi2_rst_srb_all;
@@ -225,6 +240,7 @@ struct cam_ife_csid_csi2_rx_reg_offset {
uint32_t csi2_capture_short_pkt_vc_shift;
uint32_t csi2_capture_cphy_pkt_dt_shift;
uint32_t csi2_capture_cphy_pkt_vc_shift;
+ uint32_t csi2_rx_phy_num_mask;
};
struct cam_ife_csid_csi2_tpg_reg_offset {
@@ -274,6 +290,7 @@ struct cam_ife_csid_common_reg_offset {
uint32_t num_rdis;
uint32_t num_pix;
uint32_t num_ppp;
+ uint32_t csid_reg_rst_stb;
uint32_t csid_rst_stb;
uint32_t csid_rst_stb_sw_all;
uint32_t path_rst_stb_all;
@@ -477,6 +494,8 @@ struct cam_ife_csid_hw {
bool sof_irq_triggered;
uint32_t irq_debug_cnt;
uint32_t error_irq_count;
+ uint32_t device_enabled;
+ spinlock_t lock_state;
};
int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
deleted file mode 100644
index 6c39bd84e47f..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include "cam_ife_csid_lite170.h"
-#include "cam_ife_csid_core.h"
-#include "cam_ife_csid_dev.h"
-
-#define CAM_CSID_LITE_DRV_NAME "csid_lite_170"
-#define CAM_CSID_LITE_VERSION_V170 0x10070000
-
-static struct cam_ife_csid_hw_info cam_ife_csid_lite170_hw_info = {
- .csid_reg = &cam_ife_csid_lite_170_reg_offset,
- .hw_dts_version = CAM_CSID_LITE_VERSION_V170,
-};
-
-static const struct of_device_id cam_ife_csid_lite170_dt_match[] = {
- {
- .compatible = "qcom,csid-lite170",
- .data = &cam_ife_csid_lite170_hw_info,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, cam_ife_csid_lite170_dt_match);
-
-static struct platform_driver cam_ife_csid_lite170_driver = {
- .probe = cam_ife_csid_probe,
- .remove = cam_ife_csid_remove,
- .driver = {
- .name = CAM_CSID_LITE_DRV_NAME,
- .owner = THIS_MODULE,
- .of_match_table = cam_ife_csid_lite170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_ife_csid_lite170_init_module(void)
-{
- return platform_driver_register(&cam_ife_csid_lite170_driver);
-}
-
-static void __exit cam_ife_csid_lite170_exit_module(void)
-{
- platform_driver_unregister(&cam_ife_csid_lite170_driver);
-}
-
-module_init(cam_ife_csid_lite170_init_module);
-module_exit(cam_ife_csid_lite170_exit_module);
-MODULE_DESCRIPTION("CAM IFE_CSID_LITE170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c
index b05a4b533c23..11c71145ef94 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,10 @@ static const struct of_device_id cam_ife_csid_lite_dt_match[] = {
.compatible = "qcom,csid-lite170",
.data = &cam_ife_csid_lite_hw_info,
},
+ {
+ .compatible = "qcom,csid-lite175",
+ .data = &cam_ife_csid_lite_hw_info,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cam_ife_csid_lite_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
index d4e05115455a..e39666fe12b7 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite17x.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -232,6 +232,7 @@ static const struct cam_ife_csid_csi2_rx_reg_offset
.csi2_capture_short_pkt_vc_shift = 15,
.csi2_capture_cphy_pkt_dt_shift = 20,
.csi2_capture_cphy_pkt_vc_shift = 26,
+ .csi2_rx_phy_num_mask = 0x3,
};
@@ -286,6 +287,7 @@ static const struct cam_ife_csid_common_reg_offset
.version_incr = 0,
.num_rdis = 4,
.num_pix = 0,
+ .csid_reg_rst_stb = 1,
.csid_rst_stb = 0x1e,
.csid_rst_stb_sw_all = 0x1f,
.path_rst_stb_all = 0x7f,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
index 890dad3b66b2..5e02609088c4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -117,7 +117,7 @@ int cam_ife_csid_deinit_soc_resources(
}
int cam_ife_csid_enable_soc_resources(
- struct cam_hw_soc_info *soc_info, uint32_t clk_lvl)
+ struct cam_hw_soc_info *soc_info, enum cam_vote_level clk_level)
{
int rc = 0;
struct cam_csid_soc_private *soc_private;
@@ -142,7 +142,7 @@ int cam_ife_csid_enable_soc_resources(
}
rc = cam_soc_util_enable_platform_resource(soc_info, true,
- clk_lvl, true);
+ clk_level, true);
if (rc) {
CAM_ERR(CAM_ISP, "enable platform failed");
goto stop_cpas;
@@ -235,24 +235,3 @@ int cam_ife_csid_disable_ife_force_clock_on(struct cam_hw_soc_info *soc_info,
return rc;
}
-
-uint32_t cam_ife_csid_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_rate[i][soc_info->num_clk - 1] >=
- clock_rate) {
- CAM_DBG(CAM_ISP,
- "Clock rate %lld, selected clock level %d",
- clock_rate, i);
- return i;
- }
- }
-
- return CAM_TURBO_VOTE;
-}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 940d338a9572..61542566a924 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -80,14 +80,17 @@ enum cam_isp_resource_type {
CAM_ISP_RESOURCE_PIX_PATH,
CAM_ISP_RESOURCE_VFE_IN,
CAM_ISP_RESOURCE_VFE_OUT,
+ CAM_ISP_RESOURCE_VFE_BUS_RD,
CAM_ISP_RESOURCE_MAX,
};
enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_GET_CHANGE_BASE,
CAM_ISP_HW_CMD_GET_BUF_UPDATE,
+ CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM,
CAM_ISP_HW_CMD_GET_REG_UPDATE,
CAM_ISP_HW_CMD_GET_HFR_UPDATE,
+ CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM,
CAM_ISP_HW_CMD_GET_SECURE_MODE,
CAM_ISP_HW_CMD_STRIPE_UPDATE,
CAM_ISP_HW_CMD_CLOCK_UPDATE,
@@ -95,10 +98,12 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_BW_CONTROL,
CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ,
CAM_ISP_HW_CMD_GET_REG_DUMP,
+ CAM_ISP_HW_CMD_UBWC_UPDATE,
CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
- CAM_ISP_HW_CMD_UBWC_UPDATE,
CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
+ CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
+ CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
CAM_ISP_HW_CMD_MAX,
};
@@ -186,6 +191,20 @@ struct cam_isp_hw_get_wm_update {
};
/*
+ * struct cam_isp_hw_rup_data:
+ *
+ * @Brief: RUP for required resources.
+ *
+ * @is_fe_enable if fetch engine enabled
+ * @res_bitmap resource bitmap for set resources
+ *
+ */
+struct cam_isp_hw_rup_data {
+ bool is_fe_enable;
+ unsigned long res_bitmap;
+};
+
+/*
* struct cam_isp_hw_get_cmd_update:
*
* @Brief: Get cmd buffer update for different CMD types
@@ -202,10 +221,13 @@ struct cam_isp_hw_get_cmd_update {
union {
void *data;
struct cam_isp_hw_get_wm_update *wm_update;
+ struct cam_isp_hw_get_wm_update *rm_update;
struct cam_isp_port_hfr_config *hfr_update;
struct cam_isp_clock_config *clock_update;
struct cam_isp_bw_config *bw_update;
struct cam_ubwc_plane_cfg_v1 *ubwc_update;
+ struct cam_fe_config *fe_update;
+ struct cam_isp_hw_rup_data *rup_data;
};
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index b957d6913f77..f60bf6e4b3d4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -28,7 +28,7 @@
enum cam_isp_hw_vfe_in_mux {
CAM_ISP_HW_VFE_IN_CAMIF = 0,
CAM_ISP_HW_VFE_IN_TESTGEN = 1,
- CAM_ISP_HW_VFE_IN_BUS_RD = 2,
+ CAM_ISP_HW_VFE_IN_RD = 2,
CAM_ISP_HW_VFE_IN_RDI0 = 3,
CAM_ISP_HW_VFE_IN_RDI1 = 4,
CAM_ISP_HW_VFE_IN_RDI2 = 5,
@@ -153,6 +153,7 @@ struct cam_vfe_hw_vfe_in_acquire_args {
* used to schedule bottom of IRQ events associated
* with this resource.
* @vfe_out: Acquire args for VFE_OUT
+ * @vfe_bus_rd Acquire args for VFE_BUS_READ
* @vfe_in: Acquire args for VFE_IN
*/
struct cam_vfe_acquire_args {
@@ -160,6 +161,7 @@ struct cam_vfe_acquire_args {
void *tasklet;
union {
struct cam_vfe_hw_vfe_out_acquire_args vfe_out;
+ struct cam_vfe_hw_vfe_out_acquire_args vfe_bus_rd;
struct cam_vfe_hw_vfe_in_acquire_args vfe_in;
};
};
@@ -178,7 +180,7 @@ struct cam_vfe_clock_update_args {
/*
* struct cam_vfe_bw_update_args:
*
- * @node_res: Resource to get the time stamp
+ * @node_res: Resource to get the BW
* @camnoc_bw_bytes: Bandwidth vote request for CAMNOC
* @external_bw_bytes: Bandwidth vote request from CAMNOC
* out to the rest of the path-to-DDR
@@ -189,6 +191,18 @@ struct cam_vfe_bw_update_args {
uint64_t external_bw_bytes;
};
+/*
+ * struct cam_vfe_fe_update_args:
+ *
+ * @node_res: Resource to get fetch configuration
+ * @fe_config: fetch engine configuration
+ *
+ */
+struct cam_vfe_fe_update_args {
+ struct cam_isp_resource_node *node_res;
+ struct cam_fe_config fe_config;
+};
+
enum cam_vfe_bw_control_action {
CAM_VFE_BW_CONTROL_EXCLUDE = 0,
CAM_VFE_BW_CONTROL_INCLUDE = 1
@@ -218,6 +232,7 @@ struct cam_vfe_bw_control_args {
* @irq_reg_val: IRQ and Error register values, read when IRQ was
* handled
* @error_type: Identify different errors
+ * @enable_reg_dump: enable register dump on error
* @ts: Timestamp
*/
struct cam_vfe_top_irq_evt_payload {
@@ -227,6 +242,7 @@ struct cam_vfe_top_irq_evt_payload {
uint32_t evt_id;
uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX];
uint32_t error_type;
+ bool enable_reg_dump;
struct cam_isp_timestamp ts;
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 5e6bb2012fff..2bd6db9954f1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -36,6 +36,11 @@ static uint32_t camif_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
0x00000000,
};
+static uint32_t camif_fe_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
+ 0x10000056,
+ 0x00000000,
+};
+
static uint32_t camif_irq_err_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
0x0003FC00,
0xEFFF7EBC,
@@ -286,6 +291,16 @@ int cam_vfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size)
goto deinint_vfe_res;
}
+ if (core_info->vfe_rd_bus) {
+ rc = core_info->vfe_rd_bus->hw_ops.init(
+ core_info->vfe_rd_bus->bus_priv,
+ NULL, 0);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Bus RD HW init Failed rc=%d", rc);
+ goto deinint_vfe_res;
+ }
+ }
+
vfe_hw->hw_state = CAM_HW_STATE_POWER_UP;
return rc;
@@ -339,6 +354,14 @@ int cam_vfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size)
if (rc)
CAM_ERR(CAM_ISP, "Bus HW deinit Failed rc=%d", rc);
+ if (core_info->vfe_rd_bus) {
+ rc = core_info->vfe_rd_bus->hw_ops.deinit(
+ core_info->vfe_rd_bus->bus_priv,
+ NULL, 0);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Bus HW deinit Failed rc=%d", rc);
+ }
+
isp_res = (struct cam_isp_resource_node *)deinit_hw_args;
if (isp_res && isp_res->deinit) {
rc = isp_res->deinit(isp_res, NULL, 0);
@@ -485,18 +508,25 @@ int cam_vfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size)
core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
acquire = (struct cam_vfe_acquire_args *)reserve_args;
+ CAM_DBG(CAM_ISP, "acq res type: %d", acquire->rsrc_type);
mutex_lock(&vfe_hw->hw_mutex);
- if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_IN)
+ if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_IN) {
rc = core_info->vfe_top->hw_ops.reserve(
core_info->vfe_top->top_priv,
acquire,
sizeof(*acquire));
- else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT)
+ } else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_OUT) {
rc = core_info->vfe_bus->hw_ops.reserve(
core_info->vfe_bus->bus_priv, acquire,
sizeof(*acquire));
- else
+ } else if (acquire->rsrc_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.reserve(
+ core_info->vfe_rd_bus->bus_priv, acquire,
+ sizeof(*acquire));
+ } else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", acquire->rsrc_type);
+ }
mutex_unlock(&vfe_hw->hw_mutex);
@@ -529,8 +559,14 @@ int cam_vfe_release(void *hw_priv, void *release_args, uint32_t arg_size)
rc = core_info->vfe_bus->hw_ops.release(
core_info->vfe_bus->bus_priv, isp_res,
sizeof(*isp_res));
- else
+ else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.release(
+ core_info->vfe_rd_bus->bus_priv, isp_res,
+ sizeof(*isp_res));
+ } else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
+ }
mutex_unlock(&vfe_hw->hw_mutex);
@@ -570,6 +606,19 @@ int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size)
&tasklet_bh_api);
if (isp_res->irq_handle < 1)
rc = -ENOMEM;
+ } else if (isp_res->res_id == CAM_ISP_HW_VFE_IN_RD) {
+ isp_res->irq_handle =
+ cam_irq_controller_subscribe_irq(
+ core_info->vfe_irq_controller,
+ CAM_IRQ_PRIORITY_1,
+ camif_fe_irq_reg_mask,
+ &core_info->irq_payload,
+ cam_vfe_irq_top_half,
+ cam_ife_mgr_do_tasklet,
+ isp_res->tasklet_info,
+ &tasklet_bh_api);
+ if (isp_res->irq_handle < 1)
+ rc = -ENOMEM;
} else if (isp_res->rdi_only_ctx) {
isp_res->irq_handle =
cam_irq_controller_subscribe_irq(
@@ -598,6 +647,10 @@ int cam_vfe_start(void *hw_priv, void *start_args, uint32_t arg_size)
}
} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
rc = core_info->vfe_bus->hw_ops.start(isp_res, NULL, 0);
+ } else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.start(isp_res,
+ NULL, 0);
} else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
rc = -EFAULT;
@@ -653,6 +706,10 @@ int cam_vfe_stop(void *hw_priv, void *stop_args, uint32_t arg_size)
sizeof(struct cam_isp_resource_node));
} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
+ } else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_BUS_RD) {
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.stop(isp_res,
+ NULL, 0);
} else {
CAM_ERR(CAM_ISP, "Invalid res type:%d", isp_res->res_type);
}
@@ -716,7 +773,26 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
arg_size);
break;
+ case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
+ case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+ if (core_info->vfe_rd_bus)
+ rc = core_info->vfe_rd_bus->hw_ops.process_cmd(
+ core_info->vfe_rd_bus->bus_priv, cmd_type,
+ cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+ rc = core_info->vfe_top->hw_ops.process_cmd(
+ core_info->vfe_top->top_priv, cmd_type, cmd_args,
+ arg_size);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+ if (core_info->vfe_rd_bus) {
+ rc = core_info->vfe_rd_bus->hw_ops.process_cmd(
+ core_info->vfe_rd_bus->bus_priv, cmd_type,
+ cmd_args, arg_size);
+ }
+ break;
default:
CAM_ERR(CAM_ISP, "Invalid cmd type:%d", cmd_type);
rc = -EINVAL;
@@ -766,7 +842,8 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
goto deinit_controller;
}
- rc = cam_vfe_bus_init(vfe_hw_info->bus_version, soc_info, hw_intf,
+ rc = cam_vfe_bus_init(vfe_hw_info->bus_version, BUS_TYPE_WR,
+ soc_info, hw_intf,
vfe_hw_info->bus_hw_info, core_info->vfe_irq_controller,
&core_info->vfe_bus);
if (rc) {
@@ -774,6 +851,19 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
goto deinit_top;
}
+ /* Read Bus is not valid for vfe-lite */
+ if ((hw_intf->hw_idx == 0) || (hw_intf->hw_idx == 1)) {
+ rc = cam_vfe_bus_init(vfe_hw_info->bus_rd_version, BUS_TYPE_RD,
+ soc_info, hw_intf, vfe_hw_info->bus_rd_hw_info,
+ core_info->vfe_irq_controller, &core_info->vfe_rd_bus);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Error! RD cam_vfe_bus_init failed");
+ rc = 0;
+ }
+ CAM_DBG(CAM_ISP, "vfe_bus_rd %pK hw_idx %d",
+ core_info->vfe_rd_bus, hw_intf->hw_idx);
+ }
+
INIT_LIST_HEAD(&core_info->free_payload_list);
for (i = 0; i < CAM_VFE_EVT_MAX; i++) {
INIT_LIST_HEAD(&core_info->evt_payload[i].list);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
index 9cec56a15fec..dd078f2d6ce3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,9 @@ struct cam_vfe_hw_info {
uint32_t bus_version;
void *bus_hw_info;
+ uint32_t bus_rd_version;
+ void *bus_rd_hw_info;
+
uint32_t top_version;
void *top_hw_info;
uint32_t camif_version;
@@ -53,6 +56,7 @@ struct cam_vfe_hw_core_info {
void *vfe_irq_controller;
struct cam_vfe_top *vfe_top;
struct cam_vfe_bus *vfe_bus;
+ struct cam_vfe_bus *vfe_rd_bus;
void *tasklet_info;
struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_EVT_MAX];
struct list_head free_payload_list;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
index 12b7a03c6276..b57762644082 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,8 @@ static bool cam_vfe_cpas_cb(uint32_t client_handle, void *userdata,
switch (irq_data->irq_type) {
case CAM_CAMNOC_IRQ_IFE02_UBWC_ENCODE_ERROR:
case CAM_CAMNOC_IRQ_IFE13_UBWC_ENCODE_ERROR:
+ case CAM_CAMNOC_IRQ_IFE0_UBWC_ENCODE_ERROR:
+ case CAM_CAMNOC_IRQ_IFE1_WRITE_UBWC_ENCODE_ERROR:
CAM_ERR_RATE_LIMIT(CAM_ISP,
"IFE UBWC Encode error type=%d status=%x",
irq_data->irq_type,
@@ -104,7 +106,7 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
CAM_VFE_DSP_CLK_NAME, &soc_private->dsp_clk,
&soc_private->dsp_clk_index, &soc_private->dsp_clk_rate);
if (rc)
- CAM_WARN(CAM_ISP, "option clk get failed");
+ CAM_WARN(CAM_ISP, "Option clk get failed with rc %d", rc);
rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler,
irq_data);
@@ -115,20 +117,56 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
}
memset(&cpas_register_param, 0, sizeof(cpas_register_param));
- strlcpy(cpas_register_param.identifier, "ife",
- CAM_HW_IDENTIFIER_LENGTH);
+
cpas_register_param.cell_index = soc_info->index;
cpas_register_param.dev = soc_info->dev;
cpas_register_param.cam_cpas_client_cb = cam_vfe_cpas_cb;
cpas_register_param.userdata = soc_info;
- rc = cam_cpas_register_client(&cpas_register_param);
+
+ rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version);
if (rc) {
- CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
- goto release_soc;
- } else {
- soc_private->cpas_handle = cpas_register_param.client_handle;
+ CAM_ERR(CAM_ISP, "Error! Invalid cpas version rc=%d", rc);
+ goto free_soc_private;
}
+ switch (soc_private->cpas_version) {
+ case CAM_CPAS_TITAN_175_V120:
+ strlcpy(cpas_register_param.identifier, "iferdi",
+ CAM_HW_IDENTIFIER_LENGTH);
+ rc = cam_cpas_register_client(&cpas_register_param);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "rdi CPAS registration failed rc=%d",
+ rc);
+ goto release_soc;
+ } else {
+ soc_private->cpas_handle[0] =
+ cpas_register_param.client_handle;
+ }
+
+ strlcpy(cpas_register_param.identifier, "ifenrdi",
+ CAM_HW_IDENTIFIER_LENGTH);
+ rc = cam_cpas_register_client(&cpas_register_param);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "nrdi CPAS registration failed rc=%d",
+ rc);
+ goto release_soc;
+ } else {
+ soc_private->cpas_handle[1] =
+ cpas_register_param.client_handle;
+ }
+ break;
+ default:
+ strlcpy(cpas_register_param.identifier, "ife",
+ CAM_HW_IDENTIFIER_LENGTH);
+ rc = cam_cpas_register_client(&cpas_register_param);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "CPAS registration failed rc=%d", rc);
+ goto release_soc;
+ } else {
+ soc_private->cpas_handle[0] =
+ cpas_register_param.client_handle;
+ }
+ }
return rc;
release_soc:
@@ -154,10 +192,15 @@ int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
CAM_ERR(CAM_ISP, "Error! soc_private NULL");
return -ENODEV;
}
-
- rc = cam_cpas_unregister_client(soc_private->cpas_handle);
+ rc = cam_cpas_unregister_client(soc_private->cpas_handle[0]);
if (rc)
- CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
+ CAM_ERR(CAM_ISP, "CPAS0 unregistration failed rc=%d", rc);
+
+ if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ rc = cam_cpas_unregister_client(soc_private->cpas_handle[1]);
+ if (rc)
+ CAM_ERR(CAM_ISP, "CPAS1 unregistration failed rc=%d",
+ rc);
rc = cam_vfe_release_platform_resource(soc_info);
if (rc < 0)
@@ -194,13 +237,22 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
axi_vote.compressed_bw = 10640000000L;
axi_vote.uncompressed_bw = 10640000000L;
- rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
+ rc = cam_cpas_start(soc_private->cpas_handle[0], &ahb_vote, &axi_vote);
if (rc) {
- CAM_ERR(CAM_ISP, "Error! CPAS start failed rc=%d", rc);
+ CAM_ERR(CAM_ISP, "Error! CPAS0 start failed rc=%d", rc);
rc = -EFAULT;
goto end;
}
+ if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ rc = cam_cpas_start(soc_private->cpas_handle[1], &ahb_vote,
+ &axi_vote);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Error! CPAS1 start failed rc=%d", rc);
+ rc = -EFAULT;
+ goto end;
+ }
+
rc = cam_soc_util_enable_platform_resource(soc_info, true,
CAM_TURBO_VOTE, true);
if (rc) {
@@ -211,7 +263,9 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
return rc;
stop_cpas:
- cam_cpas_stop(soc_private->cpas_handle);
+ cam_cpas_stop(soc_private->cpas_handle[0]);
+ if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ cam_cpas_stop(soc_private->cpas_handle[1]);
end:
return rc;
}
@@ -283,11 +337,18 @@ int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)
return rc;
}
- rc = cam_cpas_stop(soc_private->cpas_handle);
+ rc = cam_cpas_stop(soc_private->cpas_handle[0]);
if (rc) {
CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
return rc;
}
+ if (!rc && soc_private->cpas_version == CAM_CPAS_TITAN_175_V120)
+ rc = cam_cpas_stop(soc_private->cpas_handle[1]);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Error! CPAS stop failed rc=%d", rc);
+ return rc;
+ }
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
index 3f862e9249f8..780bd34ab968 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,12 @@
#define CAM_VFE_DSP_CLK_NAME "ife_dsp_clk"
+enum cam_cpas_handle_id {
+ CAM_CPAS_HANDLE_CAMIF,
+ CAM_CPAS_HANDLE_RAW,
+ CAM_CPAS_HANDLE_MAX,
+};
+
/*
* struct cam_vfe_soc_private:
*
@@ -26,9 +32,11 @@
* @cpas_handle: Handle returned on registering with CPAS driver.
* This handle is used for all further interface
* with CPAS.
+ * @cpas_version: Has cpas version read from Hardware
*/
struct cam_vfe_soc_private {
- uint32_t cpas_handle;
+ uint32_t cpas_handle[CAM_CPAS_HANDLE_MAX];
+ uint32_t cpas_version;
struct clk *dsp_clk;
int32_t dsp_clk_index;
int32_t dsp_clk_rate;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile
deleted file mode 100644
index deeae35cef79..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_utils
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_core
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/irq_controller
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus
-ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw
-
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe170.o cam_vfe_lite170.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
deleted file mode 100644
index d002f84015de..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include "cam_vfe170.h"
-#include "cam_vfe_hw_intf.h"
-#include "cam_vfe_core.h"
-#include "cam_vfe_dev.h"
-
-static const struct of_device_id cam_vfe170_dt_match[] = {
- {
- .compatible = "qcom,vfe170",
- .data = &cam_vfe170_hw_info,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, cam_vfe170_dt_match);
-
-static struct platform_driver cam_vfe170_driver = {
- .probe = cam_vfe_probe,
- .remove = cam_vfe_remove,
- .driver = {
- .name = "cam_vfe170",
- .owner = THIS_MODULE,
- .of_match_table = cam_vfe170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_vfe170_init_module(void)
-{
- return platform_driver_register(&cam_vfe170_driver);
-}
-
-static void __exit cam_vfe170_exit_module(void)
-{
- platform_driver_unregister(&cam_vfe170_driver);
-}
-
-module_init(cam_vfe170_init_module);
-module_exit(cam_vfe170_exit_module);
-MODULE_DESCRIPTION("CAM VFE170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c
deleted file mode 100644
index ab692cf095e4..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include "cam_vfe_lite170.h"
-#include "cam_vfe_hw_intf.h"
-#include "cam_vfe_core.h"
-#include "cam_vfe_dev.h"
-
-static const struct of_device_id cam_vfe170_dt_match[] = {
- {
- .compatible = "qcom,vfe-lite170",
- .data = &cam_vfe_lite170_hw_info,
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, cam_vfe170_dt_match);
-
-static struct platform_driver cam_vfe170_driver = {
- .probe = cam_vfe_probe,
- .remove = cam_vfe_remove,
- .driver = {
- .name = "cam_vfe_lite170",
- .owner = THIS_MODULE,
- .of_match_table = cam_vfe170_dt_match,
- .suppress_bind_attrs = true,
- },
-};
-
-static int __init cam_vfe170_init_module(void)
-{
- return platform_driver_register(&cam_vfe170_driver);
-}
-
-static void __exit cam_vfe170_exit_module(void)
-{
- platform_driver_unregister(&cam_vfe170_driver);
-}
-
-module_init(cam_vfe170_init_module);
-module_exit(cam_vfe170_exit_module);
-MODULE_DESCRIPTION("CAM VFE170 driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h
deleted file mode 100644
index 4b2e0963a599..000000000000
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _CAM_VFE_LITE170_H_
-#define _CAM_VFE_LITE170_H_
-
-#include "cam_vfe_bus_ver2.h"
-#include "cam_irq_controller.h"
-#include "cam_vfe_top_ver2.h"
-#include "cam_vfe_core.h"
-
-static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
- {
- .mask_reg_offset = 0x0000005C,
- .clear_reg_offset = 0x00000064,
- .status_reg_offset = 0x0000006C,
- },
- {
- .mask_reg_offset = 0x00000060,
- .clear_reg_offset = 0x00000068,
- .status_reg_offset = 0x00000070,
- },
-};
-
-static struct cam_irq_controller_reg_info vfe170_top_irq_reg_info = {
- .num_registers = 2,
- .irq_reg_set = vfe170_top_irq_reg_set,
- .global_clear_offset = 0x00000058,
- .global_clear_bitmask = 0x00000001,
-};
-
-static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
- .hw_version = 0x00000000,
- .hw_capability = 0x00000004,
- .lens_feature = 0x00000008,
- .stats_feature = 0x0000000C,
- .color_feature = 0x00000010,
- .zoom_feature = 0x00000014,
- .global_reset_cmd = 0x00000018,
- .module_ctrl = {
- NULL,
- NULL,
- NULL,
- NULL,
- },
- .bus_cgc_ovd = 0x0000003C,
- .core_cfg = 0x00000000,
- .three_D_cfg = 0x00000000,
- .violation_status = 0x0000007C,
- .reg_update_cmd = 0x000004AC,
-};
-
-static struct cam_vfe_rdi_ver2_reg vfe170_rdi_reg = {
- .reg_update_cmd = 0x000004AC,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_0_data = {
- .reg_update_cmd_data = 0x2,
- .sof_irq_mask = 0x8000000,
- .reg_update_irq_mask = 0x20,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_1_data = {
- .reg_update_cmd_data = 0x4,
- .sof_irq_mask = 0x10000000,
- .reg_update_irq_mask = 0x40,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_2_data = {
- .reg_update_cmd_data = 0x8,
- .sof_irq_mask = 0x20000000,
- .reg_update_irq_mask = 0x80,
-};
-
-static struct cam_vfe_rdi_reg_data vfe170_rdi_3_data = {
- .reg_update_cmd_data = 0x10,
- .sof_irq_mask = 0x40000000,
- .reg_update_irq_mask = 0x100,
-};
-
-static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .camif_hw_info = {
- .common_reg = NULL,
- .camif_reg = NULL,
- .reg_data = NULL,
- },
- .rdi_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .rdi_reg = &vfe170_rdi_reg,
- .reg_data = {
- &vfe170_rdi_0_data,
- &vfe170_rdi_1_data,
- &vfe170_rdi_2_data,
- &vfe170_rdi_3_data,
- },
- },
- .mux_type = {
- CAM_VFE_RDI_VER_1_0,
- CAM_VFE_RDI_VER_1_0,
- CAM_VFE_RDI_VER_1_0,
- CAM_VFE_RDI_VER_1_0,
- },
-};
-
-static struct cam_irq_register_set vfe170_bus_irq_reg[3] = {
- {
- .mask_reg_offset = 0x00002044,
- .clear_reg_offset = 0x00002050,
- .status_reg_offset = 0x0000205C,
- },
- {
- .mask_reg_offset = 0x00002048,
- .clear_reg_offset = 0x00002054,
- .status_reg_offset = 0x00002060,
- },
- {
- .mask_reg_offset = 0x0000204C,
- .clear_reg_offset = 0x00002058,
- .status_reg_offset = 0x00002064,
- },
-};
-
-static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
- .common_reg = {
- .hw_version = 0x00002000,
- .hw_capability = 0x00002004,
- .sw_reset = 0x00002008,
- .cgc_ovd = 0x0000200C,
- .pwr_iso_cfg = 0x000020CC,
- .dual_master_comp_cfg = 0x00002028,
- .irq_reg_info = {
- .num_registers = 3,
- .irq_reg_set = vfe170_bus_irq_reg,
- .global_clear_offset = 0x00002068,
- .global_clear_bitmask = 0x00000001,
- },
- .comp_error_status = 0x0000206C,
- .comp_ovrwr_status = 0x00002070,
- .dual_comp_error_status = 0x00002074,
- .dual_comp_ovrwr_status = 0x00002078,
- .addr_sync_cfg = 0x0000207C,
- .addr_sync_frame_hdr = 0x00002080,
- .addr_sync_no_sync = 0x00002084,
- },
- .num_client = 4,
- .bus_client_reg = {
- /* BUS Client 0 */
- {
- .status0 = 0x00002200,
- .status1 = 0x00002204,
- .cfg = 0x00002208,
- .header_addr = 0x0000220C,
- .header_cfg = 0x00002210,
- .image_addr = 0x00002214,
- .image_addr_offset = 0x00002218,
- .buffer_width_cfg = 0x0000221C,
- .buffer_height_cfg = 0x00002220,
- .packer_cfg = 0x00002224,
- .stride = 0x00002228,
- .irq_subsample_period = 0x00002248,
- .irq_subsample_pattern = 0x0000224C,
- .framedrop_period = 0x00002250,
- .framedrop_pattern = 0x00002254,
- .frame_inc = 0x00002258,
- .burst_limit = 0x0000225C,
- .ubwc_regs = NULL,
- },
- /* BUS Client 1 */
- {
- .status0 = 0x00002300,
- .status1 = 0x00002304,
- .cfg = 0x00002308,
- .header_addr = 0x0000230C,
- .header_cfg = 0x00002310,
- .image_addr = 0x00002314,
- .image_addr_offset = 0x00002318,
- .buffer_width_cfg = 0x0000231C,
- .buffer_height_cfg = 0x00002320,
- .packer_cfg = 0x00002324,
- .stride = 0x00002328,
- .irq_subsample_period = 0x00002348,
- .irq_subsample_pattern = 0x0000234C,
- .framedrop_period = 0x00002350,
- .framedrop_pattern = 0x00002354,
- .frame_inc = 0x00002358,
- .burst_limit = 0x0000235C,
- .ubwc_regs = NULL,
- },
- /* BUS Client 2 */
- {
- .status0 = 0x00002400,
- .status1 = 0x00002404,
- .cfg = 0x00002408,
- .header_addr = 0x0000240C,
- .header_cfg = 0x00002410,
- .image_addr = 0x00002414,
- .image_addr_offset = 0x00002418,
- .buffer_width_cfg = 0x0000241C,
- .buffer_height_cfg = 0x00002420,
- .packer_cfg = 0x00002424,
- .stride = 0x00002428,
- .irq_subsample_period = 0x00002448,
- .irq_subsample_pattern = 0x0000244C,
- .framedrop_period = 0x00002450,
- .framedrop_pattern = 0x00002454,
- .frame_inc = 0x00002458,
- .burst_limit = 0x0000245C,
- .ubwc_regs = NULL,
- },
- /* BUS Client 3 */
- {
- .status0 = 0x00002500,
- .status1 = 0x00002504,
- .cfg = 0x00002508,
- .header_addr = 0x0000250C,
- .header_cfg = 0x00002510,
- .image_addr = 0x00002514,
- .image_addr_offset = 0x00002518,
- .buffer_width_cfg = 0x0000251C,
- .buffer_height_cfg = 0x00002520,
- .packer_cfg = 0x00002524,
- .stride = 0x00002528,
- .irq_subsample_period = 0x00002548,
- .irq_subsample_pattern = 0x0000254C,
- .framedrop_period = 0x00002550,
- .framedrop_pattern = 0x00002554,
- .frame_inc = 0x00002558,
- .burst_limit = 0x0000255C,
- .ubwc_regs = NULL,
- },
- },
- .comp_grp_reg = {
- /* CAM_VFE_BUS_VER2_COMP_GRP_0 */
- {
- .comp_mask = 0x00002010,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_1 */
- {
- .comp_mask = 0x00002014,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_2 */
- {
- .comp_mask = 0x00002018,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_3 */
- {
- .comp_mask = 0x0000201C,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_4 */
- {
- .comp_mask = 0x00002020,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_5 */
- {
- .comp_mask = 0x00002024,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 */
- {
- .comp_mask = 0x0000202C,
- .addr_sync_mask = 0x00002088,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1 */
- {
- .comp_mask = 0x00002030,
- .addr_sync_mask = 0x0000208C,
-
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2 */
- {
- .comp_mask = 0x00002034,
- .addr_sync_mask = 0x00002090,
-
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3 */
- {
- .comp_mask = 0x00002038,
- .addr_sync_mask = 0x00002094,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4 */
- {
- .comp_mask = 0x0000203C,
- .addr_sync_mask = 0x00002098,
- },
- /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 */
- {
- .comp_mask = 0x00002040,
- .addr_sync_mask = 0x0000209C,
- },
- },
- .num_out = 4,
- .vfe_out_hw_info = {
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
- .max_width = -1,
- .max_height = -1,
- },
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1,
- .max_width = -1,
- .max_height = -1,
- },
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2,
- .max_width = -1,
- .max_height = -1,
- },
- {
- .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI3,
- .max_width = -1,
- .max_height = -1,
- },
- },
-};
-
-static struct cam_vfe_hw_info cam_vfe_lite170_hw_info = {
- .irq_reg_info = &vfe170_top_irq_reg_info,
-
- .bus_version = CAM_VFE_BUS_VER_2_0,
- .bus_hw_info = &vfe170_bus_hw_info,
-
- .top_version = CAM_VFE_TOP_VER_2_0,
- .top_hw_info = &vfe170_top_hw_info,
-
-};
-
-#endif /* _CAM_VFE_LITE170_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
index 88d5b132ad3d..61c1e9e01ba2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -828,6 +828,12 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.max_height = -1,
},
},
+ .reg_data = {
+ .ubwc_10bit_threshold_lossy_0 = 0,
+ .ubwc_10bit_threshold_lossy_1 = 0,
+ .ubwc_8bit_threshold_lossy_0 = 0,
+ .ubwc_8bit_threshold_lossy_1 = 0,
+ },
};
struct cam_vfe_hw_info cam_vfe170_hw_info = {
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
index d1284d9f23d2..13147f4acf96 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,16 +10,17 @@
* GNU General Public License for more details.
*/
-#ifndef _CAM_VFE170_H_
-#define _CAM_VFE170_H_
+#ifndef _CAM_VFE175_H_
+#define _CAM_VFE175_H_
#include "cam_vfe_camif_ver2.h"
+#include "cam_vfe_camif_lite_ver2.h"
#include "cam_vfe_bus_ver2.h"
#include "cam_irq_controller.h"
#include "cam_vfe_top_ver2.h"
#include "cam_vfe_core.h"
-static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
+static struct cam_irq_register_set vfe175_top_irq_reg_set[2] = {
{
.mask_reg_offset = 0x0000005C,
.clear_reg_offset = 0x00000064,
@@ -32,14 +33,14 @@ static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
},
};
-static struct cam_irq_controller_reg_info vfe170_top_irq_reg_info = {
+static struct cam_irq_controller_reg_info vfe175_top_irq_reg_info = {
.num_registers = 2,
- .irq_reg_set = vfe170_top_irq_reg_set,
+ .irq_reg_set = vfe175_top_irq_reg_set,
.global_clear_offset = 0x00000058,
.global_clear_bitmask = 0x00000001,
};
-static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = {
+static struct cam_vfe_camif_ver2_reg vfe175_camif_reg = {
.camif_cmd = 0x00000478,
.camif_config = 0x0000047C,
.line_skip_pattern = 0x00000488,
@@ -54,7 +55,7 @@ static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = {
.vfe_diag_sensor_status = 0x00000C4C,
};
-static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
+static struct cam_vfe_camif_reg_data vfe_175_camif_reg_data = {
.raw_crop_first_pixel_shift = 16,
.raw_crop_first_pixel_mask = 0xFFFF,
.raw_crop_last_pixel_shift = 0x0,
@@ -80,35 +81,57 @@ static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
.reg_update_irq_mask = 0x00000010,
.eof_irq_mask = 0x00000002,
.error_irq_mask0 = 0x0003FC00,
- .error_irq_mask1 = 0x0FFF7E80,
+ .error_irq_mask1 = 0xEFFF7E80,
.enable_diagnostic_hw = 0x1,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = {
+static struct cam_vfe_camif_lite_ver2_reg vfe175_camif_lite_reg = {
+ .camif_lite_cmd = 0x00000FC0,
+ .camif_lite_config = 0x00000FC4,
+ .lite_skip_period = 0x00000FC8,
+ .lite_irq_subsample_pattern = 0x00000FCC,
+ .lite_epoch_irq = 0x00000FD0,
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg_data vfe175_camif_lite_reg_data = {
+ .dual_pd_reg_update_cmd_data = 0x20,
+ .lite_epoch_line_cfg = 0x00140014,
+ .lite_sof_irq_mask = 0x00040000,
+ .lite_epoch0_irq_mask = 0x00100000,
+ .dual_pd_reg_upd_irq_mask = 0x04000000,
+ .lite_eof_irq_mask = 0x00080000,
+ .lite_error_irq_mask0 = 0x00400000,
+ .lite_error_irq_mask1 = 0x00004100,
+ .extern_reg_update_shift = 4,
+ .dual_pd_path_sel_shift = 24,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_reg = {
.reset = 0x0000001C,
.cgc_ovd = 0x0000002C,
.enable = 0x00000040,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_170_reg = {
+struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_175_reg = {
.reset = 0x00000020,
.cgc_ovd = 0x00000030,
.enable = 0x00000044,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl color_170_reg = {
+struct cam_vfe_top_ver2_reg_offset_module_ctrl color_175_reg = {
.reset = 0x00000024,
.cgc_ovd = 0x00000034,
.enable = 0x00000048,
};
-struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_170_reg = {
+struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_reg = {
.reset = 0x00000028,
.cgc_ovd = 0x00000038,
.enable = 0x0000004C,
};
-static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
+static struct cam_vfe_top_ver2_reg_offset_common vfe175_top_common_reg = {
.hw_version = 0x00000000,
.hw_capability = 0x00000004,
.lens_feature = 0x00000008,
@@ -117,10 +140,10 @@ static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
.zoom_feature = 0x00000014,
.global_reset_cmd = 0x00000018,
.module_ctrl = {
- &lens_170_reg,
- &stats_170_reg,
- &color_170_reg,
- &zoom_170_reg,
+ &lens_175_reg,
+ &stats_175_reg,
+ &color_175_reg,
+ &zoom_175_reg,
},
.bus_cgc_ovd = 0x0000003C,
.core_cfg = 0x00000050,
@@ -129,42 +152,47 @@ static struct cam_vfe_top_ver2_reg_offset_common vfe170_top_common_reg = {
.reg_update_cmd = 0x000004AC,
};
-static struct cam_vfe_rdi_ver2_reg vfe170_rdi_reg = {
+static struct cam_vfe_rdi_ver2_reg vfe175_rdi_reg = {
.reg_update_cmd = 0x000004AC,
};
-static struct cam_vfe_rdi_reg_data vfe_170_rdi_0_data = {
+static struct cam_vfe_rdi_reg_data vfe_175_rdi_0_data = {
.reg_update_cmd_data = 0x2,
.sof_irq_mask = 0x8000000,
.reg_update_irq_mask = 0x20,
};
-static struct cam_vfe_rdi_reg_data vfe_170_rdi_1_data = {
+static struct cam_vfe_rdi_reg_data vfe_175_rdi_1_data = {
.reg_update_cmd_data = 0x4,
.sof_irq_mask = 0x10000000,
.reg_update_irq_mask = 0x40,
};
-static struct cam_vfe_rdi_reg_data vfe_170_rdi_2_data = {
+static struct cam_vfe_rdi_reg_data vfe_175_rdi_2_data = {
.reg_update_cmd_data = 0x8,
.sof_irq_mask = 0x20000000,
.reg_update_irq_mask = 0x80,
};
-static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
- .common_reg = &vfe170_top_common_reg,
+static struct cam_vfe_top_ver2_hw_info vfe175_top_hw_info = {
+ .common_reg = &vfe175_top_common_reg,
.camif_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .camif_reg = &vfe170_camif_reg,
- .reg_data = &vfe_170_camif_reg_data,
+ .common_reg = &vfe175_top_common_reg,
+ .camif_reg = &vfe175_camif_reg,
+ .reg_data = &vfe_175_camif_reg_data,
+ },
+ .camif_lite_hw_info = {
+ .common_reg = &vfe175_top_common_reg,
+ .camif_lite_reg = &vfe175_camif_lite_reg,
+ .reg_data = &vfe175_camif_lite_reg_data,
},
.rdi_hw_info = {
- .common_reg = &vfe170_top_common_reg,
- .rdi_reg = &vfe170_rdi_reg,
+ .common_reg = &vfe175_top_common_reg,
+ .rdi_reg = &vfe175_rdi_reg,
.reg_data = {
- &vfe_170_rdi_0_data,
- &vfe_170_rdi_1_data,
- &vfe_170_rdi_2_data,
+ &vfe_175_rdi_0_data,
+ &vfe_175_rdi_1_data,
+ &vfe_175_rdi_2_data,
NULL,
},
},
@@ -173,10 +201,11 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = {
CAM_VFE_RDI_VER_1_0,
CAM_VFE_RDI_VER_1_0,
CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_CAMIF_LITE_VER_2_0,
},
};
-static struct cam_irq_register_set vfe170_bus_irq_reg[3] = {
+static struct cam_irq_register_set vfe175_bus_irq_reg[3] = {
{
.mask_reg_offset = 0x00002044,
.clear_reg_offset = 0x00002050,
@@ -194,29 +223,68 @@ static struct cam_irq_register_set vfe170_bus_irq_reg[3] = {
},
};
-static struct cam_vfe_bus_ver2_reg_offset_ubwc_client ubwc_regs_client_3 = {
- .tile_cfg = 0x0000252C,
- .h_init = 0x00002530,
- .v_init = 0x00002534,
- .meta_addr = 0x00002538,
- .meta_offset = 0x0000253C,
- .meta_stride = 0x00002540,
- .mode_cfg = 0x00002544,
- .bw_limit = 0x000025A0,
+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,
+ .threshlod_lossy_0 = 0x000025A8,
+ .threshlod_lossy_1 = 0x000025AC,
+
+};
+
+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,
+ .threshlod_lossy_0 = 0x000026A8,
+ .threshlod_lossy_1 = 0x000026AC,
};
-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 = 0x00002644,
- .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,
+ .threshlod_lossy_0 = 0x000036A8,
+ .threshlod_lossy_1 = 0x000036AC,
};
-static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_ubwc_regs_client_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,
+ .threshlod_lossy_0 = 0x000037A8,
+ .threshlod_lossy_1 = 0x000037AC,
+};
+
+static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = {
.common_reg = {
.hw_version = 0x00002000,
.hw_capability = 0x00002004,
@@ -226,7 +294,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.dual_master_comp_cfg = 0x00002028,
.irq_reg_info = {
.num_registers = 3,
- .irq_reg_set = vfe170_bus_irq_reg,
+ .irq_reg_set = vfe175_bus_irq_reg,
.global_clear_offset = 0x00002068,
.global_clear_bitmask = 0x00000001,
},
@@ -240,7 +308,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.debug_status_cfg = 0x0000226C,
.debug_status_0 = 0x00002270,
},
- .num_client = 20,
+ .num_client = 24,
.bus_client_reg = {
/* BUS Client 0 */
{
@@ -324,7 +392,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.framedrop_pattern = 0x00002554,
.frame_inc = 0x00002558,
.burst_limit = 0x0000255C,
- .ubwc_regs = &ubwc_regs_client_3,
+ .ubwc_regs = &vfe175_ubwc_regs_client_3,
},
/* BUS Client 4 */
{
@@ -345,7 +413,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.framedrop_pattern = 0x00002654,
.frame_inc = 0x00002658,
.burst_limit = 0x0000265C,
- .ubwc_regs = &ubwc_regs_client_4,
+ .ubwc_regs = &vfe175_ubwc_regs_client_4,
},
/* BUS Client 5 */
{
@@ -662,6 +730,90 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.burst_limit = 0x0000355C,
.ubwc_regs = NULL,
},
+ /* BUS Client 20 */
+ {
+ .status0 = 0x00003600,
+ .status1 = 0x00003604,
+ .cfg = 0x00003608,
+ .header_addr = 0x0000360C,
+ .header_cfg = 0x00003610,
+ .image_addr = 0x00003614,
+ .image_addr_offset = 0x00003618,
+ .buffer_width_cfg = 0x0000361C,
+ .buffer_height_cfg = 0x00003620,
+ .packer_cfg = 0x00003624,
+ .stride = 0x00003628,
+ .irq_subsample_period = 0x00003648,
+ .irq_subsample_pattern = 0x0000364C,
+ .framedrop_period = 0x00003650,
+ .framedrop_pattern = 0x00003654,
+ .frame_inc = 0x00003658,
+ .burst_limit = 0x0000365C,
+ .ubwc_regs = &vfe175_ubwc_regs_client_20,
+ },
+ /* BUS Client 21 */
+ {
+ .status0 = 0x00003700,
+ .status1 = 0x00003704,
+ .cfg = 0x00003708,
+ .header_addr = 0x0000370C,
+ .header_cfg = 0x00003710,
+ .image_addr = 0x00003714,
+ .image_addr_offset = 0x00003718,
+ .buffer_width_cfg = 0x0000371C,
+ .buffer_height_cfg = 0x00003720,
+ .packer_cfg = 0x00003724,
+ .stride = 0x00003728,
+ .irq_subsample_period = 0x00003748,
+ .irq_subsample_pattern = 0x0000374C,
+ .framedrop_period = 0x00003750,
+ .framedrop_pattern = 0x00003754,
+ .frame_inc = 0x00003758,
+ .burst_limit = 0x0000375C,
+ .ubwc_regs = &vfe175_ubwc_regs_client_21,
+ },
+ /* BUS Client 22 */
+ {
+ .status0 = 0x00003800,
+ .status1 = 0x00003804,
+ .cfg = 0x00003808,
+ .header_addr = 0x0000380C,
+ .header_cfg = 0x00003810,
+ .image_addr = 0x00003814,
+ .image_addr_offset = 0x00003818,
+ .buffer_width_cfg = 0x0000381C,
+ .buffer_height_cfg = 0x00003820,
+ .packer_cfg = 0x00003824,
+ .stride = 0x00003828,
+ .irq_subsample_period = 0x00003848,
+ .irq_subsample_pattern = 0x0000384C,
+ .framedrop_period = 0x00003850,
+ .framedrop_pattern = 0x00003854,
+ .frame_inc = 0x00003858,
+ .burst_limit = 0x0000385C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 23 */
+ {
+ .status0 = 0x00003900,
+ .status1 = 0x00003904,
+ .cfg = 0x00003908,
+ .header_addr = 0x0000390C,
+ .header_cfg = 0x00003910,
+ .image_addr = 0x00003914,
+ .image_addr_offset = 0x00003918,
+ .buffer_width_cfg = 0x0000391C,
+ .buffer_height_cfg = 0x00003920,
+ .packer_cfg = 0x00003924,
+ .stride = 0x00003928,
+ .irq_subsample_period = 0x00003948,
+ .irq_subsample_pattern = 0x0000394C,
+ .framedrop_period = 0x00003950,
+ .framedrop_pattern = 0x00003954,
+ .frame_inc = 0x00003958,
+ .burst_limit = 0x0000395C,
+ .ubwc_regs = NULL,
+ },
},
.comp_grp_reg = {
/* CAM_VFE_BUS_VER2_COMP_GRP_0 */
@@ -721,7 +873,7 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.addr_sync_mask = 0x0000209C,
},
},
- .num_out = 18,
+ .num_out = 22,
.vfe_out_hw_info = {
{
.vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
@@ -822,21 +974,50 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
.max_width = -1,
.max_height = -1,
},
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP,
+ .max_width = 4096,
+ .max_height = 4096,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ },
+ .reg_data = {
+ .ubwc_10bit_threshold_lossy_0 = 0x8330002,
+ .ubwc_10bit_threshold_lossy_1 = 0x20204,
+ .ubwc_8bit_threshold_lossy_0 = 0x6210022,
+ .ubwc_8bit_threshold_lossy_1 = 0xE0E,
},
};
-struct cam_vfe_hw_info cam_vfe170_hw_info = {
- .irq_reg_info = &vfe170_top_irq_reg_info,
+struct cam_vfe_hw_info cam_vfe175_hw_info = {
+ .irq_reg_info = &vfe175_top_irq_reg_info,
.bus_version = CAM_VFE_BUS_VER_2_0,
- .bus_hw_info = &vfe170_bus_hw_info,
+ .bus_hw_info = &vfe175_bus_hw_info,
.top_version = CAM_VFE_TOP_VER_2_0,
- .top_hw_info = &vfe170_top_hw_info,
+ .top_hw_info = &vfe175_top_hw_info,
.camif_version = CAM_VFE_CAMIF_VER_2_0,
- .camif_reg = &vfe170_camif_reg,
+ .camif_reg = &vfe175_camif_reg,
+
+ .camif_lite_version = CAM_VFE_CAMIF_LITE_VER_2_0,
+ .camif_lite_reg = &vfe175_camif_lite_reg,
};
-#endif /* _CAM_VFE170_H_ */
+#endif /* _CAM_VFE175_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
new file mode 100644
index 000000000000..5a09c76f95b0
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
@@ -0,0 +1,1131 @@
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_VFE175_130_H_
+#define _CAM_VFE175_130_H_
+
+#include "cam_vfe_camif_ver2.h"
+#include "cam_vfe_camif_lite_ver2.h"
+#include "cam_vfe_bus_ver2.h"
+#include "cam_vfe_bus_rd_ver1.h"
+#include "cam_irq_controller.h"
+#include "cam_vfe_top_ver2.h"
+#include "cam_vfe_core.h"
+
+static struct cam_irq_register_set vfe175_130_top_irq_reg_set[2] = {
+ {
+ .mask_reg_offset = 0x0000005C,
+ .clear_reg_offset = 0x00000064,
+ .status_reg_offset = 0x0000006C,
+ },
+ {
+ .mask_reg_offset = 0x00000060,
+ .clear_reg_offset = 0x00000068,
+ .status_reg_offset = 0x00000070,
+ },
+};
+
+static struct cam_irq_controller_reg_info vfe175_130_top_irq_reg_info = {
+ .num_registers = 2,
+ .irq_reg_set = vfe175_130_top_irq_reg_set,
+ .global_clear_offset = 0x00000058,
+ .global_clear_bitmask = 0x00000001,
+};
+
+static struct cam_vfe_camif_ver2_reg vfe175_130_camif_reg = {
+ .camif_cmd = 0x00000478,
+ .camif_config = 0x0000047C,
+ .line_skip_pattern = 0x00000488,
+ .pixel_skip_pattern = 0x0000048C,
+ .skip_period = 0x00000490,
+ .irq_subsample_pattern = 0x0000049C,
+ .epoch_irq = 0x000004A0,
+ .raw_crop_width_cfg = 0x00000CE4,
+ .raw_crop_height_cfg = 0x00000CE8,
+ .reg_update_cmd = 0x000004AC,
+ .vfe_diag_config = 0x00000C48,
+ .vfe_diag_sensor_status = 0x00000C4C,
+};
+
+static struct cam_vfe_camif_reg_data vfe_175_130_camif_reg_data = {
+ .raw_crop_first_pixel_shift = 16,
+ .raw_crop_first_pixel_mask = 0xFFFF,
+ .raw_crop_last_pixel_shift = 0x0,
+ .raw_crop_last_pixel_mask = 0x3FFF,
+ .raw_crop_first_line_shift = 16,
+ .raw_crop_first_line_mask = 0xFFFF,
+ .raw_crop_last_line_shift = 0,
+ .raw_crop_last_line_mask = 0x3FFF,
+ .input_mux_sel_shift = 5,
+ .input_mux_sel_mask = 0x3,
+ .extern_reg_update_shift = 4,
+ .extern_reg_update_mask = 1,
+ .pixel_pattern_shift = 0,
+ .pixel_pattern_mask = 0x7,
+ .dsp_mode_shift = 23,
+ .dsp_mode_mask = 0x1,
+ .dsp_en_shift = 3,
+ .dsp_en_mask = 0x1,
+ .reg_update_cmd_data = 0x1,
+ .epoch_line_cfg = 0x00140014,
+ .sof_irq_mask = 0x00000001,
+ .epoch0_irq_mask = 0x00000004,
+ .reg_update_irq_mask = 0x00000010,
+ .eof_irq_mask = 0x00000002,
+ .error_irq_mask0 = 0x0003FC00,
+ .error_irq_mask1 = 0xEFFF7E80,
+ .enable_diagnostic_hw = 0x1,
+};
+
+static struct cam_vfe_fe_ver1_reg vfe175_130_fe_reg = {
+ .camif_cmd = 0x00000478,
+ .camif_config = 0x0000047C,
+ .line_skip_pattern = 0x00000488,
+ .pixel_skip_pattern = 0x0000048C,
+ .skip_period = 0x00000490,
+ .irq_subsample_pattern = 0x0000049C,
+ .epoch_irq = 0x000004A0,
+ .raw_crop_width_cfg = 0x00000CE4,
+ .raw_crop_height_cfg = 0x00000CE8,
+ .reg_update_cmd = 0x000004AC,
+ .vfe_diag_config = 0x00000C48,
+ .vfe_diag_sensor_status = 0x00000C4C,
+ .fe_cfg = 0x00000084,
+};
+
+static struct cam_vfe_fe_reg_data vfe_175_130_fe_reg_data = {
+ .raw_crop_first_pixel_shift = 16,
+ .raw_crop_first_pixel_mask = 0xFFFF,
+ .raw_crop_last_pixel_shift = 0x0,
+ .raw_crop_last_pixel_mask = 0x3FFF,
+ .raw_crop_first_line_shift = 16,
+ .raw_crop_first_line_mask = 0xFFFF,
+ .raw_crop_last_line_shift = 0,
+ .raw_crop_last_line_mask = 0x3FFF,
+ .input_mux_sel_shift = 5,
+ .input_mux_sel_mask = 0x3,
+ .extern_reg_update_shift = 4,
+ .extern_reg_update_mask = 1,
+ .pixel_pattern_shift = 0,
+ .pixel_pattern_mask = 0x7,
+ .dsp_mode_shift = 23,
+ .dsp_mode_mask = 0x1,
+ .dsp_en_shift = 3,
+ .dsp_en_mask = 0x1,
+ .reg_update_cmd_data = 0x1,
+ .epoch_line_cfg = 0x00140014,
+ .sof_irq_mask = 0x00000001,
+ .epoch0_irq_mask = 0x00000004,
+ .reg_update_irq_mask = 0x00000010,
+ .eof_irq_mask = 0x00000002,
+ .error_irq_mask0 = 0x0003FC00,
+ .error_irq_mask1 = 0xEFFF7E80,
+ .enable_diagnostic_hw = 0x1,
+ .fe_mux_data = 0x2,
+ .hbi_cnt_shift = 0x8,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg vfe175_130_camif_lite_reg = {
+ .camif_lite_cmd = 0x00000FC0,
+ .camif_lite_config = 0x00000FC4,
+ .lite_skip_period = 0x00000FC8,
+ .lite_irq_subsample_pattern = 0x00000FCC,
+ .lite_epoch_irq = 0x00000FD0,
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_camif_lite_ver2_reg_data
+ vfe175_130_camif_lite_reg_data = {
+ .dual_pd_reg_update_cmd_data = 0x20,
+ .lite_epoch_line_cfg = 0x00140014,
+ .lite_sof_irq_mask = 0x00040000,
+ .lite_epoch0_irq_mask = 0x00100000,
+ .dual_pd_reg_upd_irq_mask = 0x04000000,
+ .lite_eof_irq_mask = 0x00080000,
+ .lite_error_irq_mask0 = 0x00400000,
+ .lite_error_irq_mask1 = 0x00004100,
+ .extern_reg_update_shift = 4,
+ .dual_pd_path_sel_shift = 24,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_175_130_reg = {
+ .reset = 0x0000001C,
+ .cgc_ovd = 0x0000002C,
+ .enable = 0x00000040,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl stats_175_130_reg = {
+ .reset = 0x00000020,
+ .cgc_ovd = 0x00000030,
+ .enable = 0x00000044,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl color_175_130_reg = {
+ .reset = 0x00000024,
+ .cgc_ovd = 0x00000034,
+ .enable = 0x00000048,
+};
+
+struct cam_vfe_top_ver2_reg_offset_module_ctrl zoom_175_130_reg = {
+ .reset = 0x00000028,
+ .cgc_ovd = 0x00000038,
+ .enable = 0x0000004C,
+};
+
+static struct cam_vfe_top_ver2_reg_offset_common vfe175_130_top_common_reg = {
+ .hw_version = 0x00000000,
+ .hw_capability = 0x00000004,
+ .lens_feature = 0x00000008,
+ .stats_feature = 0x0000000C,
+ .color_feature = 0x00000010,
+ .zoom_feature = 0x00000014,
+ .global_reset_cmd = 0x00000018,
+ .module_ctrl = {
+ &lens_175_130_reg,
+ &stats_175_130_reg,
+ &color_175_130_reg,
+ &zoom_175_130_reg,
+ },
+ .bus_cgc_ovd = 0x0000003C,
+ .core_cfg = 0x00000050,
+ .three_D_cfg = 0x00000054,
+ .violation_status = 0x0000007C,
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_ver2_reg vfe175_130_rdi_reg = {
+ .reg_update_cmd = 0x000004AC,
+};
+
+static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_0_data = {
+ .reg_update_cmd_data = 0x2,
+ .sof_irq_mask = 0x8000000,
+ .reg_update_irq_mask = 0x20,
+};
+
+static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_1_data = {
+ .reg_update_cmd_data = 0x4,
+ .sof_irq_mask = 0x10000000,
+ .reg_update_irq_mask = 0x40,
+};
+
+static struct cam_vfe_rdi_reg_data vfe_175_130_rdi_2_data = {
+ .reg_update_cmd_data = 0x8,
+ .sof_irq_mask = 0x20000000,
+ .reg_update_irq_mask = 0x80,
+};
+
+static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .camif_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .camif_reg = &vfe175_130_camif_reg,
+ .reg_data = &vfe_175_130_camif_reg_data,
+ },
+ .camif_lite_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .camif_lite_reg = &vfe175_130_camif_lite_reg,
+ .reg_data = &vfe175_130_camif_lite_reg_data,
+ },
+ .rdi_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .rdi_reg = &vfe175_130_rdi_reg,
+ .reg_data = {
+ &vfe_175_130_rdi_0_data,
+ &vfe_175_130_rdi_1_data,
+ &vfe_175_130_rdi_2_data,
+ NULL,
+ },
+ },
+ .fe_hw_info = {
+ .common_reg = &vfe175_130_top_common_reg,
+ .fe_reg = &vfe175_130_fe_reg,
+ .reg_data = &vfe_175_130_fe_reg_data,
+ },
+ .mux_type = {
+ CAM_VFE_CAMIF_VER_2_0,
+ CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_RDI_VER_1_0,
+ CAM_VFE_CAMIF_LITE_VER_2_0,
+ CAM_VFE_IN_RD_VER_1_0,
+ },
+};
+
+static struct cam_irq_register_set vfe175_130_bus_rd_irq_reg[1] = {
+ {
+ .mask_reg_offset = 0x00005010,
+ .clear_reg_offset = 0x00005014,
+ .status_reg_offset = 0x0000501C,
+ },
+};
+
+static struct cam_irq_register_set vfe175_130_bus_irq_reg[3] = {
+ {
+ .mask_reg_offset = 0x00002044,
+ .clear_reg_offset = 0x00002050,
+ .status_reg_offset = 0x0000205C,
+ },
+ {
+ .mask_reg_offset = 0x00002048,
+ .clear_reg_offset = 0x00002054,
+ .status_reg_offset = 0x00002060,
+ },
+ {
+ .mask_reg_offset = 0x0000204C,
+ .clear_reg_offset = 0x00002058,
+ .status_reg_offset = 0x00002064,
+ },
+};
+
+static struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client
+ vfe175_130_ubwc_regs_client_3 = {
+ .tile_cfg = 0x0000252C,
+ .h_init = 0x00002530,
+ .v_init = 0x00002534,
+ .meta_addr = 0x00002538,
+ .meta_offset = 0x0000253C,
+ .meta_stride = 0x00002540,
+ .mode_cfg_0 = 0x00002544,
+ .mode_cfg_1 = 0x000025A4,
+ .bw_limit = 0x000025A0,
+ .threshlod_lossy_0 = 0x000025A8,
+ .threshlod_lossy_1 = 0x000025AC,
+};
+
+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,
+ .threshlod_lossy_0 = 0x000026A8,
+ .threshlod_lossy_1 = 0x000026AC,
+};
+
+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,
+ .threshlod_lossy_0 = 0x000036A8,
+ .threshlod_lossy_1 = 0x000036AC,
+};
+
+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,
+ .threshlod_lossy_0 = 0x000037A8,
+ .threshlod_lossy_1 = 0x000037AC,
+};
+
+static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
+ .common_reg = {
+ .hw_version = 0x00005000,
+ .hw_capability = 0x00005004,
+ .sw_reset = 0x00005008,
+ .cgc_ovd = 0x0000500C,
+ .pwr_iso_cfg = 0x000050CC,
+ .input_if_cmd = 0x00005020,
+ .test_bus_ctrl = 0x00005048,
+ .irq_reg_info = {
+ .num_registers = 1,
+ .irq_reg_set = vfe175_130_bus_rd_irq_reg,
+ .global_clear_offset = 0x00005018,
+ .global_clear_bitmask = 0x00000001,
+ },
+ },
+ .num_client = 1,
+ .bus_client_reg = {
+ /* BUS Client 0 */
+ {
+ .cfg = 0x00005050,
+ .image_addr = 0x00005058,
+ .buffer_width_cfg = 0x0000505C,
+ .unpacker_cfg = 0x00005064,
+ .stride = 0x00005060,
+ .burst_limit = 0x00005080,
+ .latency_buf_allocation = 0x00005078,
+ .ubwc_regs = NULL,
+ },
+ },
+ .num_bus_rd_resc = 1,
+ .vfe_bus_rd_hw_info = {
+ {
+ .vfe_bus_rd_type = CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ },
+};
+
+static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {
+ .common_reg = {
+ .hw_version = 0x00002000,
+ .hw_capability = 0x00002004,
+ .sw_reset = 0x00002008,
+ .cgc_ovd = 0x0000200C,
+ .pwr_iso_cfg = 0x000020CC,
+ .dual_master_comp_cfg = 0x00002028,
+ .irq_reg_info = {
+ .num_registers = 3,
+ .irq_reg_set = vfe175_130_bus_irq_reg,
+ .global_clear_offset = 0x00002068,
+ .global_clear_bitmask = 0x00000001,
+ },
+ .comp_error_status = 0x0000206C,
+ .comp_ovrwr_status = 0x00002070,
+ .dual_comp_error_status = 0x00002074,
+ .dual_comp_ovrwr_status = 0x00002078,
+ .addr_sync_cfg = 0x0000207C,
+ .addr_sync_frame_hdr = 0x00002080,
+ .addr_sync_no_sync = 0x00002084,
+ },
+ .num_client = 24,
+ .bus_client_reg = {
+ /* BUS Client 0 */
+ {
+ .status0 = 0x00002200,
+ .status1 = 0x00002204,
+ .cfg = 0x00002208,
+ .header_addr = 0x0000220C,
+ .header_cfg = 0x00002210,
+ .image_addr = 0x00002214,
+ .image_addr_offset = 0x00002218,
+ .buffer_width_cfg = 0x0000221C,
+ .buffer_height_cfg = 0x00002220,
+ .packer_cfg = 0x00002224,
+ .stride = 0x00002228,
+ .irq_subsample_period = 0x00002248,
+ .irq_subsample_pattern = 0x0000224C,
+ .framedrop_period = 0x00002250,
+ .framedrop_pattern = 0x00002254,
+ .frame_inc = 0x00002258,
+ .burst_limit = 0x0000225C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 1 */
+ {
+ .status0 = 0x00002300,
+ .status1 = 0x00002304,
+ .cfg = 0x00002308,
+ .header_addr = 0x0000230C,
+ .header_cfg = 0x00002310,
+ .image_addr = 0x00002314,
+ .image_addr_offset = 0x00002318,
+ .buffer_width_cfg = 0x0000231C,
+ .buffer_height_cfg = 0x00002320,
+ .packer_cfg = 0x00002324,
+ .stride = 0x00002328,
+ .irq_subsample_period = 0x00002348,
+ .irq_subsample_pattern = 0x0000234C,
+ .framedrop_period = 0x00002350,
+ .framedrop_pattern = 0x00002354,
+ .frame_inc = 0x00002358,
+ .burst_limit = 0x0000235C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 2 */
+ {
+ .status0 = 0x00002400,
+ .status1 = 0x00002404,
+ .cfg = 0x00002408,
+ .header_addr = 0x0000240C,
+ .header_cfg = 0x00002410,
+ .image_addr = 0x00002414,
+ .image_addr_offset = 0x00002418,
+ .buffer_width_cfg = 0x0000241C,
+ .buffer_height_cfg = 0x00002420,
+ .packer_cfg = 0x00002424,
+ .stride = 0x00002428,
+ .irq_subsample_period = 0x00002448,
+ .irq_subsample_pattern = 0x0000244C,
+ .framedrop_period = 0x00002450,
+ .framedrop_pattern = 0x00002454,
+ .frame_inc = 0x00002458,
+ .burst_limit = 0x0000245C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 3 */
+ {
+ .status0 = 0x00002500,
+ .status1 = 0x00002504,
+ .cfg = 0x00002508,
+ .header_addr = 0x0000250C,
+ .header_cfg = 0x00002510,
+ .image_addr = 0x00002514,
+ .image_addr_offset = 0x00002518,
+ .buffer_width_cfg = 0x0000251C,
+ .buffer_height_cfg = 0x00002520,
+ .packer_cfg = 0x00002524,
+ .stride = 0x00002528,
+ .irq_subsample_period = 0x00002548,
+ .irq_subsample_pattern = 0x0000254C,
+ .framedrop_period = 0x00002550,
+ .framedrop_pattern = 0x00002554,
+ .frame_inc = 0x00002558,
+ .burst_limit = 0x0000255C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_3,
+ },
+ /* BUS Client 4 */
+ {
+ .status0 = 0x00002600,
+ .status1 = 0x00002604,
+ .cfg = 0x00002608,
+ .header_addr = 0x0000260C,
+ .header_cfg = 0x00002610,
+ .image_addr = 0x00002614,
+ .image_addr_offset = 0x00002618,
+ .buffer_width_cfg = 0x0000261C,
+ .buffer_height_cfg = 0x00002620,
+ .packer_cfg = 0x00002624,
+ .stride = 0x00002628,
+ .irq_subsample_period = 0x00002648,
+ .irq_subsample_pattern = 0x0000264C,
+ .framedrop_period = 0x00002650,
+ .framedrop_pattern = 0x00002654,
+ .frame_inc = 0x00002658,
+ .burst_limit = 0x0000265C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_4,
+ },
+ /* BUS Client 5 */
+ {
+ .status0 = 0x00002700,
+ .status1 = 0x00002704,
+ .cfg = 0x00002708,
+ .header_addr = 0x0000270C,
+ .header_cfg = 0x00002710,
+ .image_addr = 0x00002714,
+ .image_addr_offset = 0x00002718,
+ .buffer_width_cfg = 0x0000271C,
+ .buffer_height_cfg = 0x00002720,
+ .packer_cfg = 0x00002724,
+ .stride = 0x00002728,
+ .irq_subsample_period = 0x00002748,
+ .irq_subsample_pattern = 0x0000274C,
+ .framedrop_period = 0x00002750,
+ .framedrop_pattern = 0x00002754,
+ .frame_inc = 0x00002758,
+ .burst_limit = 0x0000275C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 6 */
+ {
+ .status0 = 0x00002800,
+ .status1 = 0x00002804,
+ .cfg = 0x00002808,
+ .header_addr = 0x0000280C,
+ .header_cfg = 0x00002810,
+ .image_addr = 0x00002814,
+ .image_addr_offset = 0x00002818,
+ .buffer_width_cfg = 0x0000281C,
+ .buffer_height_cfg = 0x00002820,
+ .packer_cfg = 0x00002824,
+ .stride = 0x00002828,
+ .irq_subsample_period = 0x00002848,
+ .irq_subsample_pattern = 0x0000284C,
+ .framedrop_period = 0x00002850,
+ .framedrop_pattern = 0x00002854,
+ .frame_inc = 0x00002858,
+ .burst_limit = 0x0000285C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 7 */
+ {
+ .status0 = 0x00002900,
+ .status1 = 0x00002904,
+ .cfg = 0x00002908,
+ .header_addr = 0x0000290C,
+ .header_cfg = 0x00002910,
+ .image_addr = 0x00002914,
+ .image_addr_offset = 0x00002918,
+ .buffer_width_cfg = 0x0000291C,
+ .buffer_height_cfg = 0x00002920,
+ .packer_cfg = 0x00002924,
+ .stride = 0x00002928,
+ .irq_subsample_period = 0x00002948,
+ .irq_subsample_pattern = 0x0000294C,
+ .framedrop_period = 0x00002950,
+ .framedrop_pattern = 0x00002954,
+ .frame_inc = 0x00002958,
+ .burst_limit = 0x0000295C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 8 */
+ {
+ .status0 = 0x00002A00,
+ .status1 = 0x00002A04,
+ .cfg = 0x00002A08,
+ .header_addr = 0x00002A0C,
+ .header_cfg = 0x00002A10,
+ .image_addr = 0x00002A14,
+ .image_addr_offset = 0x00002A18,
+ .buffer_width_cfg = 0x00002A1C,
+ .buffer_height_cfg = 0x00002A20,
+ .packer_cfg = 0x00002A24,
+ .stride = 0x00002A28,
+ .irq_subsample_period = 0x00002A48,
+ .irq_subsample_pattern = 0x00002A4C,
+ .framedrop_period = 0x00002A50,
+ .framedrop_pattern = 0x00002A54,
+ .frame_inc = 0x00002A58,
+ .burst_limit = 0x00002A5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 9 */
+ {
+ .status0 = 0x00002B00,
+ .status1 = 0x00002B04,
+ .cfg = 0x00002B08,
+ .header_addr = 0x00002B0C,
+ .header_cfg = 0x00002B10,
+ .image_addr = 0x00002B14,
+ .image_addr_offset = 0x00002B18,
+ .buffer_width_cfg = 0x00002B1C,
+ .buffer_height_cfg = 0x00002B20,
+ .packer_cfg = 0x00002B24,
+ .stride = 0x00002B28,
+ .irq_subsample_period = 0x00002B48,
+ .irq_subsample_pattern = 0x00002B4C,
+ .framedrop_period = 0x00002B50,
+ .framedrop_pattern = 0x00002B54,
+ .frame_inc = 0x00002B58,
+ .burst_limit = 0x00002B5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 10 */
+ {
+ .status0 = 0x00002C00,
+ .status1 = 0x00002C04,
+ .cfg = 0x00002C08,
+ .header_addr = 0x00002C0C,
+ .header_cfg = 0x00002C10,
+ .image_addr = 0x00002C14,
+ .image_addr_offset = 0x00002C18,
+ .buffer_width_cfg = 0x00002C1C,
+ .buffer_height_cfg = 0x00002C20,
+ .packer_cfg = 0x00002C24,
+ .stride = 0x00002C28,
+ .irq_subsample_period = 0x00002C48,
+ .irq_subsample_pattern = 0x00002C4C,
+ .framedrop_period = 0x00002C50,
+ .framedrop_pattern = 0x00002C54,
+ .frame_inc = 0x00002C58,
+ .burst_limit = 0x00002C5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 11 */
+ {
+ .status0 = 0x00002D00,
+ .status1 = 0x00002D04,
+ .cfg = 0x00002D08,
+ .header_addr = 0x00002D0C,
+ .header_cfg = 0x00002D10,
+ .image_addr = 0x00002D14,
+ .image_addr_offset = 0x00002D18,
+ .buffer_width_cfg = 0x00002D1C,
+ .buffer_height_cfg = 0x00002D20,
+ .packer_cfg = 0x00002D24,
+ .stride = 0x00002D28,
+ .irq_subsample_period = 0x00002D48,
+ .irq_subsample_pattern = 0x00002D4C,
+ .framedrop_period = 0x00002D50,
+ .framedrop_pattern = 0x00002D54,
+ .frame_inc = 0x00002D58,
+ .burst_limit = 0x00002D5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 12 */
+ {
+ .status0 = 0x00002E00,
+ .status1 = 0x00002E04,
+ .cfg = 0x00002E08,
+ .header_addr = 0x00002E0C,
+ .header_cfg = 0x00002E10,
+ .image_addr = 0x00002E14,
+ .image_addr_offset = 0x00002E18,
+ .buffer_width_cfg = 0x00002E1C,
+ .buffer_height_cfg = 0x00002E20,
+ .packer_cfg = 0x00002E24,
+ .stride = 0x00002E28,
+ .irq_subsample_period = 0x00002E48,
+ .irq_subsample_pattern = 0x00002E4C,
+ .framedrop_period = 0x00002E50,
+ .framedrop_pattern = 0x00002E54,
+ .frame_inc = 0x00002E58,
+ .burst_limit = 0x00002E5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 13 */
+ {
+ .status0 = 0x00002F00,
+ .status1 = 0x00002F04,
+ .cfg = 0x00002F08,
+ .header_addr = 0x00002F0C,
+ .header_cfg = 0x00002F10,
+ .image_addr = 0x00002F14,
+ .image_addr_offset = 0x00002F18,
+ .buffer_width_cfg = 0x00002F1C,
+ .buffer_height_cfg = 0x00002F20,
+ .packer_cfg = 0x00002F24,
+ .stride = 0x00002F28,
+ .irq_subsample_period = 0x00002F48,
+ .irq_subsample_pattern = 0x00002F4C,
+ .framedrop_period = 0x00002F50,
+ .framedrop_pattern = 0x00002F54,
+ .frame_inc = 0x00002F58,
+ .burst_limit = 0x00002F5C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 14 */
+ {
+ .status0 = 0x00003000,
+ .status1 = 0x00003004,
+ .cfg = 0x00003008,
+ .header_addr = 0x0000300C,
+ .header_cfg = 0x00003010,
+ .image_addr = 0x00003014,
+ .image_addr_offset = 0x00003018,
+ .buffer_width_cfg = 0x0000301C,
+ .buffer_height_cfg = 0x00003020,
+ .packer_cfg = 0x00003024,
+ .stride = 0x00003028,
+ .irq_subsample_period = 0x00003048,
+ .irq_subsample_pattern = 0x0000304C,
+ .framedrop_period = 0x00003050,
+ .framedrop_pattern = 0x00003054,
+ .frame_inc = 0x00003058,
+ .burst_limit = 0x0000305C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 15 */
+ {
+ .status0 = 0x00003100,
+ .status1 = 0x00003104,
+ .cfg = 0x00003108,
+ .header_addr = 0x0000310C,
+ .header_cfg = 0x00003110,
+ .image_addr = 0x00003114,
+ .image_addr_offset = 0x00003118,
+ .buffer_width_cfg = 0x0000311C,
+ .buffer_height_cfg = 0x00003120,
+ .packer_cfg = 0x00003124,
+ .stride = 0x00003128,
+ .irq_subsample_period = 0x00003148,
+ .irq_subsample_pattern = 0x0000314C,
+ .framedrop_period = 0x00003150,
+ .framedrop_pattern = 0x00003154,
+ .frame_inc = 0x00003158,
+ .burst_limit = 0x0000315C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 16 */
+ {
+ .status0 = 0x00003200,
+ .status1 = 0x00003204,
+ .cfg = 0x00003208,
+ .header_addr = 0x0000320C,
+ .header_cfg = 0x00003210,
+ .image_addr = 0x00003214,
+ .image_addr_offset = 0x00003218,
+ .buffer_width_cfg = 0x0000321C,
+ .buffer_height_cfg = 0x00003220,
+ .packer_cfg = 0x00003224,
+ .stride = 0x00003228,
+ .irq_subsample_period = 0x00003248,
+ .irq_subsample_pattern = 0x0000324C,
+ .framedrop_period = 0x00003250,
+ .framedrop_pattern = 0x00003254,
+ .frame_inc = 0x00003258,
+ .burst_limit = 0x0000325C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 17 */
+ {
+ .status0 = 0x00003300,
+ .status1 = 0x00003304,
+ .cfg = 0x00003308,
+ .header_addr = 0x0000330C,
+ .header_cfg = 0x00003310,
+ .image_addr = 0x00003314,
+ .image_addr_offset = 0x00003318,
+ .buffer_width_cfg = 0x0000331C,
+ .buffer_height_cfg = 0x00003320,
+ .packer_cfg = 0x00003324,
+ .stride = 0x00003328,
+ .irq_subsample_period = 0x00003348,
+ .irq_subsample_pattern = 0x0000334C,
+ .framedrop_period = 0x00003350,
+ .framedrop_pattern = 0x00003354,
+ .frame_inc = 0x00003358,
+ .burst_limit = 0x0000335C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 18 */
+ {
+ .status0 = 0x00003400,
+ .status1 = 0x00003404,
+ .cfg = 0x00003408,
+ .header_addr = 0x0000340C,
+ .header_cfg = 0x00003410,
+ .image_addr = 0x00003414,
+ .image_addr_offset = 0x00003418,
+ .buffer_width_cfg = 0x0000341C,
+ .buffer_height_cfg = 0x00003420,
+ .packer_cfg = 0x00003424,
+ .stride = 0x00003428,
+ .irq_subsample_period = 0x00003448,
+ .irq_subsample_pattern = 0x0000344C,
+ .framedrop_period = 0x00003450,
+ .framedrop_pattern = 0x00003454,
+ .frame_inc = 0x00003458,
+ .burst_limit = 0x0000345C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 19 */
+ {
+ .status0 = 0x00003500,
+ .status1 = 0x00003504,
+ .cfg = 0x00003508,
+ .header_addr = 0x0000350C,
+ .header_cfg = 0x00003510,
+ .image_addr = 0x00003514,
+ .image_addr_offset = 0x00003518,
+ .buffer_width_cfg = 0x0000351C,
+ .buffer_height_cfg = 0x00003520,
+ .packer_cfg = 0x00003524,
+ .stride = 0x00003528,
+ .irq_subsample_period = 0x00003548,
+ .irq_subsample_pattern = 0x0000354C,
+ .framedrop_period = 0x00003550,
+ .framedrop_pattern = 0x00003554,
+ .frame_inc = 0x00003558,
+ .burst_limit = 0x0000355C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 20 */
+ {
+ .status0 = 0x00003600,
+ .status1 = 0x00003604,
+ .cfg = 0x00003608,
+ .header_addr = 0x0000360C,
+ .header_cfg = 0x00003610,
+ .image_addr = 0x00003614,
+ .image_addr_offset = 0x00003618,
+ .buffer_width_cfg = 0x0000361C,
+ .buffer_height_cfg = 0x00003620,
+ .packer_cfg = 0x00003624,
+ .stride = 0x00003628,
+ .irq_subsample_period = 0x00003648,
+ .irq_subsample_pattern = 0x0000364C,
+ .framedrop_period = 0x00003650,
+ .framedrop_pattern = 0x00003654,
+ .frame_inc = 0x00003658,
+ .burst_limit = 0x0000365C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_20,
+ },
+ /* BUS Client 21 */
+ {
+ .status0 = 0x00003700,
+ .status1 = 0x00003704,
+ .cfg = 0x00003708,
+ .header_addr = 0x0000370C,
+ .header_cfg = 0x00003710,
+ .image_addr = 0x00003714,
+ .image_addr_offset = 0x00003718,
+ .buffer_width_cfg = 0x0000371C,
+ .buffer_height_cfg = 0x00003720,
+ .packer_cfg = 0x00003724,
+ .stride = 0x00003728,
+ .irq_subsample_period = 0x00003748,
+ .irq_subsample_pattern = 0x0000374C,
+ .framedrop_period = 0x00003750,
+ .framedrop_pattern = 0x00003754,
+ .frame_inc = 0x00003758,
+ .burst_limit = 0x0000375C,
+ .ubwc_regs =
+ &vfe175_130_ubwc_regs_client_21,
+ },
+ /* BUS Client 22 */
+ {
+ .status0 = 0x00003800,
+ .status1 = 0x00003804,
+ .cfg = 0x00003808,
+ .header_addr = 0x0000380C,
+ .header_cfg = 0x00003810,
+ .image_addr = 0x00003814,
+ .image_addr_offset = 0x00003818,
+ .buffer_width_cfg = 0x0000381C,
+ .buffer_height_cfg = 0x00003820,
+ .packer_cfg = 0x00003824,
+ .stride = 0x00003828,
+ .irq_subsample_period = 0x00003848,
+ .irq_subsample_pattern = 0x0000384C,
+ .framedrop_period = 0x00003850,
+ .framedrop_pattern = 0x00003854,
+ .frame_inc = 0x00003858,
+ .burst_limit = 0x0000385C,
+ .ubwc_regs = NULL,
+ },
+ /* BUS Client 23 */
+ {
+ .status0 = 0x00003900,
+ .status1 = 0x00003904,
+ .cfg = 0x00003908,
+ .header_addr = 0x0000390C,
+ .header_cfg = 0x00003910,
+ .image_addr = 0x00003914,
+ .image_addr_offset = 0x00003918,
+ .buffer_width_cfg = 0x0000391C,
+ .buffer_height_cfg = 0x00003920,
+ .packer_cfg = 0x00003924,
+ .stride = 0x00003928,
+ .irq_subsample_period = 0x00003948,
+ .irq_subsample_pattern = 0x0000394C,
+ .framedrop_period = 0x00003950,
+ .framedrop_pattern = 0x00003954,
+ .frame_inc = 0x00003958,
+ .burst_limit = 0x0000395C,
+ .ubwc_regs = NULL,
+ },
+ },
+ .comp_grp_reg = {
+ /* CAM_VFE_BUS_VER2_COMP_GRP_0 */
+ {
+ .comp_mask = 0x00002010,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_1 */
+ {
+ .comp_mask = 0x00002014,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_2 */
+ {
+ .comp_mask = 0x00002018,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_3 */
+ {
+ .comp_mask = 0x0000201C,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_4 */
+ {
+ .comp_mask = 0x00002020,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_5 */
+ {
+ .comp_mask = 0x00002024,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 */
+ {
+ .comp_mask = 0x0000202C,
+ .addr_sync_mask = 0x00002088,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1 */
+ {
+ .comp_mask = 0x00002030,
+ .addr_sync_mask = 0x0000208C,
+
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2 */
+ {
+ .comp_mask = 0x00002034,
+ .addr_sync_mask = 0x00002090,
+
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3 */
+ {
+ .comp_mask = 0x00002038,
+ .addr_sync_mask = 0x00002094,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4 */
+ {
+ .comp_mask = 0x0000203C,
+ .addr_sync_mask = 0x00002098,
+ },
+ /* CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 */
+ {
+ .comp_mask = 0x00002040,
+ .addr_sync_mask = 0x0000209C,
+ },
+ },
+ .num_out = 22,
+ .vfe_out_hw_info = {
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI0,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI1,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RDI2,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL,
+ .max_width = 4096,
+ .max_height = 4096,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FD,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_PDAF,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type =
+ CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST,
+ .max_width = -1,
+ .max_height = -1,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_FULL_DISP,
+ .max_width = 4096,
+ .max_height = 4096,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS4_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_DS16_DISP,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ {
+ .vfe_out_type = CAM_VFE_BUS_VER2_VFE_OUT_2PD,
+ .max_width = 1920,
+ .max_height = 1080,
+ },
+ },
+ .reg_data = {
+ .ubwc_10bit_threshold_lossy_0 = 0x8330002,
+ .ubwc_10bit_threshold_lossy_1 = 0x20204,
+ .ubwc_8bit_threshold_lossy_0 = 0x6210022,
+ .ubwc_8bit_threshold_lossy_1 = 0xE0E,
+ },
+};
+
+struct cam_vfe_hw_info cam_vfe175_130_hw_info = {
+ .irq_reg_info = &vfe175_130_top_irq_reg_info,
+
+ .bus_version = CAM_VFE_BUS_VER_2_0,
+ .bus_hw_info = &vfe175_130_bus_hw_info,
+
+ .bus_rd_version = CAM_VFE_BUS_VER_2_0,
+ .bus_rd_hw_info = &vfe175_130_bus_rd_hw_info,
+
+ .top_version = CAM_VFE_TOP_VER_2_0,
+ .top_hw_info = &vfe175_130_top_hw_info,
+
+ .camif_version = CAM_VFE_CAMIF_VER_2_0,
+ .camif_reg = &vfe175_130_camif_reg,
+
+ .camif_lite_version = CAM_VFE_CAMIF_LITE_VER_2_0,
+ .camif_lite_reg = &vfe175_130_camif_lite_reg,
+
+};
+
+#endif /* _CAM_VFE175_130_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
index 6ec5ffbde4e0..2e11dc40d5a3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe17x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,8 @@
#include <linux/module.h>
#include "cam_vfe170.h"
+#include "cam_vfe175.h"
+#include "cam_vfe175_130.h"
#include "cam_vfe_lite17x.h"
#include "cam_vfe_hw_intf.h"
#include "cam_vfe_core.h"
@@ -23,9 +25,21 @@ static const struct of_device_id cam_vfe_dt_match[] = {
.data = &cam_vfe170_hw_info,
},
{
+ .compatible = "qcom,vfe175",
+ .data = &cam_vfe175_hw_info,
+ },
+ {
+ .compatible = "qcom,vfe175_130",
+ .data = &cam_vfe175_130_hw_info,
+ },
+ {
.compatible = "qcom,vfe-lite170",
.data = &cam_vfe_lite17x_hw_info,
},
+ {
+ .compatible = "qcom,vfe-lite175",
+ .data = &cam_vfe_lite17x_hw_info,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cam_vfe_dt_match);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
index 1823497221ba..d8db0b56a0ee 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/Makefile
@@ -11,4 +11,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vf
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
-obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_bus.o cam_vfe_bus_ver2.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_bus.o cam_vfe_bus_ver2.o cam_vfe_bus_rd_ver1.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
index 4c0c147f4122..b0495922a90d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,9 +13,11 @@
#include "cam_vfe_bus.h"
#include "cam_vfe_bus_ver1.h"
#include "cam_vfe_bus_ver2.h"
+#include "cam_vfe_bus_rd_ver1.h"
#include "cam_debug_util.h"
int cam_vfe_bus_init(uint32_t bus_version,
+ int bus_type,
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
@@ -24,10 +26,16 @@ int cam_vfe_bus_init(uint32_t bus_version,
{
int rc = -ENODEV;
- switch (bus_version) {
- case CAM_VFE_BUS_VER_2_0:
- rc = cam_vfe_bus_ver2_init(soc_info, hw_intf, bus_hw_info,
- vfe_irq_controller, vfe_bus);
+ switch (bus_type) {
+ case BUS_TYPE_WR:
+ if (CAM_VFE_BUS_VER_2_0)
+ rc = cam_vfe_bus_ver2_init(soc_info, hw_intf,
+ bus_hw_info, vfe_irq_controller, vfe_bus);
+ break;
+ case BUS_TYPE_RD:
+ /* Call vfe bus rd init function */
+ rc = cam_vfe_bus_rd_ver1_init(soc_info, hw_intf,
+ bus_hw_info, vfe_irq_controller, vfe_bus);
break;
default:
CAM_ERR(CAM_ISP, "Unsupported Bus Version %x", bus_version);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
new file mode 100644
index 000000000000..00cc40158fd4
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c
@@ -0,0 +1,1232 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/ratelimit.h>
+#include <linux/slab.h>
+#include <uapi/media/cam_isp.h>
+#include "cam_io_util.h"
+#include "cam_debug_util.h"
+#include "cam_cdm_util.h"
+#include "cam_hw_intf.h"
+#include "cam_ife_hw_mgr.h"
+#include "cam_vfe_hw_intf.h"
+#include "cam_irq_controller.h"
+#include "cam_tasklet_util.h"
+#include "cam_vfe_bus.h"
+#include "cam_vfe_bus_rd_ver1.h"
+#include "cam_vfe_core.h"
+#include "cam_debug_util.h"
+#include "cam_cpas_api.h"
+
+static const char drv_name[] = "vfe_bus_rd";
+
+#define ALIGNUP(value, alignment) \
+ ((value + alignment - 1) / alignment * alignment)
+
+#define MAX_BUF_UPDATE_REG_NUM \
+ (sizeof(struct cam_vfe_bus_rd_ver1_reg_offset_bus_client)/4)
+
+#define MAX_REG_VAL_PAIR_SIZE \
+ (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
+
+#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
+ do { \
+ buf_array[(index)++] = offset; \
+ buf_array[(index)++] = val; \
+ } while (0)
+
+enum cam_vfe_bus_rd_ver1_unpacker_format {
+ BUS_RD_VER1_PACKER_FMT_PLAIN_128 = 0x0,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8 = 0x1,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_10BPP = 0x2,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_12BPP = 0x3,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_14BPP = 0x4,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_16_16BPP = 0x5,
+ BUS_RD_VER1_PACKER_FMT_ARGB_10 = 0x6,
+ BUS_RD_VER1_PACKER_FMT_ARGB_12 = 0x7,
+ BUS_RD_VER1_PACKER_FMT_ARGB_14 = 0x8,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_32_20BPP = 0x9,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_64 = 0xA,
+ BUS_RD_VER1_PACKER_FMT_TP_10 = 0xB,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_32_32BPP = 0xC,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
+ BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
+ BUS_RD_VER1_PACKER_FMT_MAX = 0xF,
+};
+
+struct cam_vfe_bus_rd_ver1_common_data {
+ uint32_t core_index;
+ void __iomem *mem_base;
+ struct cam_hw_intf *hw_intf;
+ void *bus_irq_controller;
+ void *vfe_irq_controller;
+ struct cam_vfe_bus_rd_ver1_reg_offset_common *common_reg;
+ uint32_t io_buf_update[
+ MAX_REG_VAL_PAIR_SIZE];
+
+ struct list_head free_payload_list;
+ spinlock_t spin_lock;
+ struct mutex bus_mutex;
+ uint32_t secure_mode;
+ uint32_t num_sec_out;
+ uint32_t fs_sync_enable;
+ uint32_t go_cmd_sel;
+};
+
+struct cam_vfe_bus_rd_ver1_rm_resource_data {
+ uint32_t index;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data;
+ struct cam_vfe_bus_rd_ver1_reg_offset_bus_client *hw_regs;
+ void *ctx;
+
+ uint32_t irq_enabled;
+ uint32_t offset;
+
+ uint32_t min_vbi;
+ uint32_t fs_mode;
+ uint32_t hbi_count;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ uint32_t latency_buf_allocation;
+ uint32_t unpacker_cfg;
+ uint32_t burst_len;
+
+ uint32_t go_cmd_sel;
+ uint32_t fs_sync_enable;
+ uint32_t fs_line_sync_en;
+
+ uint32_t en_cfg;
+ uint32_t is_dual;
+ uint32_t img_addr;
+ uint32_t input_if_cmd;
+};
+
+struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data {
+ uint32_t bus_rd_type;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data;
+
+ uint32_t num_rm;
+ struct cam_isp_resource_node *rm_res[PLANE_MAX];
+
+ struct cam_isp_resource_node *comp_grp;
+ enum cam_isp_hw_sync_mode dual_comp_sync_mode;
+ uint32_t dual_hw_alternate_vfe_id;
+ struct list_head vfe_bus_rd_list;
+
+ uint32_t format;
+ uint32_t max_width;
+ uint32_t max_height;
+ struct cam_cdm_utils_ops *cdm_util_ops;
+ uint32_t secure_mode;
+};
+
+struct cam_vfe_bus_rd_ver1_priv {
+ struct cam_vfe_bus_rd_ver1_common_data common_data;
+ uint32_t num_client;
+ uint32_t num_bus_rd_resc;
+
+ struct cam_isp_resource_node bus_client[
+ CAM_VFE_BUS_RD_VER1_MAX_CLIENTS];
+ struct cam_isp_resource_node vfe_bus_rd[
+ CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+
+ uint32_t irq_handle;
+ uint32_t error_irq_handle;
+};
+
+static int cam_vfe_bus_process_cmd(
+ struct cam_isp_resource_node *priv,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size);
+
+static enum cam_vfe_bus_rd_ver1_unpacker_format
+ cam_vfe_bus_get_unpacker_fmt(uint32_t unpack_fmt)
+{
+ switch (unpack_fmt) {
+ case CAM_FORMAT_MIPI_RAW_10:
+ return BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN;
+ default:
+ return BUS_RD_VER1_PACKER_FMT_MAX;
+ }
+}
+
+static bool cam_vfe_bus_can_be_secure(uint32_t out_type)
+{
+ switch (out_type) {
+ case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+static enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type
+ cam_vfe_bus_get_bus_rd_res_id(uint32_t res_type)
+{
+ switch (res_type) {
+ case CAM_ISP_RESOURCE_VFE_BUS_RD:
+ return CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0;
+ default:
+ return CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX;
+ }
+}
+
+static int cam_vfe_bus_get_num_rm(
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type res_type)
+{
+ switch (res_type) {
+ case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+ return 1;
+ default:
+ break;
+ }
+
+ CAM_ERR(CAM_ISP, "Unsupported resource_type %u",
+ res_type);
+ return -EINVAL;
+}
+
+static int cam_vfe_bus_get_rm_idx(
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id,
+ enum cam_vfe_bus_plane_type plane)
+{
+ int rm_idx = -1;
+
+ switch (vfe_bus_rd_res_id) {
+ case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0:
+ switch (plane) {
+ case PLANE_Y:
+ rm_idx = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rm_idx;
+}
+
+static int cam_vfe_bus_acquire_rm(
+ struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv,
+ struct cam_isp_out_port_info *out_port_info,
+ void *tasklet,
+ void *ctx,
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id,
+ enum cam_vfe_bus_plane_type plane,
+ uint32_t subscribe_irq,
+ struct cam_isp_resource_node **rm_res,
+ uint32_t *client_done_mask,
+ uint32_t is_dual)
+{
+ uint32_t rm_idx = 0;
+ struct cam_isp_resource_node *rm_res_local = NULL;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data = NULL;
+
+ *rm_res = NULL;
+ *client_done_mask = 0;
+
+ /* No need to allocate for BUS VER2. VFE OUT to RM is fixed. */
+ rm_idx = cam_vfe_bus_get_rm_idx(vfe_bus_rd_res_id, plane);
+ if (rm_idx < 0 || rm_idx >= ver1_bus_rd_priv->num_client) {
+ CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d",
+ vfe_bus_rd_res_id, plane);
+ return -EINVAL;
+ }
+
+ rm_res_local = &ver1_bus_rd_priv->bus_client[rm_idx];
+ if (rm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_ERR(CAM_ISP, "RM res not available state:%d",
+ rm_res_local->res_state);
+ return -EALREADY;
+ }
+ rm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ rm_res_local->tasklet_info = tasklet;
+
+ rsrc_data = rm_res_local->res_priv;
+ rsrc_data->irq_enabled = subscribe_irq;
+ rsrc_data->ctx = ctx;
+ rsrc_data->is_dual = is_dual;
+ /* Set RM offset value to default */
+ rsrc_data->offset = 0;
+
+ *client_done_mask = (1 << rm_idx);
+ *rm_res = rm_res_local;
+
+ CAM_DBG(CAM_ISP, "RM %d: Acquired");
+ return 0;
+}
+
+static int cam_vfe_bus_release_rm(void *bus_priv,
+ struct cam_isp_resource_node *rm_res)
+{
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data =
+ rm_res->res_priv;
+
+ rsrc_data->irq_enabled = 0;
+ rsrc_data->offset = 0;
+ rsrc_data->width = 0;
+ rsrc_data->height = 0;
+ rsrc_data->stride = 0;
+ rsrc_data->format = 0;
+ rsrc_data->unpacker_cfg = 0;
+ rsrc_data->burst_len = 0;
+ rsrc_data->en_cfg = 0;
+ rsrc_data->is_dual = 0;
+
+ rm_res->tasklet_info = NULL;
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+
+ return 0;
+}
+
+static int cam_vfe_bus_start_rm(struct cam_isp_resource_node *rm_res)
+{
+ int rc = 0;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data =
+ rm_res->res_priv;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data =
+ rm_data->common_data;
+ uint32_t buf_size;
+ uint32_t val;
+ uint32_t offset;
+
+ CAM_DBG(CAM_ISP, "w: 0x%x", rm_data->width);
+ CAM_DBG(CAM_ISP, "h: 0x%x", rm_data->height);
+ CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format);
+ CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg);
+ CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x",
+ rm_data->latency_buf_allocation);
+ CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride);
+ CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel);
+ CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x", rm_data->fs_sync_enable);
+ CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count);
+ CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x", rm_data->fs_line_sync_en);
+ CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode);
+ CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi);
+
+ /* Write All the values*/
+ offset = rm_data->hw_regs->buffer_width_cfg;
+ buf_size = ((rm_data->width)&(0x0000FFFF)) |
+ ((rm_data->height<<16)&(0xFFFF0000));
+ cam_io_w_mb(buf_size, common_data->mem_base + offset);
+ CAM_DBG(CAM_ISP, "buf_size: 0x%x", buf_size);
+
+ val = rm_data->width;
+ offset = rm_data->hw_regs->stride;
+ CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+ cam_io_w_mb(val, common_data->mem_base + offset);
+
+ CAM_DBG(CAM_ISP, "rm_data->unpacker_cfg:0x%x", rm_data->unpacker_cfg);
+ val = cam_vfe_bus_get_unpacker_fmt(rm_data->unpacker_cfg);
+ CAM_DBG(CAM_ISP, " value:0x%x", val);
+ offset = rm_data->hw_regs->unpacker_cfg;
+ CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+ cam_io_w_mb(val, common_data->mem_base + offset);
+
+ val = rm_data->latency_buf_allocation;
+ offset = rm_data->hw_regs->latency_buf_allocation;
+ CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val);
+ cam_io_w_mb(val, common_data->mem_base + offset);
+
+ cam_io_w_mb(0x1, common_data->mem_base +
+ rm_data->hw_regs->cfg);
+ return rc;
+}
+
+static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res)
+{
+ int rc = 0;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data =
+ rm_res->res_priv;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data =
+ rsrc_data->common_data;
+
+ /* Disable RM */
+ cam_io_w_mb(0x0,
+ common_data->mem_base + rsrc_data->hw_regs->cfg);
+
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+
+ return rc;
+}
+
+static int cam_vfe_bus_init_rm_resource(uint32_t index,
+ struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv,
+ struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info,
+ struct cam_isp_resource_node *rm_res)
+{
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data;
+
+ rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_rm_resource_data),
+ GFP_KERNEL);
+ if (!rsrc_data) {
+ CAM_DBG(CAM_ISP, "Failed to alloc for RM res priv");
+ return -ENOMEM;
+ }
+ rm_res->res_priv = rsrc_data;
+
+ rsrc_data->index = index;
+ rsrc_data->hw_regs = &bus_rd_hw_info->bus_client_reg[index];
+ rsrc_data->common_data = &ver1_bus_rd_priv->common_data;
+
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+ INIT_LIST_HEAD(&rm_res->list);
+
+ rm_res->start = cam_vfe_bus_start_rm;
+ rm_res->stop = cam_vfe_bus_stop_rm;
+ rm_res->hw_intf = ver1_bus_rd_priv->common_data.hw_intf;
+
+
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_rm_resource(
+ struct cam_isp_resource_node *rm_res)
+{
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data;
+
+ rm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+ INIT_LIST_HEAD(&rm_res->list);
+
+ rm_res->start = NULL;
+ rm_res->stop = NULL;
+ rm_res->top_half_handler = NULL;
+ rm_res->bottom_half_handler = NULL;
+ rm_res->hw_intf = NULL;
+
+ rsrc_data = rm_res->res_priv;
+ rm_res->res_priv = NULL;
+ if (!rsrc_data)
+ return -ENOMEM;
+ kfree(rsrc_data);
+
+ return 0;
+}
+
+static int cam_vfe_bus_rd_get_secure_mode(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ return 0;
+}
+
+static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args,
+ uint32_t args_size)
+{
+ int rc = -ENODEV;
+ int i;
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type bus_rd_res_id;
+ int num_rm;
+ uint32_t subscribe_irq;
+ uint32_t client_done_mask;
+ struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv =
+ bus_priv;
+ struct cam_vfe_acquire_args *acq_args = acquire_args;
+ struct cam_vfe_hw_vfe_out_acquire_args *bus_rd_acquire_args;
+ struct cam_isp_resource_node *rsrc_node = NULL;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ uint32_t secure_caps = 0, mode;
+
+ if (!bus_priv || !acquire_args) {
+ CAM_ERR(CAM_ISP, "Invalid Param");
+ return -EINVAL;
+ }
+
+ bus_rd_acquire_args = &acq_args->vfe_bus_rd;
+
+ CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
+ acq_args->rsrc_type);
+
+ bus_rd_res_id = cam_vfe_bus_get_bus_rd_res_id(
+ acq_args->rsrc_type);
+ if (bus_rd_res_id == CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX)
+ return -ENODEV;
+
+ num_rm = cam_vfe_bus_get_num_rm(bus_rd_res_id);
+ if (num_rm < 1)
+ return -EINVAL;
+
+ rsrc_node = &ver1_bus_rd_priv->vfe_bus_rd[bus_rd_res_id];
+ if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
+ bus_rd_res_id, rsrc_node->res_state);
+ return -EBUSY;
+ }
+
+ rsrc_data = rsrc_node->res_priv;
+ secure_caps = cam_vfe_bus_can_be_secure(
+ rsrc_data->bus_rd_type);
+
+ mode = bus_rd_acquire_args->out_port_info->secure_mode;
+ mutex_lock(&rsrc_data->common_data->bus_mutex);
+ if (secure_caps) {
+ if (!rsrc_data->common_data->num_sec_out) {
+ rsrc_data->secure_mode = mode;
+ rsrc_data->common_data->secure_mode = mode;
+ } else {
+ if (mode == rsrc_data->common_data->secure_mode) {
+ rsrc_data->secure_mode =
+ rsrc_data->common_data->secure_mode;
+ } else {
+ rc = -EINVAL;
+ CAM_ERR_RATE_LIMIT(CAM_ISP,
+ "Mismatch: Acquire mode[%d], drvr mode[%d]",
+ rsrc_data->common_data->secure_mode,
+ mode);
+ mutex_unlock(
+ &rsrc_data->common_data->bus_mutex);
+ return -EINVAL;
+ }
+ }
+ rsrc_data->common_data->num_sec_out++;
+ }
+ mutex_unlock(&rsrc_data->common_data->bus_mutex);
+
+ rsrc_data->num_rm = num_rm;
+ rsrc_node->tasklet_info = acq_args->tasklet;
+ rsrc_node->cdm_ops = bus_rd_acquire_args->cdm_ops;
+ rsrc_data->cdm_util_ops = bus_rd_acquire_args->cdm_ops;
+
+ subscribe_irq = 1;
+
+ for (i = 0; i < num_rm; i++) {
+ rc = cam_vfe_bus_acquire_rm(ver1_bus_rd_priv,
+ bus_rd_acquire_args->out_port_info,
+ acq_args->tasklet,
+ bus_rd_acquire_args->ctx,
+ bus_rd_res_id,
+ i,
+ subscribe_irq,
+ &rsrc_data->rm_res[i],
+ &client_done_mask,
+ bus_rd_acquire_args->is_dual);
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "VFE%d RM acquire failed for Out %d rc=%d",
+ rsrc_data->common_data->core_index,
+ bus_rd_res_id, rc);
+ goto release_rm;
+ }
+ }
+
+ rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ bus_rd_acquire_args->rsrc_node = rsrc_node;
+
+ CAM_DBG(CAM_ISP, "Acquire successful");
+ return rc;
+
+release_rm:
+ for (i--; i >= 0; i--)
+ cam_vfe_bus_release_rm(ver1_bus_rd_priv, rsrc_data->rm_res[i]);
+ return rc;
+}
+
+static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args,
+ uint32_t args_size)
+{
+ uint32_t i;
+ struct cam_isp_resource_node *vfe_bus_rd = NULL;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ uint32_t secure_caps = 0;
+
+ if (!bus_priv || !release_args) {
+ CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
+ bus_priv, release_args);
+ return -EINVAL;
+ }
+
+ vfe_bus_rd = release_args;
+ rsrc_data = vfe_bus_rd->res_priv;
+
+ if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_ERR(CAM_ISP, "Invalid resource state:%d",
+ vfe_bus_rd->res_state);
+ }
+
+ for (i = 0; i < rsrc_data->num_rm; i++)
+ cam_vfe_bus_release_rm(bus_priv, rsrc_data->rm_res[i]);
+ rsrc_data->num_rm = 0;
+
+ vfe_bus_rd->tasklet_info = NULL;
+ vfe_bus_rd->cdm_ops = NULL;
+ rsrc_data->cdm_util_ops = NULL;
+
+ secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->bus_rd_type);
+ mutex_lock(&rsrc_data->common_data->bus_mutex);
+ if (secure_caps) {
+ if (rsrc_data->secure_mode ==
+ rsrc_data->common_data->secure_mode) {
+ rsrc_data->common_data->num_sec_out--;
+ rsrc_data->secure_mode =
+ CAM_SECURE_MODE_NON_SECURE;
+ } else {
+ /*
+ * The validity of the mode is properly
+ * checked while acquiring the output port.
+ * not expected to reach here, unless there is
+ * some corruption.
+ */
+ CAM_ERR(CAM_ISP, "driver[%d],resource[%d] mismatch",
+ rsrc_data->common_data->secure_mode,
+ rsrc_data->secure_mode);
+ }
+
+ if (!rsrc_data->common_data->num_sec_out)
+ rsrc_data->common_data->secure_mode =
+ CAM_SECURE_MODE_NON_SECURE;
+ }
+ mutex_unlock(&rsrc_data->common_data->bus_mutex);
+
+ if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
+ vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+
+ return 0;
+}
+
+static int cam_vfe_bus_start_vfe_bus_rd(
+ struct cam_isp_resource_node *vfe_out)
+{
+ int rc = 0, i;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data = NULL;
+
+ if (!vfe_out) {
+ CAM_ERR(CAM_ISP, "Invalid input");
+ return -EINVAL;
+ }
+
+ rsrc_data = vfe_out->res_priv;
+ common_data = rsrc_data->common_data;
+
+ CAM_DBG(CAM_ISP, "Start resource type: %x", rsrc_data->bus_rd_type);
+
+ if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_ERR(CAM_ISP, "Invalid resource state:%d",
+ vfe_out->res_state);
+ return -EACCES;
+ }
+
+ for (i = 0; i < rsrc_data->num_rm; i++)
+ rc = cam_vfe_bus_start_rm(rsrc_data->rm_res[i]);
+ vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+ return rc;
+}
+
+static int cam_vfe_bus_stop_vfe_bus_rd(
+ struct cam_isp_resource_node *vfe_bus_rd)
+{
+ int rc = 0, i;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+
+ CAM_DBG(CAM_ISP, "E:Stop rd Res");
+ if (!vfe_bus_rd) {
+ CAM_ERR(CAM_ISP, "Invalid input");
+ return -EINVAL;
+ }
+
+ rsrc_data = vfe_bus_rd->res_priv;
+
+ if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
+ vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_DBG(CAM_ISP, "vfe_out res_state is %d",
+ vfe_bus_rd->res_state);
+ return rc;
+ }
+ for (i = 0; i < rsrc_data->num_rm; i++)
+ rc = cam_vfe_bus_stop_rm(rsrc_data->rm_res[i]);
+
+ vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+ return rc;
+}
+
+static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t index,
+ struct cam_vfe_bus_rd_ver1_priv *bus_rd_priv,
+ struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info)
+{
+ struct cam_isp_resource_node *vfe_bus_rd = NULL;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL;
+ int rc = 0;
+ int32_t vfe_bus_rd_resc_type =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type;
+
+ if (vfe_bus_rd_resc_type < 0 ||
+ vfe_bus_rd_resc_type > CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0) {
+ CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d",
+ vfe_bus_rd_resc_type);
+ return -EINVAL;
+ }
+
+ vfe_bus_rd = &bus_rd_priv->vfe_bus_rd[vfe_bus_rd_resc_type];
+ if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_UNAVAILABLE ||
+ vfe_bus_rd->res_priv) {
+ CAM_ERR(CAM_ISP,
+ "Error. Looks like same resource is init again");
+ return -EFAULT;
+ }
+
+ rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data),
+ GFP_KERNEL);
+ if (!rsrc_data) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ vfe_bus_rd->res_priv = rsrc_data;
+
+ vfe_bus_rd->res_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
+ vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+ INIT_LIST_HEAD(&vfe_bus_rd->list);
+
+ rsrc_data->bus_rd_type =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type;
+ rsrc_data->common_data = &bus_rd_priv->common_data;
+ rsrc_data->max_width =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].max_width;
+ rsrc_data->max_height =
+ bus_rd_hw_info->vfe_bus_rd_hw_info[index].max_height;
+ rsrc_data->secure_mode = CAM_SECURE_MODE_NON_SECURE;
+
+ vfe_bus_rd->start = cam_vfe_bus_start_vfe_bus_rd;
+ vfe_bus_rd->stop = cam_vfe_bus_stop_vfe_bus_rd;
+ vfe_bus_rd->process_cmd = cam_vfe_bus_process_cmd;
+ vfe_bus_rd->hw_intf = bus_rd_priv->common_data.hw_intf;
+
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_vfe_bus_rd_resource(
+ struct cam_isp_resource_node *vfe_bus_rd_res)
+{
+ struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data =
+ vfe_bus_rd_res->res_priv;
+
+ if (vfe_bus_rd_res->res_state == CAM_ISP_RESOURCE_STATE_UNAVAILABLE) {
+ /*
+ * This is not error. It can happen if the resource is
+ * never supported in the HW.
+ */
+ CAM_DBG(CAM_ISP, "HW%d Res %d already deinitialized");
+ return 0;
+ }
+
+ vfe_bus_rd_res->start = NULL;
+ vfe_bus_rd_res->stop = NULL;
+ vfe_bus_rd_res->top_half_handler = NULL;
+ vfe_bus_rd_res->bottom_half_handler = NULL;
+ vfe_bus_rd_res->hw_intf = NULL;
+
+ vfe_bus_rd_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
+ INIT_LIST_HEAD(&vfe_bus_rd_res->list);
+ vfe_bus_rd_res->res_priv = NULL;
+
+ if (!rsrc_data)
+ return -ENOMEM;
+ kfree(rsrc_data);
+
+ return 0;
+}
+
+static int cam_vfe_bus_rd_ver1_handle_irq(uint32_t evt_id,
+ struct cam_irq_th_payload *th_payload)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv;
+
+ bus_priv = th_payload->handler_priv;
+ CAM_DBG(CAM_ISP, "BUS READ IRQ Received");
+ return 0;
+}
+
+static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv;
+ struct cam_isp_hw_get_cmd_update *update_buf;
+ struct cam_buf_io_cfg *io_cfg;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *vfe_bus_rd_data = NULL;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL;
+ uint32_t *reg_val_pair;
+ uint32_t i, j, size = 0;
+ uint32_t val;
+ uint32_t buf_size = 0;
+
+ bus_priv = (struct cam_vfe_bus_rd_ver1_priv *) priv;
+ update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args;
+
+ vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
+ update_buf->res->res_priv;
+
+ if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
+ CAM_ERR(CAM_ISP, "Failed! Invalid data");
+ return -EINVAL;
+ }
+
+ CAM_DBG(CAM_ISP, "#of RM: %d", vfe_bus_rd_data->num_rm);
+ if (update_buf->rm_update->num_buf != vfe_bus_rd_data->num_rm) {
+ CAM_ERR(CAM_ISP,
+ "Failed! Invalid number buffers:%d required:%d",
+ update_buf->rm_update->num_buf,
+ vfe_bus_rd_data->num_rm);
+ return -EINVAL;
+ }
+
+ reg_val_pair = &vfe_bus_rd_data->common_data->io_buf_update[0];
+ io_cfg = update_buf->rm_update->io_cfg;
+
+ for (i = 0, j = 0; i < vfe_bus_rd_data->num_rm; i++) {
+ if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
+ CAM_ERR(CAM_ISP,
+ "reg_val_pair %d exceeds the array limit %lu",
+ j, MAX_REG_VAL_PAIR_SIZE);
+ return -ENOMEM;
+ }
+
+ rm_data = vfe_bus_rd_data->rm_res[i]->res_priv;
+
+ /* update size register */
+ rm_data->width = io_cfg->planes[i].width;
+ rm_data->height = io_cfg->planes[i].height;
+ CAM_DBG(CAM_ISP, "RM %d image w 0x%x h 0x%x image size 0x%x",
+ rm_data->index, rm_data->width, rm_data->height,
+ buf_size);
+
+ buf_size = ((rm_data->width)&(0x0000FFFF)) |
+ ((rm_data->height<<16)&(0xFFFF0000));
+
+ CAM_DBG(CAM_ISP, "size offset 0x%x buf_size 0x%x",
+ rm_data->hw_regs->buf_size, buf_size);
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ rm_data->hw_regs->buffer_width_cfg,
+ buf_size);
+ CAM_DBG(CAM_ISP, "RM %d image size 0x%x",
+ rm_data->index, reg_val_pair[j-1]);
+
+ val = rm_data->width;
+ CAM_DBG(CAM_ISP, "io_cfg stride 0x%x", val);
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ rm_data->hw_regs->stride,
+ val);
+ rm_data->stride = val;
+ CAM_DBG(CAM_ISP, "RM %d image stride 0x%x",
+ rm_data->index, reg_val_pair[j-1]);
+
+ /* RM Image address */
+ CAM_DBG(CAM_ISP, "image_addr offset %x",
+ rm_data->hw_regs->image_addr);
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ rm_data->hw_regs->image_addr,
+ update_buf->rm_update->image_buf[i] +
+ rm_data->offset);
+ CAM_DBG(CAM_ISP, "RM %d image address 0x%x",
+ rm_data->index, reg_val_pair[j-1]);
+ rm_data->img_addr = reg_val_pair[j-1];
+
+ }
+
+ size = vfe_bus_rd_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
+
+ /* cdm util returns dwords, need to convert to bytes */
+ if ((size * 4) > update_buf->cmd.size) {
+ CAM_ERR(CAM_ISP,
+ "Failed! Buf size:%d insufficient, expected size:%d",
+ update_buf->cmd.size, size);
+ return -ENOMEM;
+ }
+
+ vfe_bus_rd_data->cdm_util_ops->cdm_write_regrandom(
+ update_buf->cmd.cmd_buf_addr, j/2, reg_val_pair);
+
+ /* cdm util returns dwords, need to convert to bytes */
+ update_buf->cmd.used_bytes = size * 4;
+
+ return 0;
+}
+
+static int cam_vfe_bus_rd_update_hfr(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ return 0;
+}
+
+static int cam_vfe_bus_rd_update_fs_cfg(void *priv, void *cmd_args,
+ uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *vfe_bus_rd_data = NULL;
+ struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL;
+ struct cam_vfe_fe_update_args *fe_upd_args;
+ struct cam_fe_config *fe_cfg;
+ struct cam_vfe_bus_rd_ver1_common_data *common_data;
+ int i = 0;
+
+ bus_priv = (struct cam_vfe_bus_rd_ver1_priv *) priv;
+ fe_upd_args = (struct cam_vfe_fe_update_args *)cmd_args;
+
+ vfe_bus_rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *)
+ fe_upd_args->node_res->res_priv;
+
+ if (!vfe_bus_rd_data || !vfe_bus_rd_data->cdm_util_ops) {
+ CAM_ERR(CAM_ISP, "Failed! Invalid data");
+ return -EINVAL;
+ }
+
+ fe_cfg = &fe_upd_args->fe_config;
+
+ for (i = 0; i < vfe_bus_rd_data->num_rm; i++) {
+
+ rm_data = vfe_bus_rd_data->rm_res[i]->res_priv;
+ common_data = rm_data->common_data;
+
+ rm_data->format = fe_cfg->format;
+ CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format);
+
+ rm_data->unpacker_cfg = fe_cfg->unpacker_cfg;
+ CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg);
+
+ rm_data->latency_buf_allocation = fe_cfg->latency_buf_size;
+ CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x",
+ rm_data->latency_buf_allocation);
+
+ rm_data->stride = fe_cfg->stride;
+ CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride);
+
+ rm_data->go_cmd_sel = fe_cfg->go_cmd_sel;
+ CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel);
+
+ rm_data->fs_sync_enable = fe_cfg->fs_sync_enable;
+ CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x",
+ rm_data->fs_sync_enable);
+
+ rm_data->hbi_count = fe_cfg->hbi_count;
+ CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count);
+
+ rm_data->fs_line_sync_en = fe_cfg->fs_line_sync_en;
+ CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x",
+ rm_data->fs_line_sync_en);
+
+ rm_data->fs_mode = fe_cfg->fs_mode;
+ CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode);
+
+ rm_data->min_vbi = fe_cfg->min_vbi;
+ CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi);
+ }
+ bus_priv->common_data.fs_sync_enable = fe_cfg->fs_sync_enable;
+ bus_priv->common_data.go_cmd_sel = fe_cfg->go_cmd_sel;
+ return 0;
+}
+
+static int cam_vfe_bus_start_hw(void *hw_priv,
+ void *start_hw_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_start_vfe_bus_rd(hw_priv);
+}
+
+static int cam_vfe_bus_stop_hw(void *hw_priv,
+ void *stop_hw_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_stop_vfe_bus_rd(hw_priv);
+}
+
+static int cam_vfe_bus_init_hw(void *hw_priv,
+ void *init_hw_args, uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = hw_priv;
+ uint32_t top_irq_reg_mask[2] = {0};
+ uint32_t offset = 0, val = 0;
+ struct cam_vfe_bus_rd_ver1_reg_offset_common *common_reg;
+
+ if (!bus_priv) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return -EINVAL;
+ }
+ common_reg = bus_priv->common_data.common_reg;
+ top_irq_reg_mask[0] = (1 << 23);
+
+ bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
+ bus_priv->common_data.vfe_irq_controller,
+ CAM_IRQ_PRIORITY_2,
+ top_irq_reg_mask,
+ bus_priv,
+ cam_vfe_bus_rd_ver1_handle_irq,
+ NULL,
+ NULL,
+ NULL);
+
+ if (bus_priv->irq_handle <= 0) {
+ CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
+ return -EFAULT;
+ }
+ /* no clock gating at bus input */
+ offset = common_reg->cgc_ovd;
+ cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
+
+ /* BUS_RD_TEST_BUS_CTRL */
+ offset = common_reg->test_bus_ctrl;
+ cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset);
+
+ /* Read irq mask */
+ offset = common_reg->irq_reg_info.irq_reg_set->mask_reg_offset;
+ cam_io_w_mb(0x5, bus_priv->common_data.mem_base + offset);
+
+ /* INPUT_IF_CMD */
+ val = (bus_priv->common_data.fs_sync_enable << 5) |
+ (bus_priv->common_data.go_cmd_sel << 4);
+ offset = common_reg->input_if_cmd;
+ cam_io_w_mb(val, bus_priv->common_data.mem_base + offset);
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_hw(void *hw_priv,
+ void *deinit_hw_args, uint32_t arg_size)
+{
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = hw_priv;
+ int rc = 0;
+
+ if (!bus_priv) {
+ CAM_ERR(CAM_ISP, "Error: Invalid args");
+ return -EINVAL;
+ }
+
+ if (bus_priv->error_irq_handle) {
+ rc = cam_irq_controller_unsubscribe_irq(
+ bus_priv->common_data.bus_irq_controller,
+ bus_priv->error_irq_handle);
+ if (rc)
+ CAM_ERR(CAM_ISP,
+ "Failed to unsubscribe error irq rc=%d", rc);
+
+ bus_priv->error_irq_handle = 0;
+ }
+
+ if (bus_priv->irq_handle) {
+ rc = cam_irq_controller_unsubscribe_irq(
+ bus_priv->common_data.vfe_irq_controller,
+ bus_priv->irq_handle);
+ if (rc)
+ CAM_ERR(CAM_ISP,
+ "Failed to unsubscribe irq rc=%d", rc);
+
+ bus_priv->irq_handle = 0;
+ }
+
+ return rc;
+}
+
+static int __cam_vfe_bus_process_cmd(void *priv,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_process_cmd(priv, cmd_type, cmd_args, arg_size);
+}
+
+static int cam_vfe_bus_process_cmd(
+ struct cam_isp_resource_node *priv,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+ int rc = -EINVAL;
+
+ if (!priv || !cmd_args) {
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid input arguments");
+ return -EINVAL;
+ }
+
+ switch (cmd_type) {
+ case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+ rc = cam_vfe_bus_rd_update_rm(priv, cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
+ rc = cam_vfe_bus_rd_update_hfr(priv, cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_GET_SECURE_MODE:
+ rc = cam_vfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+ rc = cam_vfe_bus_rd_update_fs_cfg(priv, cmd_args, arg_size);
+ break;
+ default:
+ CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d",
+ cmd_type);
+ break;
+ }
+
+ return rc;
+}
+
+int cam_vfe_bus_rd_ver1_init(
+ struct cam_hw_soc_info *soc_info,
+ struct cam_hw_intf *hw_intf,
+ void *bus_hw_info,
+ void *vfe_irq_controller,
+ struct cam_vfe_bus **vfe_bus)
+{
+ int i, rc = 0;
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = NULL;
+ struct cam_vfe_bus *vfe_bus_local;
+ struct cam_vfe_bus_rd_ver1_hw_info *bus_rd_hw_info = bus_hw_info;
+
+ if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
+ CAM_ERR(CAM_ISP,
+ "Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
+ soc_info, hw_intf, bus_rd_hw_info);
+ CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
+ if (!vfe_bus_local) {
+ CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ bus_priv = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_priv),
+ GFP_KERNEL);
+ if (!bus_priv) {
+ CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
+ rc = -ENOMEM;
+ goto free_bus_local;
+ }
+
+ vfe_bus_local->bus_priv = bus_priv;
+
+ bus_priv->num_client = bus_rd_hw_info->num_client;
+ bus_priv->num_bus_rd_resc =
+ bus_rd_hw_info->num_bus_rd_resc;
+ bus_priv->common_data.num_sec_out = 0;
+ bus_priv->common_data.secure_mode = CAM_SECURE_MODE_NON_SECURE;
+ bus_priv->common_data.core_index = soc_info->index;
+ bus_priv->common_data.mem_base =
+ CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
+ bus_priv->common_data.hw_intf = hw_intf;
+ bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
+ bus_priv->common_data.common_reg = &bus_rd_hw_info->common_reg;
+
+ mutex_init(&bus_priv->common_data.bus_mutex);
+
+ rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
+ &bus_rd_hw_info->common_reg.irq_reg_info,
+ &bus_priv->common_data.bus_irq_controller);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "cam_irq_controller_init failed");
+ goto free_bus_priv;
+ }
+
+ for (i = 0; i < bus_priv->num_client; i++) {
+ rc = cam_vfe_bus_init_rm_resource(i, bus_priv, bus_hw_info,
+ &bus_priv->bus_client[i]);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "Init RM failed rc=%d", rc);
+ goto deinit_rm;
+ }
+ }
+
+ for (i = 0; i < bus_priv->num_bus_rd_resc; i++) {
+ rc = cam_vfe_bus_init_vfe_bus_read_resource(i, bus_priv,
+ bus_rd_hw_info);
+ if (rc < 0) {
+ CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
+ goto deinit_vfe_bus_rd;
+ }
+ }
+
+ spin_lock_init(&bus_priv->common_data.spin_lock);
+
+ vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_bus_rd;
+ vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_bus_rd;
+ vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
+ vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
+ vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
+ vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
+ vfe_bus_local->top_half_handler = cam_vfe_bus_rd_ver1_handle_irq;
+ vfe_bus_local->bottom_half_handler = NULL;
+ vfe_bus_local->hw_ops.process_cmd = __cam_vfe_bus_process_cmd;
+
+ *vfe_bus = vfe_bus_local;
+
+ return rc;
+
+deinit_vfe_bus_rd:
+ if (i < 0)
+ i = CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX;
+ for (--i; i >= 0; i--)
+ cam_vfe_bus_deinit_vfe_bus_rd_resource(
+ &bus_priv->vfe_bus_rd[i]);
+deinit_rm:
+ if (i < 0)
+ i = bus_priv->num_client;
+ for (--i; i >= 0; i--)
+ cam_vfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
+
+free_bus_priv:
+ kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+ kfree(vfe_bus_local);
+
+end:
+ return rc;
+}
+
+int cam_vfe_bus_rd_bus_ver1_deinit(
+ struct cam_vfe_bus **vfe_bus)
+{
+ int i, rc = 0;
+ struct cam_vfe_bus_rd_ver1_priv *bus_priv = NULL;
+ struct cam_vfe_bus *vfe_bus_local;
+
+ if (!vfe_bus || !*vfe_bus) {
+ CAM_ERR(CAM_ISP, "Invalid input");
+ return -EINVAL;
+ }
+ vfe_bus_local = *vfe_bus;
+
+ bus_priv = vfe_bus_local->bus_priv;
+ if (!bus_priv) {
+ CAM_ERR(CAM_ISP, "bus_priv is NULL");
+ rc = -ENODEV;
+ goto free_bus_local;
+ }
+
+ for (i = 0; i < bus_priv->num_client; i++) {
+ rc = cam_vfe_bus_deinit_rm_resource(&bus_priv->bus_client[i]);
+ if (rc < 0)
+ CAM_ERR(CAM_ISP,
+ "Deinit RM failed rc=%d", rc);
+ }
+ for (i = 0; i < CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX; i++) {
+ rc = cam_vfe_bus_deinit_vfe_bus_rd_resource(
+ &bus_priv->vfe_bus_rd[i]);
+ if (rc < 0)
+ CAM_ERR(CAM_ISP,
+ "Deinit VFE Out failed rc=%d", rc);
+ }
+
+ rc = cam_irq_controller_deinit(
+ &bus_priv->common_data.bus_irq_controller);
+ if (rc)
+ CAM_ERR(CAM_ISP,
+ "Deinit IRQ Controller failed rc=%d", rc);
+
+ mutex_destroy(&bus_priv->common_data.bus_mutex);
+ kfree(vfe_bus_local->bus_priv);
+
+free_bus_local:
+ kfree(vfe_bus_local);
+
+ *vfe_bus = NULL;
+
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h
new file mode 100644
index 000000000000..9ab2911d6472
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h
@@ -0,0 +1,143 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_VFE_BUS_R_VER1_H_
+#define _CAM_VFE_BUS_R_VER1_H_
+
+#include "cam_irq_controller.h"
+#include "cam_vfe_bus.h"
+
+#define CAM_VFE_BUS_RD_VER1_MAX_CLIENTS 1
+
+enum cam_vfe_bus_rd_ver1_vfe_core_id {
+ CAM_VFE_BUS_RD_VER1_VFE_CORE_0,
+ CAM_VFE_BUS_RD_VER1_VFE_CORE_1,
+ CAM_VFE_BUS_RD_VER1_VFE_CORE_MAX,
+};
+
+enum cam_vfe_bus_rd_ver1_comp_grp_type {
+ CAM_VFE_BUS_RD_VER1_COMP_GRP_0,
+ CAM_VFE_BUS_RD_VER1_COMP_GRP_MAX,
+};
+
+
+enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type {
+ CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0,
+ CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX,
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_reg_offset_common:
+ *
+ * @Brief: Common registers across all BUS Clients
+ */
+struct cam_vfe_bus_rd_ver1_reg_offset_common {
+ uint32_t hw_version;
+ uint32_t hw_capability;
+ uint32_t sw_reset;
+ uint32_t cgc_ovd;
+ uint32_t pwr_iso_cfg;
+ uint32_t input_if_cmd;
+ uint32_t test_bus_ctrl;
+ struct cam_irq_controller_reg_info irq_reg_info;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_reg_offset_bus_client:
+ *
+ * @Brief: Register offsets for BUS Clients
+ */
+struct cam_vfe_bus_rd_ver1_reg_offset_bus_client {
+ uint32_t status0;
+ uint32_t status1;
+ uint32_t cfg;
+ uint32_t header_addr;
+ uint32_t header_cfg;
+ uint32_t image_addr;
+ uint32_t image_addr_offset;
+ uint32_t buffer_width_cfg;
+ uint32_t buffer_height_cfg;
+ uint32_t unpacker_cfg;
+ uint32_t stride;
+ void *ubwc_regs;
+ uint32_t burst_limit;
+ uint32_t latency_buf_allocation;
+ uint32_t buf_size;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info:
+ *
+ * @Brief: HW capability of VFE Bus Client
+ */
+struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info {
+ enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_type;
+ uint32_t max_width;
+ uint32_t max_height;
+};
+
+/*
+ * struct cam_vfe_bus_rd_ver1_hw_info:
+ *
+ * @Brief: HW register info for entire Bus
+ *
+ * @common_reg: Common register details
+ * @bus_client_reg: Bus client register info
+ * @comp_reg_grp: Composite group register info
+ * @vfe_out_hw_info: VFE output capability
+ */
+struct cam_vfe_bus_rd_ver1_hw_info {
+ struct cam_vfe_bus_rd_ver1_reg_offset_common common_reg;
+ uint32_t num_client;
+ struct cam_vfe_bus_rd_ver1_reg_offset_bus_client
+ bus_client_reg[CAM_VFE_BUS_RD_VER1_MAX_CLIENTS];
+ uint32_t num_bus_rd_resc;
+ struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info
+ vfe_bus_rd_hw_info[CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
+};
+
+/*
+ * cam_vfe_bus_rd_ver1_init()
+ *
+ * @Brief: Initialize Bus layer
+ *
+ * @soc_info: Soc Information for the associated HW
+ * @hw_intf: HW Interface of HW to which this resource belongs
+ * @bus_hw_info: BUS HW info that contains details of BUS registers
+ * @vfe_irq_controller: VFE IRQ Controller to use for subscribing to Top
+ * level IRQs
+ * @vfe_bus: Pointer to vfe_bus structure which will be filled
+ * and returned on successful initialize
+ *
+ * @Return: 0: Success
+ * Non-zero: Failure
+ */
+int cam_vfe_bus_rd_ver1_init(
+ struct cam_hw_soc_info *soc_info,
+ struct cam_hw_intf *hw_intf,
+ void *bus_hw_info,
+ void *vfe_irq_controller,
+ struct cam_vfe_bus **vfe_bus);
+
+/*
+ * cam_vfe_bus_rd_bus_ver1_deinit()
+ *
+ * @Brief: Deinitialize Bus layer
+ *
+ * @vfe_bus: Pointer to vfe_bus structure to deinitialize
+ *
+ * @Return: 0: Success
+ * Non-zero: Failure
+ */
+int cam_vfe_bus_rd_bus_ver1_deinit(struct cam_vfe_bus **vfe_bus);
+
+#endif /* _CAM_VFE_BUS_R_VER1_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 7ee9f000a8c0..8ad4d96dcff8 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -103,6 +103,7 @@ struct cam_vfe_bus_ver2_common_data {
void *bus_irq_controller;
void *vfe_irq_controller;
struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
+ struct cam_vfe_bus_ver2_reg_data *reg_data;
uint32_t io_buf_update[
MAX_REG_VAL_PAIR_SIZE];
@@ -114,6 +115,7 @@ struct cam_vfe_bus_ver2_common_data {
uint32_t secure_mode;
uint32_t num_sec_out;
uint32_t addr_no_sync;
+ uint32_t camera_hw_version;
};
struct cam_vfe_bus_ver2_wm_resource_data {
@@ -123,8 +125,6 @@ struct cam_vfe_bus_ver2_wm_resource_data {
void *ctx;
uint32_t irq_enabled;
- bool init_cfg_done;
- bool hfr_cfg_done;
uint32_t offset;
uint32_t width;
@@ -306,10 +306,10 @@ static int cam_vfe_bus_put_evt_payload(void *core_info,
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)
+ uint32_t *intra_client_mask,
+ uint32_t camera_hw_version)
{
int rc = 0;
- uint32_t camera_hw_version = 0;
uint32_t version_based_intra_client_mask = 0x1;
*intra_client_mask = 0;
@@ -321,10 +321,6 @@ static int cam_vfe_bus_ver2_get_intra_client_mask(
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;
@@ -1130,8 +1126,6 @@ static int cam_vfe_bus_release_wm(void *bus_priv,
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;
@@ -1149,7 +1143,7 @@ static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
struct cam_vfe_bus_ver2_common_data *common_data =
rsrc_data->common_data;
uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
- uint32_t camera_hw_version;
+ uint32_t camera_hw_version = 0;
cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
@@ -1185,12 +1179,7 @@ static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
/* 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;
- }
+ camera_hw_version = rsrc_data->common_data->camera_hw_version;
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
@@ -1268,8 +1257,6 @@ static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
wm_res->irq_handle);
wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
- rsrc_data->init_cfg_done = false;
- rsrc_data->hfr_cfg_done = false;
return rc;
}
@@ -1571,7 +1558,8 @@ static int cam_vfe_bus_acquire_comp_grp(
rc = cam_vfe_bus_ver2_get_intra_client_mask(
dual_slave_core,
comp_grp_local->hw_intf->hw_idx,
- &rsrc_data->intra_client_mask);
+ &rsrc_data->intra_client_mask,
+ rsrc_data->common_data->camera_hw_version);
if (rc)
return rc;
} else {
@@ -2526,9 +2514,9 @@ static void cam_vfe_bus_update_ubwc_meta_addr(
uint32_t *reg_val_pair,
uint32_t *j,
void *regs,
- uint64_t image_buf)
+ uint64_t image_buf,
+ uint32_t camera_hw_version)
{
- 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;
@@ -2539,11 +2527,7 @@ static void cam_vfe_bus_update_ubwc_meta_addr(
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) ||
+ if ((camera_hw_version < CAM_CPAS_TITAN_170_V100) ||
(camera_hw_version > CAM_CPAS_TITAN_175_V120)) {
CAM_ERR(CAM_ISP, "Invalid HW version: %d",
camera_hw_version);
@@ -2582,7 +2566,9 @@ static int cam_vfe_bus_update_ubwc_3_regs(
uint32_t *reg_val_pair, uint32_t i, uint32_t *j)
{
struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *ubwc_regs;
+ struct cam_vfe_bus_ver2_reg_data *reg_data;
uint32_t ubwc_bw_limit = 0;
+ uint32_t camera_hw_version = 0;
int rc = 0;
if (!wm_data || !reg_val_pair || !j) {
@@ -2593,6 +2579,7 @@ static int cam_vfe_bus_update_ubwc_3_regs(
ubwc_regs = (struct cam_vfe_bus_ver2_reg_offset_ubwc_3_client *)
wm_data->hw_regs->ubwc_regs;
+ reg_data = wm_data->common_data->reg_data;
CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
wm_data->hw_regs->packer_cfg, wm_data->packer_cfg);
@@ -2663,6 +2650,39 @@ static int cam_vfe_bus_update_ubwc_3_regs(
wm_data->index, ubwc_bw_limit);
}
+ camera_hw_version = wm_data->common_data->camera_hw_version;
+ if (camera_hw_version == CAM_CPAS_TITAN_175_V120) {
+ switch (wm_data->format) {
+ case CAM_FORMAT_UBWC_TP10:
+ case CAM_FORMAT_UBWC_P010:
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+ ubwc_regs->threshlod_lossy_0,
+ reg_data->ubwc_10bit_threshold_lossy_0);
+ CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_0 0x%x",
+ wm_data->index, reg_val_pair[*j-1]);
+
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+ ubwc_regs->threshlod_lossy_1,
+ reg_data->ubwc_10bit_threshold_lossy_1);
+ CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_1 0x%x",
+ wm_data->index, reg_val_pair[*j-1]);
+ break;
+ default:
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+ ubwc_regs->threshlod_lossy_0,
+ reg_data->ubwc_8bit_threshold_lossy_0);
+ CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_0 0x%x",
+ wm_data->index, reg_val_pair[*j-1]);
+
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j,
+ ubwc_regs->threshlod_lossy_1,
+ reg_data->ubwc_8bit_threshold_lossy_1);
+ CAM_DBG(CAM_ISP, "WM %d threshlod_lossy_1 0x%x",
+ wm_data->index, reg_val_pair[*j-1]);
+ break;
+ }
+ }
+
end:
return rc;
}
@@ -2866,8 +2886,7 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
io_cfg->planes[i].plane_stride,
val);
- if ((wm_data->stride != val ||
- !wm_data->init_cfg_done) && (wm_data->index >= 3)) {
+ if (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);
@@ -2882,17 +2901,16 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
"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);
- }
+
+ 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]);
+ update_buf->wm_update->image_buf[i],
+ wm_data->common_data->camera_hw_version);
CAM_DBG(CAM_ISP, "WM %d ubwc meta addr 0x%llx",
wm_data->index,
update_buf->wm_update->image_buf[i]);
@@ -2946,9 +2964,6 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
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);
@@ -3012,52 +3027,36 @@ static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
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);
- }
+ 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);
- }
+ 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);
- }
+ 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);
- }
+ 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);
@@ -3126,62 +3125,14 @@ static int cam_vfe_bus_update_ubwc_config(void *cmd_args)
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;
- }
+ wm_data->packer_cfg = ubwc_plane_cfg->packer_config;
+ wm_data->tile_cfg = ubwc_plane_cfg->tile_config;
+ wm_data->h_init = ubwc_plane_cfg->h_init;
+ wm_data->v_init = ubwc_plane_cfg->v_init;
+ wm_data->ubwc_meta_stride = ubwc_plane_cfg->meta_stride;
+ wm_data->ubwc_mode_cfg_0 = ubwc_plane_cfg->mode_config_0;
+ wm_data->ubwc_mode_cfg_1 = ubwc_plane_cfg->mode_config_1;
+ wm_data->ubwc_meta_offset = ubwc_plane_cfg->meta_offset;
}
end:
@@ -3268,24 +3219,27 @@ static int cam_vfe_bus_init_hw(void *hw_priv,
NULL,
NULL);
- if (bus_priv->irq_handle <= 0) {
+ if ((int)bus_priv->irq_handle <= 0) {
CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
return -EFAULT;
}
- bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
- bus_priv->common_data.bus_irq_controller,
- CAM_IRQ_PRIORITY_0,
- bus_error_irq_mask,
- bus_priv,
- cam_vfe_bus_error_irq_top_half,
- cam_vfe_bus_err_bottom_half,
- bus_priv->tasklet_info,
- &tasklet_bh_api);
-
- if (bus_priv->irq_handle <= 0) {
- CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
- return -EFAULT;
+ if (bus_priv->tasklet_info != NULL) {
+ bus_priv->error_irq_handle = cam_irq_controller_subscribe_irq(
+ bus_priv->common_data.bus_irq_controller,
+ CAM_IRQ_PRIORITY_0,
+ bus_error_irq_mask,
+ bus_priv,
+ cam_vfe_bus_error_irq_top_half,
+ cam_vfe_bus_err_bottom_half,
+ bus_priv->tasklet_info,
+ &tasklet_bh_api);
+
+ if ((int)bus_priv->error_irq_handle <= 0) {
+ CAM_ERR(CAM_ISP, "Failed to subscribe BUS error IRQ %d",
+ bus_priv->error_irq_handle);
+ return -EFAULT;
+ }
}
/*Set Debug Registers*/
@@ -3422,6 +3376,7 @@ int cam_vfe_bus_ver2_init(
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;
+ uint32_t camera_hw_version = 0;
CAM_DBG(CAM_ISP, "Enter");
@@ -3434,6 +3389,14 @@ int cam_vfe_bus_ver2_init(
goto end;
}
+ 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);
+ 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");
@@ -3460,8 +3423,10 @@ int cam_vfe_bus_ver2_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 = &ver2_hw_info->common_reg;
+ bus_priv->common_data.reg_data = &ver2_hw_info->reg_data;
bus_priv->common_data.addr_no_sync =
CAM_VFE_BUS_ADDR_NO_SYNC_DEFAULT_VAL;
+ bus_priv->common_data.camera_hw_version = camera_hw_version;
mutex_init(&bus_priv->common_data.bus_mutex);
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
index 73b7eb2dc59d..39d8fa561590 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -122,6 +122,8 @@ 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 threshlod_lossy_0;
+ uint32_t threshlod_lossy_1;
};
@@ -175,6 +177,19 @@ struct cam_vfe_bus_ver2_vfe_out_hw_info {
};
/*
+ * struct cam_vfe_bus_ver2_reg_data:
+ *
+ * @Brief: Holds the bus register data
+ */
+
+struct cam_vfe_bus_ver2_reg_data {
+ uint32_t ubwc_10bit_threshold_lossy_0;
+ uint32_t ubwc_10bit_threshold_lossy_1;
+ uint32_t ubwc_8bit_threshold_lossy_0;
+ uint32_t ubwc_8bit_threshold_lossy_1;
+};
+
+/*
* struct cam_vfe_bus_ver2_hw_info:
*
* @Brief: HW register info for entire Bus
@@ -183,6 +198,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
+ * @reg_data: bus register data;
*/
struct cam_vfe_bus_ver2_hw_info {
struct cam_vfe_bus_ver2_reg_offset_common common_reg;
@@ -194,6 +210,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];
+ struct cam_vfe_bus_ver2_reg_data reg_data;
};
/*
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
index 6f88bc7f5a99..4cdb28a0cb67 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/include/cam_vfe_bus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#define CAM_VFE_BUS_VER_1_0 0x1000
#define CAM_VFE_BUS_VER_2_0 0x2000
+#define CAM_VFE_BUS_RD_VER_4_0 0x4000
enum cam_vfe_bus_plane_type {
PLANE_Y,
@@ -26,6 +27,12 @@ enum cam_vfe_bus_plane_type {
PLANE_MAX,
};
+enum cam_vfe_bus_type {
+ BUS_TYPE_WR,
+ BUS_TYPE_RD,
+ BUS_TYPE_MAX,
+};
+
/*
* struct cam_vfe_bus:
*
@@ -50,6 +57,7 @@ struct cam_vfe_bus {
* @Brief: Initialize Bus layer
*
* @bus_version: Version of BUS to initialize
+ * @bus_type: Bus Type RD/WR
* @soc_info: Soc Information for the associated HW
* @hw_intf: HW Interface of HW to which this resource belongs
* @bus_hw_info: BUS HW info that contains details of BUS registers
@@ -62,6 +70,7 @@ struct cam_vfe_bus {
* Non-zero: Failure
*/
int cam_vfe_bus_init(uint32_t bus_version,
+ int bus_type,
struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
index cdb6b2867433..eb867630d88e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/Makefile
@@ -11,3 +11,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vf
obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_camif_lite_ver2.o
obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_top.o cam_vfe_top_ver2.o cam_vfe_camif_ver2.o cam_vfe_rdi.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_vfe_fe_ver1.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
index 64b77eb7ccb8..b3c795417171 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -166,10 +166,7 @@ static int cam_vfe_camif_lite_resource_start(
static int cam_vfe_camif_lite_resource_stop(
struct cam_isp_resource_node *camif_lite_res)
{
- struct cam_vfe_mux_camif_lite_data *camif_lite_priv;
- struct cam_vfe_camif_lite_ver2_reg *camif_lite_reg;
int rc = 0;
- uint32_t val = 0;
if (!camif_lite_res) {
CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
@@ -180,16 +177,6 @@ static int cam_vfe_camif_lite_resource_stop(
(camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
return 0;
- camif_lite_priv = (struct cam_vfe_mux_camif_lite_data *)
- camif_lite_res->res_priv;
- camif_lite_reg = camif_lite_priv->camif_lite_reg;
-
- val = cam_io_r_mb(camif_lite_priv->mem_base +
- camif_lite_priv->common_reg->core_cfg);
- val &= (~(1 << camif_lite_priv->reg_data->dual_pd_path_sel_shift));
- cam_io_w_mb(val, camif_lite_priv->mem_base +
- camif_lite_priv->common_reg->core_cfg);
-
if (camif_lite_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 95bed8d9d23c..c40936525c73 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -212,8 +212,7 @@ static int cam_vfe_camif_resource_start(
uint32_t epoch0_irq_mask;
uint32_t epoch1_irq_mask;
uint32_t computed_epoch_line_cfg;
- uint32_t camera_hw_version = 0;
- int rc = 0;
+ struct cam_vfe_soc_private *soc_private;
if (!camif_res) {
CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
@@ -228,6 +227,13 @@ static int cam_vfe_camif_resource_start(
rsrc_data = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
+ soc_private = rsrc_data->soc_info->soc_private;
+
+ if (!soc_private) {
+ CAM_ERR(CAM_ISP, "Error! soc_private NULL");
+ return -ENODEV;
+ }
+
/*config vfe core*/
val = (rsrc_data->pix_pattern <<
rsrc_data->reg_data->pixel_pattern_shift);
@@ -253,26 +259,14 @@ static int cam_vfe_camif_resource_start(
rsrc_data->common_reg->module_ctrl[
CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
- /* get the HW version */
- rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
-
- if (rc) {
- CAM_ERR(CAM_ISP, "Couldn't find HW version. rc: %d", rc);
- return rc;
- }
-
/* epoch config */
- switch (camera_hw_version) {
+ switch (soc_private->cpas_version) {
case CAM_CPAS_TITAN_170_V100:
case CAM_CPAS_TITAN_170_V110:
case CAM_CPAS_TITAN_170_V120:
- cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg,
- rsrc_data->mem_base +
- rsrc_data->camif_reg->epoch_irq);
- break;
default:
- epoch0_irq_mask = ((rsrc_data->last_line -
- rsrc_data->first_line) / 2) +
+ epoch0_irq_mask = (((rsrc_data->last_line -
+ rsrc_data->first_line) * 2) / 3) +
rsrc_data->first_line;
epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg &
0xFFFF;
@@ -316,27 +310,16 @@ static int cam_vfe_camif_resource_start(
}
static int cam_vfe_camif_reg_dump(
- struct cam_isp_resource_node *camif_res)
+ struct cam_vfe_mux_camif_data *camif_priv)
{
- struct cam_vfe_mux_camif_data *camif_priv;
- struct cam_vfe_soc_private *soc_private;
- int rc = 0, i;
- uint32_t val = 0;
+ uint32_t val = 0, wm_idx, offset;
+ int i = 0;
- if (!camif_res) {
- CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
- return -EINVAL;
- }
-
- if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
- (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
- return 0;
-
- camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
- soc_private = camif_priv->soc_info->soc_private;
- for (i = 0xA3C; i <= 0xA90; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ for (i = 0xA3C; i <= 0xA90; i += 8) {
+ CAM_INFO(CAM_ISP,
+ "SCALING offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ i, cam_io_r_mb(camif_priv->mem_base + i), i + 4,
+ cam_io_r_mb(camif_priv->mem_base + i + 4));
}
for (i = 0xE0C; i <= 0xE3C; i += 4) {
@@ -344,64 +327,96 @@ static int cam_vfe_camif_reg_dump(
CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
}
- for (i = 0x2000; i <= 0x20B8; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
- }
-
- for (i = 0x2500; i <= 0x255C; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
- }
-
- for (i = 0x2600; i <= 0x265C; i += 4) {
- val = cam_io_r_mb(camif_priv->mem_base + i);
- CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ for (wm_idx = 0; wm_idx <= 23; wm_idx++) {
+ offset = 0x2214 + 0x100 * wm_idx;
+ CAM_INFO(CAM_ISP,
+ "BUS_WM%u offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ wm_idx, offset,
+ cam_io_r_mb(camif_priv->mem_base + offset),
+ offset + 4, cam_io_r_mb(camif_priv->mem_base +
+ offset + 4));
+ CAM_INFO(CAM_ISP,
+ "offset+8 0x%x val+8 0x%x offset+12 0x%x val+12 0x%x",
+ offset + 8,
+ cam_io_r_mb(camif_priv->mem_base + offset + 8),
+ offset + 12, cam_io_r_mb(camif_priv->mem_base +
+ offset + 12));
}
- cam_cpas_reg_read(soc_private->cpas_handle,
- CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
- CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+ offset = 0x420;
+ val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
+ CAM_INFO(CAM_ISP, "CAMNOC IFE02 MaxWR_LOW offset 0x%x value 0x%x",
+ offset, val);
- cam_cpas_reg_read(soc_private->cpas_handle,
- CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
- CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+ offset = 0x820;
+ val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
+ CAM_INFO(CAM_ISP, "CAMNOC IFE13 MaxWR_LOW offset 0x%x value 0x%x",
+ offset, val);
- return rc;
+ return 0;
}
-static int cam_vfe_camif_reg_dump_bh(struct cam_vfe_mux_camif_data *camif_priv)
+static int cam_vfe_camif_reg_dump_bh(
+ struct cam_isp_resource_node *camif_res)
{
+ struct cam_vfe_mux_camif_data *camif_priv;
+ struct cam_vfe_soc_private *soc_private;
uint32_t offset, val, wm_idx;
+ if (!camif_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+ (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
+ return 0;
+
+ camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
for (offset = 0x0; offset < 0x1000; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
- CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
+ CAM_DBG(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
}
for (offset = 0x2000; offset <= 0x20B8; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
- CAM_INFO(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
+ CAM_DBG(CAM_ISP, "offset 0x%x value 0x%x", offset, val);
}
for (wm_idx = 0; wm_idx <= 23; wm_idx++) {
for (offset = 0x2200 + 0x100 * wm_idx;
offset < 0x2278 + 0x100 * wm_idx; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
- CAM_INFO(CAM_ISP,
+ CAM_DBG(CAM_ISP,
"offset 0x%x value 0x%x", offset, val);
}
}
- offset = 0x420;
- val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
- CAM_INFO(CAM_ISP, "CAMNOC IFE02 MaxWR_LOW offset 0x%x value 0x%x",
- offset, val);
-
- offset = 0x820;
- val = cam_soc_util_r(camif_priv->soc_info, 1, offset);
- CAM_INFO(CAM_ISP, "CAMNOC IFE13 MaxWR_LOW offset 0x%x value 0x%x",
- offset, val);
+ soc_private = camif_priv->soc_info->soc_private;
+ if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120) {
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val);
+ CAM_DBG(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x",
+ val);
+
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x5420, true, &val);
+ CAM_DBG(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x",
+ val);
+
+ cam_cpas_reg_read(soc_private->cpas_handle[1],
+ CAM_CPAS_REG_CAMNOC, 0x3620, true, &val);
+ CAM_DBG(CAM_ISP,
+ "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val);
+ } else {
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
+ CAM_DBG(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+
+ cam_cpas_reg_read(soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
+ CAM_DBG(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+ }
return 0;
}
@@ -483,7 +498,7 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
arg_size);
break;
case CAM_ISP_HW_CMD_GET_REG_DUMP:
- rc = cam_vfe_camif_reg_dump(rsrc_node);
+ rc = cam_vfe_camif_reg_dump_bh(rsrc_node);
break;
case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args);
@@ -573,11 +588,11 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv,
}
break;
case CAM_ISP_HW_EVENT_ERROR:
- if (irq_status1 & camif_priv->reg_data->error_irq_mask1) {
+ if (irq_status1 & camif_priv->reg_data->error_irq_mask1 &&
+ payload->enable_reg_dump) {
CAM_DBG(CAM_ISP, "Received ERROR\n");
ret = CAM_ISP_HW_ERROR_OVERFLOW;
- cam_vfe_camif_reg_dump(camif_node);
- cam_vfe_camif_reg_dump_bh(camif_node->res_priv);
+ cam_vfe_camif_reg_dump(camif_node->res_priv);
} else {
ret = CAM_ISP_HW_ERROR_NONE;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
new file mode 100644
index 000000000000..2432d7a5044b
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c
@@ -0,0 +1,638 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <uapi/media/cam_isp.h>
+#include "cam_io_util.h"
+#include "cam_isp_hw_mgr_intf.h"
+#include "cam_isp_hw.h"
+#include "cam_vfe_hw_intf.h"
+#include "cam_vfe_soc.h"
+#include "cam_vfe_top.h"
+#include "cam_vfe_top_ver2.h"
+#include "cam_vfe_fe_ver1.h"
+#include "cam_debug_util.h"
+#include "cam_cdm_util.h"
+#include "cam_cpas_api.h"
+
+#define CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX 2
+
+struct cam_vfe_mux_fe_data {
+ void __iomem *mem_base;
+ struct cam_hw_intf *hw_intf;
+ struct cam_vfe_fe_ver1_reg *fe_reg;
+ struct cam_vfe_top_ver2_reg_offset_common *common_reg;
+ struct cam_vfe_fe_reg_data *reg_data;
+ struct cam_hw_soc_info *soc_info;
+
+ enum cam_isp_hw_sync_mode sync_mode;
+ uint32_t dsp_mode;
+ uint32_t pix_pattern;
+ uint32_t first_pixel;
+ uint32_t first_line;
+ uint32_t last_pixel;
+ uint32_t last_line;
+ bool enable_sof_irq_debug;
+ uint32_t irq_debug_cnt;
+ uint32_t fe_cfg_data;
+ uint32_t hbi_count;
+};
+
+static int cam_vfe_fe_validate_pix_pattern(uint32_t pattern)
+{
+ int rc;
+
+ switch (pattern) {
+ case CAM_ISP_PATTERN_BAYER_RGRGRG:
+ case CAM_ISP_PATTERN_BAYER_GRGRGR:
+ case CAM_ISP_PATTERN_BAYER_BGBGBG:
+ case CAM_ISP_PATTERN_BAYER_GBGBGB:
+ case CAM_ISP_PATTERN_YUV_YCBYCR:
+ case CAM_ISP_PATTERN_YUV_YCRYCB:
+ case CAM_ISP_PATTERN_YUV_CBYCRY:
+ case CAM_ISP_PATTERN_YUV_CRYCBY:
+ rc = 0;
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "Error! Invalid pix pattern:%d", pattern);
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
+static int cam_vfe_fe_update(
+ struct cam_isp_resource_node *fe_res,
+ void *cmd_data, uint32_t arg_size)
+{
+ struct cam_vfe_mux_fe_data *rsrc_data = NULL;
+ struct cam_vfe_fe_update_args *args = cmd_data;
+ uint32_t fe_cfg_data;
+
+ if (arg_size != sizeof(struct cam_vfe_fe_update_args)) {
+ CAM_ERR(CAM_ISP, "Invalid cmd size");
+ return -EINVAL;
+ }
+
+ if (!args) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return -EINVAL;
+ }
+
+ CAM_DBG(CAM_ISP, "fe_update->min_vbi = 0x%x", args->fe_config.min_vbi);
+ CAM_DBG(CAM_ISP, "fe_update->hbi_count = 0x%x",
+ args->fe_config.hbi_count);
+ CAM_DBG(CAM_ISP, "fe_update->fs_mode = 0x%x", args->fe_config.fs_mode);
+ CAM_DBG(CAM_ISP, "fe_update->fs_line_sync_en = 0x%x",
+ args->fe_config.fs_line_sync_en);
+
+ fe_cfg_data = args->fe_config.min_vbi |
+ args->fe_config.fs_mode << 8 |
+ args->fe_config.fs_line_sync_en;
+
+ rsrc_data = fe_res->res_priv;
+ rsrc_data->fe_cfg_data = fe_cfg_data;
+ rsrc_data->hbi_count = args->fe_config.hbi_count;
+
+ CAM_DBG(CAM_ISP, "fe_cfg_data = 0x%x", fe_cfg_data);
+ return 0;
+}
+
+static int cam_vfe_fe_get_reg_update(
+ struct cam_isp_resource_node *fe_res,
+ void *cmd_args, uint32_t arg_size)
+{
+ uint32_t size = 0;
+ uint32_t reg_val_pair[2];
+ struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args;
+ struct cam_cdm_utils_ops *cdm_util_ops = NULL;
+ struct cam_vfe_mux_fe_data *rsrc_data = NULL;
+
+ if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) {
+ CAM_ERR(CAM_ISP, "Invalid cmd size");
+ return -EINVAL;
+ }
+
+ if (!cdm_args || !cdm_args->res) {
+ CAM_ERR(CAM_ISP, "Invalid args");
+ return -EINVAL;
+ }
+
+ cdm_util_ops = (struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops;
+
+ if (!cdm_util_ops) {
+ CAM_ERR(CAM_ISP, "Invalid CDM ops");
+ return -EINVAL;
+ }
+
+ if (cdm_args->rup_data->is_fe_enable &&
+ (cdm_args->rup_data->res_bitmap &
+ (1 << CAM_IFE_REG_UPD_CMD_RDI1_BIT))) {
+ CAM_DBG(CAM_ISP, "Avoiding rup_upd for fe");
+ cdm_args->cmd.used_bytes = 0;
+ return 0;
+ }
+
+ size = cdm_util_ops->cdm_required_size_reg_random(1);
+ /* since cdm returns dwords, we need to convert it into bytes */
+ if ((size * 4) > cdm_args->cmd.size) {
+ CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
+ cdm_args->cmd.size, size);
+ return -EINVAL;
+ }
+
+ rsrc_data = fe_res->res_priv;
+ reg_val_pair[0] = rsrc_data->fe_reg->reg_update_cmd;
+ reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
+ CAM_DBG(CAM_ISP, "CAMIF res_id %d reg_update_cmd 0x%x offset 0x%x",
+ fe_res->res_id, reg_val_pair[1], reg_val_pair[0]);
+
+ cdm_util_ops->cdm_write_regrandom(cdm_args->cmd.cmd_buf_addr,
+ 1, reg_val_pair);
+
+ cdm_args->cmd.used_bytes = size * 4;
+
+ return 0;
+}
+
+int cam_vfe_fe_ver1_acquire_resource(
+ struct cam_isp_resource_node *fe_res,
+ void *acquire_param)
+{
+ struct cam_vfe_mux_fe_data *fe_data;
+ struct cam_vfe_acquire_args *acquire_data;
+
+ int rc = 0;
+
+ fe_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+ acquire_data = (struct cam_vfe_acquire_args *)acquire_param;
+
+ rc = cam_vfe_fe_validate_pix_pattern(
+ acquire_data->vfe_in.in_port->test_pattern);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "pix validation failed: id:%d pix_pattern %d",
+ fe_res->hw_intf->hw_idx,
+ acquire_data->vfe_in.in_port->test_pattern);
+ return rc;
+ }
+
+ fe_data->sync_mode = acquire_data->vfe_in.sync_mode;
+ fe_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern;
+ fe_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode;
+ fe_data->first_pixel = acquire_data->vfe_in.in_port->left_start;
+ fe_data->last_pixel = acquire_data->vfe_in.in_port->left_stop;
+ fe_data->first_line = acquire_data->vfe_in.in_port->line_start;
+ fe_data->last_line = acquire_data->vfe_in.in_port->line_stop;
+
+ CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d",
+ fe_res->hw_intf->hw_idx,
+ fe_data->pix_pattern, fe_data->dsp_mode);
+ return rc;
+}
+
+static int cam_vfe_fe_resource_init(
+ struct cam_isp_resource_node *fe_res,
+ void *init_args, uint32_t arg_size)
+{
+ struct cam_vfe_mux_fe_data *fe_data;
+ struct cam_hw_soc_info *soc_info;
+ int rc = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error Invalid input arguments");
+ return -EINVAL;
+ }
+
+ fe_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+ soc_info = fe_data->soc_info;
+
+ if ((fe_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (fe_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ rc = cam_vfe_soc_enable_clk(soc_info, CAM_VFE_DSP_CLK_NAME);
+ if (rc)
+ CAM_ERR(CAM_ISP, "failed to enable dsp clk");
+ }
+
+ return rc;
+}
+
+static int cam_vfe_fe_resource_deinit(
+ struct cam_isp_resource_node *fe_res,
+ void *init_args, uint32_t arg_size)
+{
+ struct cam_vfe_mux_fe_data *fe_data;
+ struct cam_hw_soc_info *soc_info;
+ int rc = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error Invalid input arguments");
+ return -EINVAL;
+ }
+
+ fe_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+ soc_info = fe_data->soc_info;
+
+ if ((fe_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (fe_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ rc = cam_vfe_soc_disable_clk(soc_info, CAM_VFE_DSP_CLK_NAME);
+ if (rc)
+ CAM_ERR(CAM_ISP, "failed to disable dsp clk");
+ }
+
+ return rc;
+
+}
+
+static int cam_vfe_fe_resource_start(
+ struct cam_isp_resource_node *fe_res)
+{
+ struct cam_vfe_mux_fe_data *rsrc_data;
+ uint32_t val = 0;
+ uint32_t epoch0_irq_mask;
+ uint32_t epoch1_irq_mask;
+ uint32_t computed_epoch_line_cfg;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if (fe_res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
+ CAM_ERR(CAM_ISP, "Error! Invalid fe res res_state:%d",
+ fe_res->res_state);
+ return -EINVAL;
+ }
+
+ rsrc_data = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+
+ /* config vfe core */
+ val = (rsrc_data->pix_pattern <<
+ rsrc_data->reg_data->pixel_pattern_shift);
+ if (rsrc_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
+ val |= (1 << rsrc_data->reg_data->extern_reg_update_shift);
+
+ if ((rsrc_data->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (rsrc_data->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ /* DSP mode reg val is CAM_ISP_DSP_MODE - 1 */
+ val |= (((rsrc_data->dsp_mode - 1) &
+ rsrc_data->reg_data->dsp_mode_mask) <<
+ rsrc_data->reg_data->dsp_mode_shift);
+ val |= (0x1 << rsrc_data->reg_data->dsp_en_shift);
+ }
+
+ if (rsrc_data->fe_cfg_data) {
+ /*set Mux mode value to EXT_RD_PATH */
+ val |= (rsrc_data->reg_data->fe_mux_data <<
+ rsrc_data->reg_data->input_mux_sel_shift);
+ }
+
+ if (rsrc_data->hbi_count) {
+ /*set hbi count*/
+ val |= (rsrc_data->hbi_count <<
+ rsrc_data->reg_data->hbi_cnt_shift);
+ }
+ cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg);
+
+ CAM_DBG(CAM_ISP, "hw id:%d core_cfg (off:0x%x, val:0x%x)",
+ fe_res->hw_intf->hw_idx,
+ rsrc_data->common_reg->core_cfg,
+ val);
+
+ /* disable the CGC for stats */
+ cam_io_w_mb(0xFFFFFFFF, rsrc_data->mem_base +
+ rsrc_data->common_reg->module_ctrl[
+ CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
+
+ /* epoch config */
+ epoch0_irq_mask = ((rsrc_data->last_line - rsrc_data->first_line) / 2) +
+ rsrc_data->first_line;
+
+ epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF;
+ computed_epoch_line_cfg = (epoch0_irq_mask << 16) | epoch1_irq_mask;
+ cam_io_w_mb(computed_epoch_line_cfg,
+ rsrc_data->mem_base + rsrc_data->fe_reg->epoch_irq);
+ CAM_DBG(CAM_ISP, "first_line:0x%x last_line:0x%x epoch_line_cfg: 0x%x",
+ rsrc_data->first_line, rsrc_data->last_line,
+ computed_epoch_line_cfg);
+
+ fe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+
+ /* Read Back cfg */
+ cam_io_w_mb(rsrc_data->fe_cfg_data,
+ rsrc_data->mem_base + rsrc_data->fe_reg->fe_cfg);
+ CAM_DBG(CAM_ISP, "hw id:%d fe_cfg_data(off:0x%x val:0x%x)",
+ fe_res->hw_intf->hw_idx,
+ rsrc_data->fe_reg->fe_cfg,
+ rsrc_data->fe_cfg_data);
+
+ /* Reg Update */
+ cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
+ rsrc_data->mem_base + rsrc_data->fe_reg->reg_update_cmd);
+ CAM_DBG(CAM_ISP, "hw id:%d RUP (off:0x%x, val:0x%x)",
+ fe_res->hw_intf->hw_idx,
+ rsrc_data->fe_reg->reg_update_cmd,
+ rsrc_data->reg_data->reg_update_cmd_data);
+
+ /* disable sof irq debug flag */
+ rsrc_data->enable_sof_irq_debug = false;
+ rsrc_data->irq_debug_cnt = 0;
+
+ CAM_DBG(CAM_ISP, "Start Camif IFE %d Done", fe_res->hw_intf->hw_idx);
+ return 0;
+}
+
+static int cam_vfe_fe_reg_dump(
+ struct cam_isp_resource_node *fe_res)
+{
+ struct cam_vfe_mux_fe_data *fe_priv;
+ struct cam_vfe_soc_private *soc_private;
+ int rc = 0, i;
+ uint32_t val = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if ((fe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+ (fe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE))
+ return 0;
+
+ fe_priv = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+ soc_private = fe_priv->soc_info->soc_private;
+ for (i = 0xA3C; i <= 0xA90; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0xE0C; i <= 0xE3C; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0x2000; i <= 0x20B8; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0x2500; i <= 0x255C; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ for (i = 0x2600; i <= 0x265C; i += 4) {
+ val = cam_io_r_mb(fe_priv->mem_base + i);
+ CAM_INFO(CAM_ISP, "offset 0x%x val 0x%x", i, val);
+ }
+
+ cam_cpas_reg_read((uint32_t)soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x420, true, &val);
+ CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val);
+
+ cam_cpas_reg_read((uint32_t)soc_private->cpas_handle[0],
+ CAM_CPAS_REG_CAMNOC, 0x820, true, &val);
+ CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val);
+
+ return rc;
+}
+
+static int cam_vfe_fe_resource_stop(
+ struct cam_isp_resource_node *fe_res)
+{
+ struct cam_vfe_mux_fe_data *fe_priv;
+ struct cam_vfe_fe_ver1_reg *fe_reg;
+ int rc = 0;
+ uint32_t val = 0;
+
+ if (!fe_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
+ return -EINVAL;
+ }
+
+ if (fe_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED ||
+ fe_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)
+ return 0;
+
+ fe_priv = (struct cam_vfe_mux_fe_data *)fe_res->res_priv;
+ fe_reg = fe_priv->fe_reg;
+
+ if ((fe_priv->dsp_mode >= CAM_ISP_DSP_MODE_ONE_WAY) &&
+ (fe_priv->dsp_mode <= CAM_ISP_DSP_MODE_ROUND)) {
+ val = cam_io_r_mb(fe_priv->mem_base +
+ fe_priv->common_reg->core_cfg);
+ val &= (~(1 << fe_priv->reg_data->dsp_en_shift));
+ cam_io_w_mb(val, fe_priv->mem_base +
+ fe_priv->common_reg->core_cfg);
+ }
+
+ if (fe_res->res_state == CAM_ISP_RESOURCE_STATE_STREAMING)
+ fe_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+
+ return rc;
+}
+
+static int cam_vfe_fe_sof_irq_debug(
+ struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+ struct cam_vfe_mux_fe_data *fe_priv;
+ uint32_t *enable_sof_irq = (uint32_t *)cmd_args;
+
+ fe_priv =
+ (struct cam_vfe_mux_fe_data *)rsrc_node->res_priv;
+
+ if (*enable_sof_irq == 1)
+ fe_priv->enable_sof_irq_debug = true;
+ else
+ fe_priv->enable_sof_irq_debug = false;
+
+ return 0;
+}
+
+static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node,
+ uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+ int rc = -EINVAL;
+
+ if (!rsrc_node || !cmd_args) {
+ CAM_ERR(CAM_ISP, "Invalid input arguments");
+ return -EINVAL;
+ }
+
+ switch (cmd_type) {
+ case CAM_ISP_HW_CMD_GET_REG_UPDATE:
+ rc = cam_vfe_fe_get_reg_update(rsrc_node, cmd_args,
+ arg_size);
+ break;
+ case CAM_ISP_HW_CMD_GET_REG_DUMP:
+ rc = cam_vfe_fe_reg_dump(rsrc_node);
+ break;
+ case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
+ rc = cam_vfe_fe_sof_irq_debug(rsrc_node, cmd_args);
+ break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+ rc = cam_vfe_fe_update(rsrc_node, cmd_args, arg_size);
+ break;
+ default:
+ CAM_ERR(CAM_ISP,
+ "unsupported process command:%d", cmd_type);
+ break;
+ }
+
+ return rc;
+}
+
+static int cam_vfe_fe_handle_irq_top_half(uint32_t evt_id,
+ struct cam_irq_th_payload *th_payload)
+{
+ return -EPERM;
+}
+
+static int cam_vfe_fe_handle_irq_bottom_half(void *handler_priv,
+ void *evt_payload_priv)
+{
+ int ret = CAM_VFE_IRQ_STATUS_ERR;
+ struct cam_isp_resource_node *fe_node;
+ struct cam_vfe_mux_fe_data *fe_priv;
+ struct cam_vfe_top_irq_evt_payload *payload;
+ uint32_t irq_status0;
+ uint32_t irq_status1;
+
+ if (!handler_priv || !evt_payload_priv) {
+ CAM_ERR(CAM_ISP, "Invalid params");
+ return ret;
+ }
+
+ fe_node = handler_priv;
+ fe_priv = fe_node->res_priv;
+ payload = evt_payload_priv;
+ irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0];
+ irq_status1 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1];
+
+ CAM_DBG(CAM_ISP, "event ID:%d, irq_status_0 = 0x%x",
+ payload->evt_id, irq_status0);
+
+ switch (payload->evt_id) {
+ case CAM_ISP_HW_EVENT_SOF:
+ if (irq_status0 & fe_priv->reg_data->sof_irq_mask) {
+ if ((fe_priv->enable_sof_irq_debug) &&
+ (fe_priv->irq_debug_cnt <=
+ CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX)) {
+ CAM_INFO_RATE_LIMIT(CAM_ISP, "Received SOF");
+
+ fe_priv->irq_debug_cnt++;
+ if (fe_priv->irq_debug_cnt ==
+ CAM_VFE_CAMIF_IRQ_SOF_DEBUG_CNT_MAX) {
+ fe_priv->enable_sof_irq_debug =
+ false;
+ fe_priv->irq_debug_cnt = 0;
+ }
+ } else {
+ CAM_DBG(CAM_ISP, "Received SOF");
+ }
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_EPOCH:
+ if (irq_status0 & fe_priv->reg_data->epoch0_irq_mask) {
+ CAM_DBG(CAM_ISP, "Received EPOCH");
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_REG_UPDATE:
+ if (irq_status0 & fe_priv->reg_data->reg_update_irq_mask) {
+ CAM_DBG(CAM_ISP, "Received REG_UPDATE_ACK");
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_EOF:
+ if (irq_status0 & fe_priv->reg_data->eof_irq_mask) {
+ CAM_DBG(CAM_ISP, "Received EOF\n");
+ ret = CAM_VFE_IRQ_STATUS_SUCCESS;
+ }
+ break;
+ case CAM_ISP_HW_EVENT_ERROR:
+ if (irq_status1 & fe_priv->reg_data->error_irq_mask1) {
+ CAM_DBG(CAM_ISP, "Received ERROR\n");
+ ret = CAM_ISP_HW_ERROR_OVERFLOW;
+ cam_vfe_fe_reg_dump(fe_node);
+ } else {
+ ret = CAM_ISP_HW_ERROR_NONE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ CAM_DBG(CAM_ISP, "returing status = %d", ret);
+ return ret;
+}
+
+int cam_vfe_fe_ver1_init(
+ struct cam_hw_intf *hw_intf,
+ struct cam_hw_soc_info *soc_info,
+ void *fe_hw_info,
+ struct cam_isp_resource_node *fe_node)
+{
+ struct cam_vfe_mux_fe_data *fe_priv = NULL;
+ struct cam_vfe_fe_ver1_hw_info *fe_info = fe_hw_info;
+
+ fe_priv = kzalloc(sizeof(struct cam_vfe_mux_fe_data),
+ GFP_KERNEL);
+ if (!fe_priv) {
+ CAM_ERR(CAM_ISP, "Error! Failed to alloc for fe_priv");
+ return -ENOMEM;
+ }
+
+ fe_node->res_priv = fe_priv;
+
+ fe_priv->mem_base = soc_info->reg_map[VFE_CORE_BASE_IDX].mem_base;
+ fe_priv->fe_reg = fe_info->fe_reg;
+ fe_priv->common_reg = fe_info->common_reg;
+ fe_priv->reg_data = fe_info->reg_data;
+ fe_priv->hw_intf = hw_intf;
+ fe_priv->soc_info = soc_info;
+
+ fe_node->init = cam_vfe_fe_resource_init;
+ fe_node->deinit = cam_vfe_fe_resource_deinit;
+ fe_node->start = cam_vfe_fe_resource_start;
+ fe_node->stop = cam_vfe_fe_resource_stop;
+ fe_node->process_cmd = cam_vfe_fe_process_cmd;
+ fe_node->top_half_handler = cam_vfe_fe_handle_irq_top_half;
+ fe_node->bottom_half_handler = cam_vfe_fe_handle_irq_bottom_half;
+
+ return 0;
+}
+
+int cam_vfe_fe_ver1_deinit(
+ struct cam_isp_resource_node *fe_node)
+{
+ struct cam_vfe_mux_fe_data *fe_priv = fe_node->res_priv;
+
+ fe_node->start = NULL;
+ fe_node->stop = NULL;
+ fe_node->process_cmd = NULL;
+ fe_node->top_half_handler = NULL;
+ fe_node->bottom_half_handler = NULL;
+
+ fe_node->res_priv = NULL;
+
+ if (!fe_priv) {
+ CAM_ERR(CAM_ISP, "Error! fe_priv is NULL");
+ return -ENODEV;
+ }
+
+ kfree(fe_priv);
+
+ return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h
new file mode 100644
index 000000000000..0f8d2f18d1ec
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_VFE_FE_VER1_H_
+#define _CAM_VFE_FE_VER1_H_
+
+#include "cam_isp_hw.h"
+#include "cam_vfe_top.h"
+
+struct cam_vfe_fe_ver1_reg {
+ uint32_t camif_cmd;
+ uint32_t camif_config;
+ uint32_t line_skip_pattern;
+ uint32_t pixel_skip_pattern;
+ uint32_t skip_period;
+ uint32_t irq_subsample_pattern;
+ uint32_t epoch_irq;
+ uint32_t raw_crop_width_cfg;
+ uint32_t raw_crop_height_cfg;
+ uint32_t reg_update_cmd;
+ uint32_t vfe_diag_config;
+ uint32_t vfe_diag_sensor_status;
+ uint32_t fe_cfg;
+};
+
+struct cam_vfe_fe_reg_data {
+ uint32_t raw_crop_first_pixel_shift;
+ uint32_t raw_crop_first_pixel_mask;
+
+ uint32_t raw_crop_last_pixel_shift;
+ uint32_t raw_crop_last_pixel_mask;
+
+ uint32_t raw_crop_first_line_shift;
+ uint32_t raw_crop_first_line_mask;
+
+ uint32_t raw_crop_last_line_shift;
+ uint32_t raw_crop_last_line_mask;
+
+ uint32_t input_mux_sel_shift;
+ uint32_t input_mux_sel_mask;
+ uint32_t extern_reg_update_shift;
+ uint32_t extern_reg_update_mask;
+
+ uint32_t pixel_pattern_shift;
+ uint32_t pixel_pattern_mask;
+
+ uint32_t dsp_mode_shift;
+ uint32_t dsp_mode_mask;
+ uint32_t dsp_en_shift;
+ uint32_t dsp_en_mask;
+
+ uint32_t reg_update_cmd_data;
+ uint32_t epoch_line_cfg;
+ uint32_t sof_irq_mask;
+ uint32_t epoch0_irq_mask;
+ uint32_t reg_update_irq_mask;
+ uint32_t eof_irq_mask;
+ uint32_t error_irq_mask0;
+ uint32_t error_irq_mask1;
+
+ uint32_t enable_diagnostic_hw;
+ uint32_t fe_mux_data;
+ uint32_t hbi_cnt_shift;
+};
+
+struct cam_vfe_fe_ver1_hw_info {
+ struct cam_vfe_top_ver2_reg_offset_common *common_reg;
+ struct cam_vfe_fe_ver1_reg *fe_reg;
+ struct cam_vfe_fe_reg_data *reg_data;
+};
+
+int cam_vfe_fe_ver1_acquire_resource(
+ struct cam_isp_resource_node *camif_res,
+ void *acquire_param);
+
+int cam_vfe_fe_ver1_init(
+ struct cam_hw_intf *hw_intf,
+ struct cam_hw_soc_info *soc_info,
+ void *camif_hw_info,
+ struct cam_isp_resource_node *camif_node);
+
+int cam_vfe_fe_ver1_deinit(
+ struct cam_isp_resource_node *camif_node);
+
+#endif /* _CAM_VFE_FE_VER1_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
index 230698f7f890..c2c1bc20463b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -64,6 +64,14 @@ static int cam_vfe_rdi_get_reg_update(
return -EINVAL;
}
+ if (cdm_args->rup_data->is_fe_enable &&
+ (cdm_args->rup_data->res_bitmap &
+ (1 << CAM_IFE_REG_UPD_CMD_PIX_BIT))) {
+ cdm_args->cmd.used_bytes = 0;
+ CAM_DBG(CAM_ISP, "Avoiding reg_upd for fe for rdi");
+ return 0;
+ }
+
rsrc_data = rdi_res->res_priv;
reg_val_pair[0] = rsrc_data->rdi_reg->reg_update_cmd;
reg_val_pair[1] = rsrc_data->reg_data->reg_update_cmd_data;
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index f54f52af5334..569bbb6b2ce0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -37,11 +37,13 @@ struct cam_vfe_top_ver2_priv {
struct cam_axi_vote applied_axi_vote;
struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX];
unsigned long req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX];
- struct cam_axi_vote last_vote[CAM_VFE_TOP_VER2_MUX_MAX *
+ struct cam_axi_vote last_vote[CAM_CPAS_HANDLE_MAX]
+ [CAM_VFE_TOP_VER2_MUX_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES];
- uint32_t last_counter;
+ uint32_t last_counter[CAM_CPAS_HANDLE_MAX];
enum cam_vfe_bw_control_action
axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX];
+ enum cam_cpas_handle_id cpashdl_type[CAM_VFE_TOP_VER2_MUX_MAX];
};
static int cam_vfe_top_mux_get_base(struct cam_vfe_top_ver2_priv *top_priv,
@@ -133,99 +135,131 @@ static int cam_vfe_top_set_axi_bw_vote(
struct cam_vfe_soc_private *soc_private =
soc_info->soc_private;
bool apply_bw_update = false;
+ enum cam_cpas_handle_id cpashdl_type;
+ struct cam_axi_vote *last_vote = NULL;
if (!soc_private) {
CAM_ERR(CAM_ISP, "Error soc_private NULL");
return -EINVAL;
}
- for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
- if (top_priv->axi_vote_control[i] ==
- CAM_VFE_BW_CONTROL_INCLUDE) {
- sum.uncompressed_bw +=
+ for (cpashdl_type = 0; cpashdl_type < CAM_CPAS_HANDLE_MAX;
+ cpashdl_type++) {
+
+ if ((soc_private->cpas_version != CAM_CPAS_TITAN_175_V120)
+ && cpashdl_type)
+ continue;
+
+ sum.uncompressed_bw = sum.compressed_bw = 0;
+ to_be_applied_axi_vote.uncompressed_bw = 0;
+ to_be_applied_axi_vote.compressed_bw = 0;
+ apply_bw_update = false;
+
+ for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
+ if (top_priv->axi_vote_control[i] ==
+ CAM_VFE_BW_CONTROL_INCLUDE &&
+ top_priv->cpashdl_type[i] ==
+ cpashdl_type) {
+ sum.uncompressed_bw +=
top_priv->req_axi_vote[i].uncompressed_bw;
- sum.compressed_bw +=
+ sum.compressed_bw +=
top_priv->req_axi_vote[i].compressed_bw;
+ }
}
- }
-
- CAM_DBG(CAM_ISP, "Updating BW from (%llu %llu) to (%llu %llu)",
- top_priv->applied_axi_vote.uncompressed_bw,
- top_priv->applied_axi_vote.compressed_bw,
- sum.uncompressed_bw,
- sum.compressed_bw);
- top_priv->last_vote[top_priv->last_counter] = sum;
- top_priv->last_counter = (top_priv->last_counter + 1) %
- (CAM_VFE_TOP_VER2_MUX_MAX *
- CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
-
- if ((top_priv->applied_axi_vote.uncompressed_bw ==
- sum.uncompressed_bw) &&
- (top_priv->applied_axi_vote.compressed_bw ==
- sum.compressed_bw)) {
- CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
+ CAM_DBG(CAM_ISP, "Updating BW from (%llu %llu) to (%llu %llu)",
top_priv->applied_axi_vote.uncompressed_bw,
- top_priv->applied_axi_vote.compressed_bw);
- return 0;
- }
+ top_priv->applied_axi_vote.compressed_bw,
+ sum.uncompressed_bw,
+ sum.compressed_bw);
- if (start_stop == true) {
- /* need to vote current request immediately */
- to_be_applied_axi_vote = sum;
- /* Reset everything, we can start afresh */
- memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
- (CAM_VFE_TOP_VER2_MUX_MAX *
- CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
- top_priv->last_counter = 0;
- top_priv->last_vote[top_priv->last_counter] = sum;
- top_priv->last_counter = (top_priv->last_counter + 1) %
+ last_vote = top_priv->last_vote[cpashdl_type];
+
+ last_vote[top_priv->last_counter[cpashdl_type]] = sum;
+ top_priv->last_counter[cpashdl_type] =
+ (top_priv->last_counter[cpashdl_type] + 1) %
(CAM_VFE_TOP_VER2_MUX_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
- } else {
+
+ if ((top_priv->applied_axi_vote.uncompressed_bw ==
+ sum.uncompressed_bw) &&
+ (top_priv->applied_axi_vote.compressed_bw ==
+ sum.compressed_bw)) {
+ CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
+ top_priv->applied_axi_vote.uncompressed_bw,
+ top_priv->applied_axi_vote.compressed_bw);
+ return 0;
+ }
+
+ if (start_stop == true) {
+ rc = cam_cpas_update_axi_vote(
+ soc_private->cpas_handle[cpashdl_type],
+ &to_be_applied_axi_vote);
+ if (!rc) {
+ top_priv->applied_axi_vote.uncompressed_bw =
+ to_be_applied_axi_vote.uncompressed_bw;
+ top_priv->applied_axi_vote.compressed_bw =
+ to_be_applied_axi_vote.compressed_bw;
+ }
+ return rc;
+ }
+
/*
- * Find max bw request in last few frames. This will the bw
- *that we want to vote to CPAS now.
+ * Find max bw request in last few frames. This is the bw
+ * that we want to vote to CPAS now.
*/
for (i = 0; i < (CAM_VFE_TOP_VER2_MUX_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) {
if (to_be_applied_axi_vote.compressed_bw <
- top_priv->last_vote[i].compressed_bw)
+ last_vote[i].compressed_bw)
to_be_applied_axi_vote.compressed_bw =
- top_priv->last_vote[i].compressed_bw;
+ last_vote[i].compressed_bw;
if (to_be_applied_axi_vote.uncompressed_bw <
- top_priv->last_vote[i].uncompressed_bw)
+ last_vote[i].uncompressed_bw)
to_be_applied_axi_vote.uncompressed_bw =
- top_priv->last_vote[i].uncompressed_bw;
+ last_vote[i].uncompressed_bw;
}
- }
- if ((to_be_applied_axi_vote.uncompressed_bw !=
- top_priv->applied_axi_vote.uncompressed_bw) ||
- (to_be_applied_axi_vote.compressed_bw !=
- top_priv->applied_axi_vote.compressed_bw))
- apply_bw_update = true;
+ if ((to_be_applied_axi_vote.uncompressed_bw !=
+ top_priv->applied_axi_vote.uncompressed_bw) ||
+ (to_be_applied_axi_vote.compressed_bw !=
+ top_priv->applied_axi_vote.compressed_bw))
+ apply_bw_update = true;
- CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
+ CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
- if (apply_bw_update == true) {
- rc = cam_cpas_update_axi_vote(
- soc_private->cpas_handle,
- &to_be_applied_axi_vote);
- if (!rc) {
- top_priv->applied_axi_vote.uncompressed_bw =
+ if (apply_bw_update == true) {
+ rc = cam_cpas_update_axi_vote(
+ soc_private->cpas_handle[cpashdl_type],
+ &to_be_applied_axi_vote);
+ if (!rc) {
+ top_priv->applied_axi_vote.uncompressed_bw =
to_be_applied_axi_vote.uncompressed_bw;
- top_priv->applied_axi_vote.compressed_bw =
- to_be_applied_axi_vote.compressed_bw;
- } else {
- CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc);
+ top_priv->applied_axi_vote.compressed_bw =
+ to_be_applied_axi_vote.compressed_bw;
+ } else {
+ CAM_ERR(CAM_ISP, "BW request failed, rc=%d",
+ rc);
+ }
}
}
-
return rc;
}
+static int cam_vfe_top_fs_update(
+ struct cam_vfe_top_ver2_priv *top_priv,
+ void *cmd_args, uint32_t arg_size)
+{
+ struct cam_vfe_fe_update_args *cmd_update = cmd_args;
+
+ if (cmd_update->node_res->process_cmd)
+ return cmd_update->node_res->process_cmd(cmd_update->node_res,
+ CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, cmd_args, arg_size);
+
+ return 0;
+}
+
static int cam_vfe_top_clock_update(
struct cam_vfe_top_ver2_priv *top_priv,
void *cmd_args, uint32_t arg_size)
@@ -476,6 +510,14 @@ int cam_vfe_top_reserve(void *device_priv,
break;
}
+ if (acquire_args->res_id == CAM_ISP_HW_VFE_IN_RD) {
+ rc = cam_vfe_fe_ver1_acquire_resource(
+ &top_priv->mux_rsrc[i],
+ args);
+ if (rc)
+ break;
+ }
+
top_priv->mux_rsrc[i].cdm_ops = acquire_args->cdm_ops;
top_priv->mux_rsrc[i].tasklet_info = args->tasklet;
top_priv->mux_rsrc[i].res_state =
@@ -583,6 +625,7 @@ int cam_vfe_top_stop(void *device_priv,
if ((mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) ||
(mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF_LITE) ||
+ (mux_res->res_id == CAM_ISP_HW_VFE_IN_RD) ||
((mux_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0) &&
(mux_res->res_id <= CAM_ISP_HW_VFE_IN_RDI3))) {
rc = mux_res->stop(mux_res);
@@ -643,6 +686,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type,
rc = cam_vfe_top_clock_update(top_priv, cmd_args,
arg_size);
break;
+ case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
+ rc = cam_vfe_top_fs_update(top_priv, cmd_args,
+ arg_size);
+ break;
case CAM_ISP_HW_CMD_BW_UPDATE:
rc = cam_vfe_top_bw_update(top_priv, cmd_args,
arg_size);
@@ -669,6 +716,7 @@ int cam_vfe_top_ver2_init(
struct cam_vfe_top_ver2_priv *top_priv = NULL;
struct cam_vfe_top_ver2_hw_info *ver2_hw_info = top_hw_info;
struct cam_vfe_top *vfe_top;
+ struct cam_vfe_soc_private *soc_private = NULL;
vfe_top = kzalloc(sizeof(struct cam_vfe_top), GFP_KERNEL);
if (!vfe_top) {
@@ -684,14 +732,22 @@ int cam_vfe_top_ver2_init(
rc = -ENOMEM;
goto free_vfe_top;
}
+
+ soc_private = soc_info->soc_private;
+ if (!soc_private) {
+ CAM_ERR(CAM_ISP, "Error! soc_private NULL");
+ rc = -ENODEV;
+ goto free_vfe_top_priv;
+ }
vfe_top->top_priv = top_priv;
top_priv->hw_clk_rate = 0;
top_priv->applied_axi_vote.compressed_bw = 0;
top_priv->applied_axi_vote.uncompressed_bw = 0;
memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
- (CAM_VFE_TOP_VER2_MUX_MAX *
+ (CAM_VFE_TOP_VER2_MUX_MAX * CAM_CPAS_HANDLE_MAX *
CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
- top_priv->last_counter = 0;
+ top_priv->last_counter[0] = 0;
+ top_priv->last_counter[1] = 0;
for (i = 0, j = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN;
@@ -707,6 +763,7 @@ int cam_vfe_top_ver2_init(
if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
top_priv->mux_rsrc[i].res_id =
CAM_ISP_HW_VFE_IN_CAMIF;
+ top_priv->cpashdl_type[i] = CAM_CPAS_HANDLE_CAMIF;
rc = cam_vfe_camif_ver2_init(hw_intf, soc_info,
&ver2_hw_info->camif_hw_info,
@@ -717,6 +774,13 @@ int cam_vfe_top_ver2_init(
CAM_VFE_CAMIF_LITE_VER_2_0) {
top_priv->mux_rsrc[i].res_id =
CAM_ISP_HW_VFE_IN_CAMIF_LITE;
+ if (soc_private->cpas_version ==
+ CAM_CPAS_TITAN_175_V120)
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_RAW;
+ else
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_CAMIF;
rc = cam_vfe_camif_lite_ver2_init(hw_intf, soc_info,
&ver2_hw_info->camif_lite_hw_info,
@@ -729,12 +793,30 @@ int cam_vfe_top_ver2_init(
/* set the RDI resource id */
top_priv->mux_rsrc[i].res_id =
CAM_ISP_HW_VFE_IN_RDI0 + j++;
+ if (soc_private->cpas_version ==
+ CAM_CPAS_TITAN_175_V120)
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_RAW;
+ else
+ top_priv->cpashdl_type[i] =
+ CAM_CPAS_HANDLE_CAMIF;
rc = cam_vfe_rdi_ver2_init(hw_intf, soc_info,
&ver2_hw_info->rdi_hw_info,
&top_priv->mux_rsrc[i]);
if (rc)
goto deinit_resources;
+ } else if (ver2_hw_info->mux_type[i] ==
+ CAM_VFE_IN_RD_VER_1_0) {
+ /* set the RD resource id */
+ top_priv->mux_rsrc[i].res_id =
+ CAM_ISP_HW_VFE_IN_RD;
+
+ rc = cam_vfe_fe_ver1_init(hw_intf, soc_info,
+ &ver2_hw_info->fe_hw_info,
+ &top_priv->mux_rsrc[i]);
+ if (rc)
+ goto deinit_resources;
} else {
CAM_WARN(CAM_ISP, "Invalid mux type: %u",
ver2_hw_info->mux_type[i]);
@@ -769,6 +851,12 @@ deinit_resources:
if (cam_vfe_camif_lite_ver2_deinit(
&top_priv->mux_rsrc[i]))
CAM_ERR(CAM_ISP, "Camif lite deinit failed");
+ } else if (ver2_hw_info->mux_type[i] ==
+ CAM_ISP_HW_VFE_IN_RDI0) {
+ if (cam_vfe_rdi_ver2_init(hw_intf, soc_info,
+ &ver2_hw_info->rdi_hw_info,
+ &top_priv->mux_rsrc[i]))
+ CAM_ERR(CAM_ISP, "RDI deinit failed");
} else {
if (cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]))
CAM_ERR(CAM_ISP, "RDI Deinit failed");
@@ -776,7 +864,7 @@ deinit_resources:
top_priv->mux_rsrc[i].res_state =
CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
}
-
+free_vfe_top_priv:
kfree(vfe_top->top_priv);
free_vfe_top:
kfree(vfe_top);
@@ -829,6 +917,12 @@ int cam_vfe_top_ver2_deinit(struct cam_vfe_top **vfe_top_ptr)
rc = cam_vfe_rdi_ver2_deinit(&top_priv->mux_rsrc[i]);
if (rc)
CAM_ERR(CAM_ISP, "RDI deinit failed rc=%d", rc);
+ } else if (top_priv->mux_rsrc[i].res_type ==
+ CAM_VFE_IN_RD_VER_1_0) {
+ rc = cam_vfe_fe_ver1_deinit(&top_priv->mux_rsrc[i]);
+ if (rc)
+ CAM_ERR(CAM_ISP, "Camif deinit failed rc=%d",
+ rc);
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
index 11ca78cd8a2e..33435df476d1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,8 +16,9 @@
#include "cam_vfe_camif_ver2.h"
#include "cam_vfe_camif_lite_ver2.h"
#include "cam_vfe_rdi.h"
+#include "cam_vfe_fe_ver1.h"
-#define CAM_VFE_TOP_VER2_MUX_MAX 5
+#define CAM_VFE_TOP_VER2_MUX_MAX 6
enum cam_vfe_top_ver2_module_type {
CAM_VFE_TOP_VER2_MODULE_LENS,
@@ -55,6 +56,7 @@ struct cam_vfe_top_ver2_hw_info {
struct cam_vfe_camif_ver2_hw_info camif_hw_info;
struct cam_vfe_camif_lite_ver2_hw_info camif_lite_hw_info;
struct cam_vfe_rdi_ver2_hw_info rdi_hw_info;
+ struct cam_vfe_fe_ver1_hw_info fe_hw_info;
uint32_t mux_type[CAM_VFE_TOP_VER2_MUX_MAX];
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
index 90c75291bd73..cee2b4a96cb4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
+++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/include/cam_vfe_top.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,7 +24,8 @@
#define CAM_VFE_CAMIF_LITE_VER_2_0 0x02
-#define CAM_VFE_RDI_VER_1_0 0x1000
+#define CAM_VFE_RDI_VER_1_0 0x1000
+#define CAM_VFE_IN_RD_VER_1_0 0x2000
struct cam_vfe_top {
void *top_priv;
diff --git a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 24bb154f922c..f27b54a81e4a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -258,7 +258,7 @@ static int cam_jpeg_insert_cdm_change_base(
struct cam_jpeg_hw_ctx_data *ctx_data,
struct cam_jpeg_hw_mgr *hw_mgr)
{
- int rc;
+ int rc = 0;
uint32_t dev_type;
struct cam_cdm_bl_request *cdm_cmd;
uint32_t size;
@@ -275,6 +275,12 @@ static int cam_jpeg_insert_cdm_change_base(
"unable to get src buf info for cmd buf: %d", rc);
return rc;
}
+
+ if (config_args->hw_update_entries[CAM_JPEG_CHBASE].offset >=
+ ch_base_len) {
+ CAM_ERR(CAM_JPEG, "Not enough buf");
+ return -EINVAL;
+ }
CAM_DBG(CAM_JPEG, "iova %pK len %zu offset %d",
(void *)iova_addr, ch_base_len,
config_args->hw_update_entries[CAM_JPEG_CHBASE].offset);
@@ -713,7 +719,7 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
return -EINVAL;
}
- rc = cam_packet_util_validate_packet(packet);
+ rc = cam_packet_util_validate_packet(packet, prepare_args->remain_len);
if (rc) {
CAM_ERR(CAM_JPEG, "invalid packet %d", rc);
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile b/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile
index 5e46bf2531f8..83a580c23bc2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include/
obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw_mgr/
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h b/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h
index dc1c8f4c10aa..b8d0357f6f3d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/cam_lrme_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,7 +19,7 @@
#include "cam_req_mgr_interface.h"
#include "cam_sync_api.h"
-#define CAM_LRME_CTX_INDEX_SHIFT 16
+#define CAM_LRME_CTX_INDEX_SHIFT 32
/**
* struct cam_lrme_context
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile
index a048afece9db..2a4fba727773 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/Makefile
@@ -7,7 +7,7 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cdm
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw
-ccflags-y += -Idrivers/media/platform/msm/camera
+ccflags-y += -Idrivers/media/platform/msm/camera_v3
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_cpas/include
obj-$(CONFIG_SPECTRA_CAMERA) += lrme_hw/
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index 0c236462b7f5..11e9069b3c79 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -83,7 +83,8 @@ static int cam_lrme_mgr_util_get_device(struct cam_lrme_hw_mgr *hw_mgr,
return 0;
}
-static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet)
+static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet,
+ size_t remain_len)
{
struct cam_cmd_buf_desc *cmd_desc = NULL;
int i, rc;
@@ -105,7 +106,7 @@ static int cam_lrme_mgr_util_packet_validate(struct cam_packet *packet)
packet->patch_offset, packet->num_patches,
packet->kmd_cmd_buf_offset, packet->kmd_cmd_buf_index);
- if (cam_packet_util_validate_packet(packet)) {
+ if (cam_packet_util_validate_packet(packet, remain_len)) {
CAM_ERR(CAM_LRME, "invalid packet:%d %d %d %d %d",
packet->kmd_cmd_buf_index,
packet->num_cmd_buf, packet->cmd_buf_offset,
@@ -166,13 +167,6 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
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_LRME, "Invalid number of buffers %d %d %d",
- num_in_buf, num_out_buf, io_buf_size);
- return -EINVAL;
- }
-
memset(io_addr, 0, sizeof(io_addr));
for (plane = 0; plane < CAM_PACKET_MAX_PLANES; plane++) {
if (!io_cfg[i].mem_handle[plane])
@@ -186,6 +180,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
return -ENOMEM;
}
+ if ((size_t)io_cfg[i].offsets[plane] >= size) {
+ CAM_ERR(CAM_LRME, "Invalid plane offset: %zu",
+ (size_t)io_cfg[i].offsets[plane]);
+ return -EINVAL;
+ }
+
io_addr[plane] += io_cfg[i].offsets[plane];
CAM_DBG(CAM_LRME, "IO Address[%d][%d] : %llu",
@@ -194,6 +194,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
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 =
@@ -209,6 +215,12 @@ static int cam_lrme_mgr_util_prepare_io_buffer(int32_t iommu_hdl,
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 =
@@ -841,7 +853,7 @@ static int cam_lrme_mgr_hw_prepare_update(void *hw_mgr_priv,
goto error;
}
- rc = cam_lrme_mgr_util_packet_validate(args->packet);
+ rc = cam_lrme_mgr_util_packet_validate(args->packet, args->remain_len);
if (rc) {
CAM_ERR(CAM_LRME, "Error in packet validation %d", rc);
goto error;
diff --git a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index 8cb1c9c28e7a..4220e5993dd5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,7 +42,10 @@ static void cam_lrme_hw_util_fill_fe_reg(struct cam_lrme_hw_io_buffer *io_buf,
uint32_t reg_val;
/* 1. config buffer size */
- reg_val = io_buf->io_cfg->planes[0].width;
+ if (io_buf->io_cfg->format == CAM_FORMAT_PLAIN16_10)
+ reg_val = io_buf->io_cfg->planes[0].width * 2;
+ else
+ reg_val = io_buf->io_cfg->planes[0].width;
reg_val |= (io_buf->io_cfg->planes[0].height << 16);
cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
hw_info->bus_rd_reg.bus_client_reg[index].rd_buffer_size,
@@ -736,6 +739,11 @@ int cam_lrme_hw_process_irq(void *priv, void *data)
mutex_lock(&lrme_hw->hw_mutex);
+ if (lrme_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_DBG(CAM_LRME, "LRME HW is in off state");
+ goto end;
+ }
+
if (top_irq_status & (1 << 3)) {
CAM_DBG(CAM_LRME, "Error");
rc = cam_lrme_hw_util_process_err(lrme_hw);
@@ -895,7 +903,7 @@ int cam_lrme_hw_stop(void *hw_priv, void *hw_stop_args, uint32_t arg_size)
lrme_core->state = CAM_LRME_CORE_STATE_INIT;
} else {
CAM_ERR(CAM_LRME, "HW in wrong state %d", lrme_core->state);
- return -EINVAL;
+ rc = -EINVAL;
}
unlock:
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c
index 2d17f7b51cd7..284742ef33ee 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,6 +23,7 @@
#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_map_cpu_va(struct ion_handle *hdl,
uintptr_t *vaddr,
@@ -108,6 +109,7 @@ int cam_mem_mgr_init(void)
tbl.bufq[i].buf_handle = -1;
}
mutex_init(&tbl.m_lock);
+ atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED);
return rc;
bitmap_fail:
@@ -151,6 +153,11 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
{
int rc = 0, idx;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "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;
@@ -191,6 +198,11 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
uintptr_t kvaddr = 0;
size_t klen = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!buf_handle || !vaddr_ptr || !len)
return -EINVAL;
@@ -241,12 +253,24 @@ exit_func:
}
EXPORT_SYMBOL(cam_mem_get_cpu_buf);
+int cam_mem_put_cpu_buf(int32_t buf_handle)
+{
+ int rc = 0;
+ return rc;
+}
+EXPORT_SYMBOL(cam_mem_put_cpu_buf);
+
int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
{
int rc = 0, idx;
uint32_t ion_cache_ops;
unsigned long ion_flag = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd)
return -EINVAL;
@@ -409,11 +433,6 @@ static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd,
static int cam_mem_util_check_flags(struct cam_mem_mgr_alloc_cmd *cmd)
{
- if (!cmd->flags) {
- CAM_ERR(CAM_MEM, "Invalid flags");
- return -EINVAL;
- }
-
if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) {
CAM_ERR(CAM_MEM, "Num of mmu hdl exceeded maximum(%d)",
CAM_MEM_MMU_MAX_HANDLE);
@@ -528,6 +547,11 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)
dma_addr_t hw_vaddr = 0;
size_t len;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd) {
CAM_ERR(CAM_MEM, " Invalid argument");
return -EINVAL;
@@ -626,6 +650,11 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd)
dma_addr_t hw_vaddr = 0;
size_t len = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd || (cmd->fd < 0)) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
@@ -811,6 +840,7 @@ static int cam_mem_mgr_cleanup_table(void)
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);
@@ -899,6 +929,11 @@ 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_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!cmd) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
@@ -946,6 +981,11 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp || !out) {
CAM_ERR(CAM_MEM, "Invalid params");
return -EINVAL;
@@ -1064,6 +1104,11 @@ 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_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
@@ -1113,6 +1158,11 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp,
int32_t smmu_hdl = 0;
int32_t num_hdl = 0;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp || !out) {
CAM_ERR(CAM_MEM, "Invalid param(s)");
return -EINVAL;
@@ -1205,6 +1255,11 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp)
int rc;
int32_t smmu_hdl;
+ if (!atomic_read(&cam_mem_mgr_state)) {
+ CAM_ERR(CAM_CRM, "failed. mem_mgr not initialized");
+ return -EINVAL;
+ }
+
if (!inp) {
CAM_ERR(CAM_MEM, "Invalid argument");
return -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.h
index 92c366d723f9..73f0eb3d3425 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,12 @@
#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,
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h
index 64258e8fb5ee..79945cff1dd2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_mem_mgr_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -95,6 +95,15 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr,
size_t *len);
+/**
+ * @brief: This indicates end of CPU access
+ *
+ * @buf_handle: Handle for the buffer
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int cam_mem_put_cpu_buf(int32_t buf_handle);
+
static inline bool cam_mem_is_secure_buf(int32_t buf_handle)
{
return CAM_MEM_MGR_IS_SECURE_HDL(buf_handle);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
index 275940f839e3..234c51453476 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,31 @@
#include "cam_req_mgr_dev.h"
static struct cam_req_mgr_core_device *g_crm_core_dev;
+static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION];
+
+void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
+{
+ link->link_hdl = 0;
+ link->num_devs = 0;
+ link->max_delay = CAM_PIPELINE_DELAY_0;
+ link->workq = NULL;
+ link->pd_mask = 0;
+ link->l_dev = NULL;
+ link->req.in_q = NULL;
+ link->req.l_tbl = NULL;
+ link->req.num_tbl = 0;
+ link->watchdog = NULL;
+ link->state = CAM_CRM_LINK_STATE_AVAILABLE;
+ link->parent = NULL;
+ link->subscribe_event = 0;
+ link->trigger_mask = 0;
+ link->sync_link = 0;
+ link->sync_link_sof_skip = false;
+ link->open_req_cnt = 0;
+ link->last_flush_id = 0;
+ link->initial_sync_req = -1;
+ link->in_msync_mode = false;
+}
void cam_req_mgr_handle_core_shutdown(void)
{
@@ -117,31 +142,35 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val)
}
/**
- * __cam_req_mgr_validate_inject_delay()
+ * __cam_req_mgr_inject_delay()
*
- * @brief : Check if any pd device is introducing inject delay
+ * @brief : Check if any pd device is injecting delay
* @tbl : cam_req_mgr_req_tbl
* @curr_idx : slot idx
*
* @return : 0 for success, negative for failure
*/
-static int __cam_req_mgr_validate_inject_delay(
+static int __cam_req_mgr_inject_delay(
struct cam_req_mgr_req_tbl *tbl,
int32_t curr_idx)
{
struct cam_req_mgr_tbl_slot *slot = NULL;
+ int rc = 0;
while (tbl) {
slot = &tbl->slot[curr_idx];
if (slot->inject_delay > 0) {
slot->inject_delay--;
- return -EAGAIN;
+ CAM_DBG(CAM_CRM,
+ "Delay injected by pd %d device",
+ tbl->pd);
+ rc = -EAGAIN;
}
__cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta,
tbl->num_slots);
tbl = tbl->next;
}
- return 0;
+ return rc;
}
/**
@@ -183,19 +212,6 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status,
traverse_data->in_q->slot[curr_idx].skip_idx);
- if ((traverse_data->self_link == true) &&
- (!traverse_data->inject_delay_chk)) {
- rc = __cam_req_mgr_validate_inject_delay(tbl, curr_idx);
- if (rc) {
- CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
- apply_data[tbl->pd].req_id = -1;
- /* This pd tbl not ready to proceed with asked idx */
- SET_FAILURE_BIT(traverse_data->result, tbl->pd);
- return -EAGAIN;
- }
- traverse_data->inject_delay_chk = true;
- }
-
/* Check if req is ready or in skip mode or pd tbl is in skip mode */
if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY ||
traverse_data->in_q->slot[curr_idx].skip_idx == 1 ||
@@ -356,6 +372,30 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
}
/**
+ * __cam_req_mgr_check_for_lower_pd_devices()
+ *
+ * @brief : Checks if there are any devices on the link having a lesser
+ * pd than the max pd of the link
+ * @link : Pointer to link which needs to be checked
+ *
+ * @return : 0 if a lower pd device is found negative otherwise
+ */
+static int __cam_req_mgr_check_for_lower_pd_devices(
+ struct cam_req_mgr_core_link *link)
+{
+ int i = 0;
+ struct cam_req_mgr_connected_device *dev = NULL;
+
+ for (i = 0; i < link->num_devs; i++) {
+ dev = &link->l_dev[i];
+ if (dev->dev_info.p_delay < link->max_delay)
+ return 0;
+ }
+
+ return -EAGAIN;
+}
+
+/**
* __cam_req_mgr_check_next_req_slot()
*
* @brief : While streaming if input queue does not contain any pending
@@ -363,11 +403,14 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
* devices with lower pipeline delay value.
* @in_q : Pointer to input queue where req mgr wil peep into
*
+ * @return : 0 for success, negative for failure
*/
-static void __cam_req_mgr_check_next_req_slot(
- struct cam_req_mgr_req_queue *in_q)
+static int __cam_req_mgr_check_next_req_slot(
+ struct cam_req_mgr_core_link *link)
{
- int32_t idx = in_q->rd_idx;
+ int rc = 0;
+ struct cam_req_mgr_req_queue *in_q = link->req.in_q;
+ int32_t idx = in_q->rd_idx;
struct cam_req_mgr_slot *slot;
__cam_req_mgr_inc_idx(&idx, 1, in_q->num_slots);
@@ -377,12 +420,20 @@ static void __cam_req_mgr_check_next_req_slot(
/* Check if there is new req from CSL, if not complete req */
if (slot->status == CRM_SLOT_STATUS_NO_REQ) {
+ rc = __cam_req_mgr_check_for_lower_pd_devices(link);
+ if (rc) {
+ CAM_DBG(CAM_CRM, "No lower pd devices on link 0x%x",
+ link->link_hdl);
+ return rc;
+ }
__cam_req_mgr_in_q_skip_idx(in_q, idx);
if (in_q->wr_idx != idx)
CAM_WARN(CAM_CRM,
"CHECK here wr %d, rd %d", in_q->wr_idx, idx);
__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
}
+
+ return rc;
}
/**
@@ -483,8 +534,6 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
continue;
}
- trace_cam_req_mgr_apply_request(link, &apply_req, dev);
-
apply_req.trigger_point = trigger;
CAM_DBG(CAM_REQ,
"SEND: link_hdl: %x pd %d req_id %lld",
@@ -497,6 +546,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
if (pd == link->max_delay)
link->open_req_cnt--;
}
+ trace_cam_req_mgr_apply_request(link, &apply_req, dev);
}
}
if (rc < 0) {
@@ -526,14 +576,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
* traversed through
* @idx : index within input request queue
* @validate_only : Whether to validate only and/or update settings
- * @self_link : To indicate whether the validation is for the given link or
- * other sync link
*
* @return : 0 for success, negative for failure
*
*/
static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
- int32_t idx, bool validate_only, bool self_link)
+ int32_t idx, bool validate_only)
{
int rc;
struct cam_req_mgr_traverse traverse_data;
@@ -555,19 +603,16 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
traverse_data.in_q = in_q;
traverse_data.result = 0;
traverse_data.validate_only = validate_only;
- traverse_data.self_link = self_link;
- traverse_data.inject_delay_chk = false;
traverse_data.open_req_cnt = link->open_req_cnt;
+
/*
* Traverse through all pd tables, if result is success,
* apply the settings
*/
-
rc = __cam_req_mgr_traverse(&traverse_data);
CAM_DBG(CAM_CRM,
- "SOF: idx %d self_link %d validate %d result %x pd_mask %x rc %d",
- idx, traverse_data.self_link, traverse_data.validate_only,
- traverse_data.result, link->pd_mask, rc);
+ "SOF: idx %d result %x pd_mask %x rc %d",
+ idx, traverse_data.result, link->pd_mask, rc);
if (!rc && traverse_data.result == link->pd_mask) {
CAM_DBG(CAM_CRM,
@@ -616,113 +661,218 @@ static int32_t __cam_req_mgr_find_slot_for_req(
}
/**
- * __cam_req_mgr_reset_sof_cnt()
+ * __cam_req_mgr_check_sync_for_mslave()
*
- * @brief : the sof_count for both the links are reset
- * @link : pointer to link whose input queue and req tbl are
+ * @brief : Processes requests during sync mode [master-slave]
+ * Here master corresponds to the link having a higher
+ * max_delay (pd) compared to the slave link.
+ * @link : Pointer to link whose input queue and req tbl are
* traversed through
+ * @slot : Pointer to the current slot being processed
+ * @return : 0 for success, negative for failure
*
*/
-static void __cam_req_mgr_reset_sof_cnt(
- struct cam_req_mgr_core_link *link)
+static int __cam_req_mgr_check_sync_for_mslave(
+ struct cam_req_mgr_core_link *link,
+ struct cam_req_mgr_slot *slot)
{
- link->sof_counter = -1;
- link->sync_link->sof_counter = -1;
- link->frame_skip_flag = false;
+ struct cam_req_mgr_core_link *sync_link = NULL;
+ struct cam_req_mgr_slot *sync_slot = NULL;
+ int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, sync_rd_idx, rc = 0;
+ int64_t req_id = 0, sync_req_id = 0;
- CAM_DBG(CAM_CRM,
- "link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d",
- link->link_hdl, link->sof_counter,
- link->sync_link->sof_counter, link->frame_skip_flag);
-}
+ if (!link->sync_link) {
+ CAM_ERR(CAM_CRM, "Sync link null");
+ return -EINVAL;
+ }
-/**
- * __cam_req_mgr_sof_cnt_initialize()
- *
- * @brief : when the sof count is intially -1 it increments count
- * and computes the sync_self_ref for this link
- * the count needs to be wrapped back starting from 0
- * @link : pointer to link whose input queue and req tbl are
- * traversed through
- *
- */
-static void __cam_req_mgr_sof_cnt_initialize(
- struct cam_req_mgr_core_link *link)
-{
- link->sof_counter++;
- link->sync_self_ref = link->sof_counter -
- link->sync_link->sof_counter;
+ sync_link = link->sync_link;
+ req_id = slot->req_id;
+ sync_rd_idx = sync_link->req.in_q->rd_idx;
CAM_DBG(CAM_CRM,
- "link_hdl %x self_counter %lld other_counter %lld",
- link->link_hdl, link->sof_counter,
- link->sync_link->sof_counter);
-}
+ "link_hdl %x req %lld frame_skip_flag %d open_req_cnt:%d initial_sync_req [%lld,%lld] is_master:%d",
+ link->link_hdl, req_id, link->sync_link_sof_skip,
+ link->open_req_cnt, link->initial_sync_req,
+ sync_link->initial_sync_req, link->is_master);
-/**
- * __cam_req_mgr_wrap_sof_cnt()
- *
- * @brief : once the sof count reaches a predefined maximum
- * the count needs to be wrapped back starting from 0
- * @link : pointer to link whose input queue and req tbl are
- * traversed through
- *
- */
-static void __cam_req_mgr_wrap_sof_cnt(
- struct cam_req_mgr_core_link *link)
-{
- link->sof_counter = (MAX_SYNC_COUNT -
- (link->sync_link->sof_counter));
- link->sync_link->sof_counter = 0;
+ if (sync_link->sync_link_sof_skip) {
+ CAM_DBG(CAM_CRM,
+ "No req applied on corresponding SOF on sync link: %x",
+ sync_link->link_hdl);
+ sync_link->sync_link_sof_skip = false;
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ return -EAGAIN;
+ }
- CAM_DBG(CAM_CRM,
- "link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld",
- link->link_hdl, link->sof_counter,
- link->sync_link->link_hdl, link->sync_link->sof_counter);
-}
+ if (link->in_msync_mode &&
+ sync_link->in_msync_mode &&
+ (req_id - sync_link->req.in_q->slot[sync_rd_idx].req_id >
+ link->max_delay - sync_link->max_delay)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld on link:%x need to hold for link: %x req:%d",
+ req_id,
+ link->link_hdl,
+ sync_link->link_hdl,
+ sync_link->req.in_q->slot[sync_rd_idx].req_id);
+ return -EINVAL;
+ }
-/**
- * __cam_req_mgr_validate_sof_cnt()
- *
- * @brief : validates sof count difference for a given link
- * @link : pointer to link whose input queue and req tbl are
- * traversed through
- * @sync_link : pointer to the sync link
- * @return : 0 for success, negative for failure
- *
- */
-static int __cam_req_mgr_validate_sof_cnt(
- struct cam_req_mgr_core_link *link,
- struct cam_req_mgr_core_link *sync_link)
-{
- int64_t sync_diff = 0;
- int rc = 0;
+ if (link->is_master) {
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Skip Process Req: %lld on link: %x",
+ req_id, link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+
+ if (sync_link->initial_skip) {
+ CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on",
+ sync_link->link_hdl);
+ return -EAGAIN;
+ }
- if (link->sof_counter == MAX_SYNC_COUNT)
- __cam_req_mgr_wrap_sof_cnt(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",
+ req_id, link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
- sync_diff = link->sof_counter - sync_link->sof_counter;
+ 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;
+ }
- CAM_DBG(CAM_CRM,
- "link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld",
- link->link_hdl, link->sof_counter,
- sync_link->sof_counter, sync_diff, link->sync_self_ref);
-
- if (sync_diff > SYNC_LINK_SOF_CNT_MAX_LMT) {
- link->sync_link->frame_skip_flag = true;
- CAM_WARN(CAM_CRM,
- "Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld",
- link->link_hdl, link->sof_counter,
- sync_link->sof_counter, link->sync_self_ref);
- rc = -EPERM;
+ if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED) &&
+ ((sync_slot_idx - rd_idx) >= 1) &&
+ (sync_link->req.in_q->slot[rd_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Prev Req: %lld [master] not next on link: %x [slave]",
+ sync_req_id,
+ sync_link->link_hdl);
+ return -EINVAL;
+ }
+
+ rc = __cam_req_mgr_check_link_is_ready(sync_link,
+ sync_slot_idx, true);
+ if (rc &&
+ (sync_link->req.in_q->slot[sync_slot_idx].status
+ != CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld not ready on [slave] link: %x, rc=%d",
+ sync_req_id, sync_link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+ }
+ } else {
+ if (link->initial_skip)
+ link->initial_skip = false;
+
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Skip Process Req: %lld on link: %x",
+ req_id, link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld [slave] not ready on link: %x, rc=%d",
+ req_id, link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+
+ next_idx = link->req.in_q->rd_idx;
+ rd_idx = sync_link->req.in_q->rd_idx;
+ __cam_req_mgr_inc_idx(&next_idx,
+ (sync_link->max_delay - link->max_delay),
+ link->req.in_q->num_slots);
+
+ sync_req_id = link->req.in_q->slot[next_idx].req_id;
+
+ if ((sync_link->initial_sync_req != -1) &&
+ (sync_link->initial_sync_req <= sync_req_id)) {
+ sync_slot_idx = __cam_req_mgr_find_slot_for_req(
+ sync_link->req.in_q, sync_req_id);
+ if (sync_slot_idx == -1) {
+ CAM_DBG(CAM_CRM,
+ "Next Req: %lld [slave] not found on link: %x [master]",
+ sync_req_id, sync_link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return -EINVAL;
+ }
+
+ if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED) &&
+ ((sync_slot_idx - rd_idx) >= 1) &&
+ (sync_link->req.in_q->slot[rd_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Next Req: %lld [slave] not next on link: %x [master]",
+ sync_req_id, sync_link->link_hdl);
+ return -EINVAL;
+ }
+
+ sync_slot = &sync_link->req.in_q->slot[sync_slot_idx];
+ rc = __cam_req_mgr_check_link_is_ready(sync_link,
+ sync_slot_idx, true);
+ if (rc && (sync_slot->status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Next Req: %lld [slave] not ready on [master] link: %x, rc=%d",
+ sync_req_id, sync_link->link_hdl, rc);
+ link->sync_link_sof_skip = true;
+ return rc;
+ }
+ }
}
- return rc;
+ CAM_DBG(CAM_REQ,
+ "Req: %lld ready to apply on link: %x [validation successful]",
+ req_id, link->link_hdl);
+
+ /*
+ * At this point all validation is successfully done
+ * and we can proceed to apply the given request.
+ * Ideally the next call should return success.
+ */
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+ if (rc)
+ CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
+
+ return 0;
}
/**
- * __cam_req_mgr_process_sync_req()
+ * __cam_req_mgr_check_sync_request_is_ready()
*
* @brief : processes requests during sync mode
* @link : pointer to link whose input queue and req tbl are
@@ -731,13 +881,13 @@ static int __cam_req_mgr_validate_sof_cnt(
* @return : 0 for success, negative for failure
*
*/
-static int __cam_req_mgr_process_sync_req(
+static int __cam_req_mgr_check_sync_req_is_ready(
struct cam_req_mgr_core_link *link,
struct cam_req_mgr_slot *slot)
{
struct cam_req_mgr_core_link *sync_link = NULL;
int64_t req_id = 0;
- int sync_slot_idx = 0, rc = 0;
+ int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
if (!link->sync_link) {
CAM_ERR(CAM_CRM, "Sync link null");
@@ -748,94 +898,81 @@ static int __cam_req_mgr_process_sync_req(
req_id = slot->req_id;
CAM_DBG(CAM_REQ,
- "link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
- link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
- link->frame_skip_flag, link->sync_link->sync_self_ref);
+ "link_hdl %x req %lld frame_skip_flag %d ",
+ link->link_hdl, req_id, link->sync_link_sof_skip);
if (sync_link->sync_link_sof_skip) {
CAM_DBG(CAM_REQ,
"No req applied on corresponding SOF on sync link: %x",
sync_link->link_hdl);
sync_link->sync_link_sof_skip = false;
- /*It is to manage compensate inject delay for each pd*/
- __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
- return -EINVAL;
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ return -EAGAIN;
}
- if (link->sof_counter == -1) {
- __cam_req_mgr_sof_cnt_initialize(link);
- } else if ((link->frame_skip_flag) &&
- (sync_link->sync_self_ref != -1)) {
- CAM_DBG(CAM_REQ, "Link[%x] Req[%lld] Resetting values ",
- link->link_hdl, req_id);
- __cam_req_mgr_reset_sof_cnt(link);
- __cam_req_mgr_sof_cnt_initialize(link);
- } else {
- link->sof_counter++;
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM,
+ "Skip Process Req: %lld on link: %x",
+ req_id, link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return rc;
}
- rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
if (rc) {
- CAM_DBG(CAM_REQ,
+ CAM_DBG(CAM_CRM,
"Req: %lld [My link] not ready on link: %x, rc=%d",
req_id, link->link_hdl, rc);
link->sync_link_sof_skip = true;
- goto failure;
+ return rc;
}
sync_slot_idx = __cam_req_mgr_find_slot_for_req(
sync_link->req.in_q, req_id);
-
- if (sync_slot_idx != -1) {
- rc = __cam_req_mgr_check_link_is_ready(
- sync_link, sync_slot_idx, true, false);
- CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
- sync_slot_idx,
- sync_link->req.in_q->slot[sync_slot_idx].status,
- rc);
- } else {
- CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d",
- sync_slot_idx, rc);
+ if (sync_slot_idx == -1) {
+ CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]",
+ req_id, sync_link->link_hdl);
+ link->sync_link_sof_skip = true;
+ return -EINVAL;
}
- if ((sync_slot_idx != -1) &&
- ((sync_link->req.in_q->slot[sync_slot_idx].status ==
- CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
- rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
- if (rc) {
- CAM_DBG(CAM_CRM,
- "Req: %lld validate failed: %x",
- req_id, sync_link->link_hdl);
- goto failure;
- }
-
- CAM_DBG(CAM_REQ,
- "Req: %lld ready to apply on link: %x [validation successful]",
- req_id, link->link_hdl);
- /*
- * At this point all validation is successfully done
- * and we can proceed to apply the given request.
- * Ideally the next call should return success.
- */
- rc = __cam_req_mgr_check_link_is_ready(link,
- slot->idx, false, true);
-
- if (rc)
- CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
- } else {
- CAM_DBG(CAM_REQ,
- "Req: %lld [Other link] not ready to apply on link: %x",
+ sync_rd_idx = sync_link->req.in_q->rd_idx;
+ if ((sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED) &&
+ ((sync_slot_idx - sync_rd_idx) >= 1) &&
+ (sync_link->req.in_q->slot[sync_rd_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld [other link] not next req to be applied on link: %x",
req_id, sync_link->link_hdl);
- rc = -EPERM;
+ return -EAGAIN;
+ }
+
+ rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true);
+ if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status !=
+ CRM_SLOT_STATUS_REQ_APPLIED)) {
+ CAM_DBG(CAM_CRM,
+ "Req: %lld not ready on [other link] link: %x, rc=%d",
+ req_id, sync_link->link_hdl, rc);
link->sync_link_sof_skip = true;
- goto failure;
+ return rc;
}
- return rc;
+ CAM_DBG(CAM_REQ,
+ "Req: %lld ready to apply on link: %x [validation successful]",
+ req_id, link->link_hdl);
-failure:
- link->sof_counter--;
- return rc;
+ /*
+ * At this point all validation is successfully done
+ * and we can proceed to apply the given request.
+ * Ideally the next call should return success.
+ */
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false);
+ if (rc)
+ CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
+
+ return 0;
}
/**
@@ -852,6 +989,7 @@ 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;
@@ -896,11 +1034,41 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
goto error;
}
- if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)
- rc = __cam_req_mgr_process_sync_req(link, slot);
- else
- rc = __cam_req_mgr_check_link_is_ready(link,
- slot->idx, false, true);
+ if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) &&
+ (link->sync_link)) {
+ if (link->is_master || link->sync_link->is_master) {
+ if (!link->in_msync_mode) {
+ CAM_DBG(CAM_CRM,
+ "Settings master-slave sync mode for link 0x%x",
+ link->link_hdl);
+ link->in_msync_mode = true;
+ }
+
+ rc = __cam_req_mgr_check_sync_for_mslave(
+ link, slot);
+ } else {
+ rc = __cam_req_mgr_check_sync_req_is_ready(
+ link, slot);
+ }
+ } else {
+ if (link->in_msync_mode) {
+ CAM_DBG(CAM_CRM,
+ "Settings master-slave non sync mode for link 0x%x",
+ link->link_hdl);
+ link->in_msync_mode = false;
+ link->initial_sync_req = -1;
+ if (link->sync_link) {
+ link->sync_link->initial_sync_req = -1;
+ link->sync_link->in_msync_mode = false;
+ }
+ }
+
+ rc = __cam_req_mgr_inject_delay(link->req.l_tbl,
+ slot->idx);
+ if (!rc)
+ rc = __cam_req_mgr_check_link_is_ready(link,
+ slot->idx, false);
+ }
if (rc < 0) {
/*
@@ -954,8 +1122,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
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, link->max_delay + 1,
+ &idx, reset_step + 1,
in_q->num_slots);
__cam_req_mgr_reset_req_slot(link, idx);
}
@@ -1344,25 +1519,25 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
session->num_links, MAXIMUM_LINKS_PER_SESSION);
return NULL;
}
-
- link = (struct cam_req_mgr_core_link *)
- kzalloc(sizeof(struct cam_req_mgr_core_link), GFP_KERNEL);
- if (!link) {
- CAM_ERR(CAM_CRM, "failed to create link, no mem");
- return NULL;
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
+ if (!atomic_cmpxchg(&g_links[i].is_used, 0, 1)) {
+ link = &g_links[i];
+ CAM_DBG(CAM_CRM, "alloc link index %d", i);
+ cam_req_mgr_core_link_reset(link);
+ break;
+ }
}
+ if (i == MAXIMUM_LINKS_PER_SESSION)
+ return NULL;
+
in_q = (struct cam_req_mgr_req_queue *)
kzalloc(sizeof(struct cam_req_mgr_req_queue), GFP_KERNEL);
if (!in_q) {
CAM_ERR(CAM_CRM, "failed to create input queue, no mem");
- kfree(link);
return NULL;
}
- mutex_init(&link->lock);
- spin_lock_init(&link->link_state_spin_lock);
mutex_lock(&link->lock);
- link->state = CAM_CRM_LINK_STATE_AVAILABLE;
link->num_devs = 0;
link->max_delay = 0;
memset(in_q->slot, 0,
@@ -1399,7 +1574,6 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
return link;
error:
mutex_unlock(&session->lock);
- kfree(link);
kfree(in_q);
return NULL;
}
@@ -1414,9 +1588,12 @@ error:
*/
static void __cam_req_mgr_free_link(struct cam_req_mgr_core_link *link)
{
+ ptrdiff_t i;
kfree(link->req.in_q);
link->req.in_q = NULL;
- kfree(link);
+ i = link - g_links;
+ CAM_DBG(CAM_CRM, "free link index %d", i);
+ atomic_set(&g_links[i].is_used, 0);
}
/**
@@ -1450,21 +1627,14 @@ static void __cam_req_mgr_unreserve_link(
for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
if (session->links[i] == link)
session->links[i] = NULL;
- }
- if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) &&
- (link->sync_link)) {
- /*
- * make sure to unlink sync setup under the assumption
- * of only having 2 links in a given session
- */
- session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC;
- for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
- if (session->links[i])
+ if (link->sync_link) {
+ if (link->sync_link == session->links[i])
session->links[i]->sync_link = NULL;
}
}
+ link->sync_link = NULL;
session->num_links--;
CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
mutex_unlock(&session->lock);
@@ -1544,6 +1714,9 @@ int cam_req_mgr_process_flush_req(void *priv, void *data)
mutex_lock(&link->req.lock);
if (flush_info->flush_type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ link->last_flush_id = flush_info->req_id;
+ CAM_INFO(CAM_CRM, "Last request id to flush is %lld",
+ flush_info->req_id);
for (i = 0; i < in_q->num_slots; i++) {
slot = &in_q->slot[i];
slot->req_id = -1;
@@ -1559,21 +1732,20 @@ int cam_req_mgr_process_flush_req(void *priv, void *data)
if (idx < 0) {
CAM_ERR(CAM_CRM, "req_id %lld not found in input queue",
flush_info->req_id);
- mutex_unlock(&link->req.lock);
- return -EINVAL;
- }
- CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
- flush_info->req_id, idx);
- slot = &in_q->slot[idx];
- if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
- slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
- CAM_WARN(CAM_CRM,
- "req_id %lld can not be cancelled",
- flush_info->req_id);
- mutex_unlock(&link->req.lock);
- return -EINVAL;
+ } else {
+ CAM_DBG(CAM_CRM, "req_id %lld found at idx %d",
+ flush_info->req_id, idx);
+ slot = &in_q->slot[idx];
+ if (slot->status == CRM_SLOT_STATUS_REQ_PENDING ||
+ slot->status == CRM_SLOT_STATUS_REQ_APPLIED) {
+ CAM_WARN(CAM_CRM,
+ "req_id %lld can not be cancelled",
+ flush_info->req_id);
+ mutex_unlock(&link->req.lock);
+ return -EINVAL;
+ }
+ __cam_req_mgr_in_q_skip_idx(in_q, idx);
}
- __cam_req_mgr_in_q_skip_idx(in_q, idx);
}
for (i = 0; i < link->num_devs; i++) {
@@ -1622,9 +1794,11 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
sched_req = (struct cam_req_mgr_sched_request *)&task_data->u;
in_q = link->req.in_q;
- CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld at slot %d sync_mode %d",
+ CAM_DBG(CAM_CRM,
+ "link_hdl %x req_id %lld at slot %d sync_mode %d is_master:%d",
sched_req->link_hdl, sched_req->req_id,
- in_q->wr_idx, sched_req->sync_mode);
+ in_q->wr_idx, sched_req->sync_mode,
+ link->is_master);
mutex_lock(&link->req.lock);
slot = &in_q->slot[in_q->wr_idx];
@@ -1640,6 +1814,16 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
slot->recover = sched_req->bubble_enable;
link->open_req_cnt++;
__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
+
+ if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
+ if (link->initial_sync_req == -1)
+ link->initial_sync_req = slot->req_id;
+ } else {
+ link->initial_sync_req = -1;
+ if (link->sync_link)
+ link->sync_link->initial_sync_req = -1;
+ }
+
mutex_unlock(&link->req.lock);
end:
@@ -1736,8 +1920,9 @@ int cam_req_mgr_process_add_req(void *priv, void *data)
trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
if (slot->req_ready_map == tbl->dev_mask) {
- CAM_DBG(CAM_REQ, "idx %d req_id %lld pd %d SLOT READY",
- idx, add_req->req_id, tbl->pd);
+ CAM_DBG(CAM_REQ,
+ "link 0x%x idx %d req_id %lld pd %d SLOT READY",
+ link->link_hdl, idx, add_req->req_id, tbl->pd);
slot->state = CRM_REQ_STATE_READY;
}
mutex_unlock(&link->req.lock);
@@ -1895,14 +2080,22 @@ static int cam_req_mgr_process_trigger(void *priv, void *data)
* Check if any new req is pending in slot, if not finish the
* lower pipeline delay device with available req ids.
*/
- CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
+ CAM_DBG(CAM_CRM, "link[%x] Req[%lld] invalidating slot",
link->link_hdl, in_q->slot[in_q->rd_idx].req_id);
- __cam_req_mgr_check_next_req_slot(in_q);
+ rc = __cam_req_mgr_check_next_req_slot(link);
+ if (rc) {
+ CAM_DBG(CAM_REQ,
+ "No pending req to apply to lower pd devices");
+ rc = 0;
+ goto release_lock;
+ }
__cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
}
+
rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
- mutex_unlock(&link->req.lock);
+release_lock:
+ mutex_unlock(&link->req.lock);
end:
return rc;
}
@@ -2368,7 +2561,8 @@ static int __cam_req_mgr_unlink(struct cam_req_mgr_core_link *link)
if (rc < 0) {
CAM_ERR(CAM_CRM, "error destroying link hdl %x rc %d",
link->link_hdl, rc);
- }
+ } else
+ link->link_hdl = -1;
mutex_unlock(&link->lock);
return rc;
@@ -2445,16 +2639,17 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
return -EINVAL;
}
+ mutex_lock(&g_crm_core_dev->crm_lock);
+
/* session hdl's priv data is cam session struct */
cam_session = (struct cam_req_mgr_core_session *)
cam_get_device_priv(link_info->session_hdl);
if (!cam_session) {
CAM_DBG(CAM_CRM, "NULL pointer");
+ mutex_unlock(&g_crm_core_dev->crm_lock);
return -EINVAL;
}
- mutex_lock(&g_crm_core_dev->crm_lock);
-
/* Allocate link struct and map it with session's request queue */
link = __cam_req_mgr_reserve_link(cam_session);
if (!link) {
@@ -2478,6 +2673,7 @@ int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
goto link_hdl_fail;
}
link_info->link_hdl = link->link_hdl;
+ link->last_flush_id = 0;
/* Allocate memory to hold data of all linked devs */
rc = __cam_req_mgr_create_subdevs(&link->l_dev,
@@ -2524,7 +2720,7 @@ setup_failed:
__cam_req_mgr_destroy_subdev(link->l_dev);
create_subdev_failed:
cam_destroy_device_hdl(link->link_hdl);
- link_info->link_hdl = 0;
+ link_info->link_hdl = -1;
link_hdl_fail:
mutex_unlock(&link->lock);
__cam_req_mgr_unreserve_link(cam_session, link);
@@ -2603,6 +2799,17 @@ int cam_req_mgr_schedule_request(
goto end;
}
+ if (sched_req->req_id <= link->last_flush_id) {
+ CAM_INFO(CAM_CRM,
+ "request %lld is flushed, last_flush_id to flush %d",
+ sched_req->req_id, link->last_flush_id);
+ rc = -EINVAL;
+ goto end;
+ }
+
+ if (sched_req->req_id > link->last_flush_id)
+ link->last_flush_id = 0;
+
CAM_DBG(CAM_CRM, "link 0x%x req %lld, sync_mode %d",
sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
@@ -2627,6 +2834,33 @@ end:
return rc;
}
+/**
+ * __cam_req_mgr_set_master_link()
+ *
+ * @brief : Each links sets its max pd delay based on the devices on the
+ * link. The link with higher pd is assigned master.
+ * @link1 : One of the sync links
+ * @link2 : The other sync link
+ */
+static void __cam_req_mgr_set_master_link(
+ struct cam_req_mgr_core_link *link1,
+ struct cam_req_mgr_core_link *link2)
+{
+
+ if (link1->max_delay > link2->max_delay) {
+ link1->is_master = true;
+ link2->initial_skip = true;
+ } else if (link2->max_delay > link1->max_delay) {
+ link2->is_master = true;
+ link1->initial_skip = true;
+ }
+
+ CAM_DBG(CAM_CRM,
+ "link_hdl1[0x%x] is_master [%u] link_hdl2[0x%x] is_master[%u]",
+ link1->link_hdl, link1->is_master,
+ link2->link_hdl, link2->is_master);
+}
+
int cam_req_mgr_sync_config(
struct cam_req_mgr_sync_mode *sync_info)
{
@@ -2647,6 +2881,12 @@ int cam_req_mgr_sync_config(
return -EINVAL;
}
+ if ((sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC) &&
+ (sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC)) {
+ CAM_ERR(CAM_CRM, "Invalid sync mode %d", sync_info->sync_mode);
+ return -EINVAL;
+ }
+
if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) {
CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x",
sync_info->link_hdls[0], sync_info->link_hdls[1]);
@@ -2683,17 +2923,27 @@ int cam_req_mgr_sync_config(
goto done;
}
- link1->sof_counter = -1;
- link1->sync_self_ref = -1;
- link1->frame_skip_flag = false;
link1->sync_link_sof_skip = false;
- link1->sync_link = link2;
+ link1->sync_link = NULL;
- link2->sof_counter = -1;
- link2->sync_self_ref = -1;
- link2->frame_skip_flag = false;
link2->sync_link_sof_skip = false;
- link2->sync_link = link1;
+ link2->sync_link = NULL;
+
+ link1->is_master = false;
+ link2->is_master = false;
+ link1->initial_skip = false;
+ link2->initial_skip = false;
+
+ link1->in_msync_mode = false;
+ link2->in_msync_mode = false;
+ link1->initial_sync_req = -1;
+ link2->initial_sync_req = -1;
+
+ if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
+ link1->sync_link = link2;
+ link2->sync_link = link1;
+ __cam_req_mgr_set_master_link(link1, link2);
+ }
cam_session->sync_mode = sync_info->sync_mode;
CAM_DBG(CAM_REQ,
@@ -2791,7 +3041,8 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
goto end;
}
- if (control->num_links > MAX_LINKS_PER_SESSION) {
+ if ((control->num_links <= 0) ||
+ (control->num_links > MAX_LINKS_PER_SESSION)) {
CAM_ERR(CAM_CRM, "Invalid number of links %d",
control->num_links);
rc = -EINVAL;
@@ -2860,6 +3111,7 @@ end:
int cam_req_mgr_core_device_init(void)
{
+ int i;
CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
if (g_crm_core_dev) {
@@ -2876,6 +3128,12 @@ int cam_req_mgr_core_device_init(void)
mutex_init(&g_crm_core_dev->crm_lock);
cam_req_mgr_debug_register(g_crm_core_dev);
+ for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
+ mutex_init(&g_links[i].lock);
+ spin_lock_init(&g_links[i].link_state_spin_lock);
+ atomic_set(&g_links[i].is_used, 0);
+ cam_req_mgr_core_link_reset(&g_links[i]);
+ }
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
index b7222237473b..9bff66b36ebb 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -135,9 +135,6 @@ enum cam_req_mgr_link_state {
* @apply_data : pointer which various tables will update during traverse
* @in_q : input request queue pointer
* @validate_only : Whether to validate only and/or update settings
- * @self_link : To indicate whether the check is for the given link or
- * the other sync link
- * @inject_delay_chk : if inject delay has been validated for all pd devices
* @open_req_cnt : Count of open requests yet to be serviced in the kernel.
*/
struct cam_req_mgr_traverse {
@@ -147,8 +144,6 @@ struct cam_req_mgr_traverse {
struct cam_req_mgr_apply *apply_data;
struct cam_req_mgr_req_queue *in_q;
bool validate_only;
- bool self_link;
- bool inject_delay_chk;
int32_t open_req_cnt;
};
@@ -308,15 +303,20 @@ struct cam_req_mgr_connected_device {
* notification to CRM at those hw events.
* @trigger_mask : mask on which irq the req is already applied
* @sync_link : pointer to the sync link for synchronization
- * @sof_counter : sof counter during sync_mode
- * @sync_self_ref : reference sync count against which the difference
- * between sync_counts for a given link is checked
- * @frame_skip_flag : flag that determines if a frame needs to be skipped
* @sync_link_sof_skip : flag determines if a pkt is not available for a given
* frame in a particular link skip corresponding
* frame in sync link as well.
* @open_req_cnt : Counter to keep track of open requests that are yet
* to be serviced in the kernel.
+ * @last_flush_id : Last request to flush
+ * @is_used : 1 if link is in use else 0
+ * @is_master : Based on pd among links, the link with the highest pd
+ * is assigned as master
+ * @initial_skip : Flag to determine if slave has started streaming in
+ * master-slave sync
+ * @in_msync_mode : Flag to determine if a link is in master-slave mode
+ * @initial_sync_req : The initial req which is required to sync with the
+ * other link
*
*/
struct cam_req_mgr_core_link {
@@ -336,11 +336,14 @@ struct cam_req_mgr_core_link {
uint32_t subscribe_event;
uint32_t trigger_mask;
struct cam_req_mgr_core_link *sync_link;
- int64_t sof_counter;
- int64_t sync_self_ref;
- bool frame_skip_flag;
bool sync_link_sof_skip;
int32_t open_req_cnt;
+ uint32_t last_flush_id;
+ atomic_t is_used;
+ bool is_master;
+ bool initial_skip;
+ bool in_msync_mode;
+ int64_t initial_sync_req;
};
/**
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h
index 1df3122109e6..1d1df45c6ea5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -50,7 +50,7 @@ typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *);
* @cam_req_mgr_link_setup : to establish link with device for a session
* @cam_req_mgr_notify_err : to broadcast error happened on link for request id
* @cam_req_mgr_apply_req : CRM asks device to apply certain request id.
- * @cam_req_mgr_flush_req : Flush or cancle request
+ * @cam_req_mgr_flush_req : Flush or cancel request
* cam_req_mgr_process_evt : generic events
*/
typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *);
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c
index 12bc3ac47a8e..de6a2dc519df 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -224,8 +224,8 @@ int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
crm_workq->in_irq = in_irq;
crm_workq->task.num_task = num_tasks;
crm_workq->task.pool = (struct crm_workq_task *)
- kzalloc(sizeof(struct crm_workq_task) *
- crm_workq->task.num_task,
+ kcalloc(crm_workq->task.num_task,
+ sizeof(struct crm_workq_task),
GFP_KERNEL);
if (!crm_workq->task.pool) {
CAM_WARN(CAM_CRM, "Insufficient memory %zu",
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h
index af76ae467346..c24ee31959d6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_workq.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,7 +26,8 @@
/* Flag to create a high priority workq */
#define CAM_WORKQ_FLAG_HIGH_PRIORITY (1 << 0)
-/* This flag ensures only one task from a given
+/*
+ * This flag ensures only one task from a given
* workq will execute at any given point on any
* given CPU.
*/
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
index b2a7dc0784f4..1262db7646dc 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
#include "cam_trace.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
int32_t cam_actuator_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -214,12 +215,12 @@ static int32_t cam_actuator_i2c_modes_util(
}
int32_t cam_actuator_slaveInfo_pkt_parser(struct cam_actuator_ctrl_t *a_ctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info;
- if (!a_ctrl || !cmd_buf) {
+ if (!a_ctrl || !cmd_buf || (len < sizeof(struct cam_cmd_i2c_info))) {
CAM_ERR(CAM_ACTUATOR, "Invalid Args");
return -EINVAL;
}
@@ -413,9 +414,11 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
int32_t i = 0;
uint32_t total_cmd_buf_in_bytes = 0;
size_t len_of_buff = 0;
+ size_t remain_len = 0;
uint32_t *offset = NULL;
uint32_t *cmd_buf = NULL;
uintptr_t generic_ptr;
+ uintptr_t generic_pkt_ptr;
struct common_header *cmm_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
@@ -442,23 +445,36 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
sizeof(config)))
return -EFAULT;
rc = cam_mem_get_cpu_buf(config.packet_handle,
- &generic_ptr, &len_of_buff);
+ &generic_pkt_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Error in converting command Handle %d",
rc);
return rc;
}
- if (config.offset > len_of_buff) {
+ remain_len = len_of_buff;
+ if ((sizeof(struct cam_packet) > len_of_buff) ||
+ ((size_t)config.offset >= len_of_buff -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_ACTUATOR,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buff);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buff);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
- csl_packet =
- (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
- CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
+ remain_len -= (size_t)config.offset;
+ csl_packet = (struct cam_packet *)
+ (generic_pkt_ptr + (uint32_t)config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_ACTUATOR, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ CAM_DBG(CAM_ACTUATOR, "Pkt opcode: %d", csl_packet->header.op_code);
if ((csl_packet->header.op_code & 0xFFFFFF) !=
CAM_ACTUATOR_PACKET_OPCODE_INIT &&
@@ -467,7 +483,8 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR,
"reject request %lld, last request to flush %lld",
csl_packet->header.request_id, a_ctrl->last_flush_req);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
if (csl_packet->header.request_id > a_ctrl->last_flush_req)
@@ -488,13 +505,22 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
&generic_ptr, &len_of_buff);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Failed to get cpu buf");
- return rc;
+ goto rel_pkt_buf;
}
cmd_buf = (uint32_t *)generic_ptr;
if (!cmd_buf) {
CAM_ERR(CAM_ACTUATOR, "invalid cmd buf");
- return -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (len_of_buff -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_ACTUATOR,
+ "Invalid length for sensor cmd");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ remain_len = len_of_buff - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmm_hdr = (struct common_header *)cmd_buf;
@@ -503,11 +529,11 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_DBG(CAM_ACTUATOR,
"Received slave info buffer");
rc = cam_actuator_slaveInfo_pkt_parser(
- a_ctrl, cmd_buf);
+ a_ctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Failed to parse slave info: %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
break;
case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
@@ -517,12 +543,12 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- power_info);
+ power_info, remain_len);
if (rc) {
CAM_ERR(CAM_ACTUATOR,
"Failed:parse power settings: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
break;
default:
@@ -542,10 +568,14 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_ERR(CAM_ACTUATOR,
"Failed:parse init settings: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
break;
}
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_ACTUATOR,
+ "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
}
if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) {
@@ -553,7 +583,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
" Actuator Power up failed");
- return rc;
+ goto rel_pkt_buf;
}
a_ctrl->cam_act_state = CAM_ACTUATOR_CONFIG;
}
@@ -562,7 +592,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
&a_ctrl->i2c_data.init_settings);
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings");
- return rc;
+ goto rel_pkt_buf;
}
/* Delete the request even if the apply is failed */
@@ -579,7 +609,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_WARN(CAM_ACTUATOR,
"Not in right state to move lens: %d",
a_ctrl->cam_act_state);
- return rc;
+ goto rel_pkt_buf;
}
a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_NOW;
@@ -599,7 +629,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Auto move lens parsing failed: %d", rc);
- return rc;
+ goto rel_pkt_buf;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
@@ -609,7 +639,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_WARN(CAM_ACTUATOR,
"Not in right state to move lens: %d",
a_ctrl->cam_act_state);
- return rc;
+ goto rel_pkt_buf;
}
a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_LATER;
@@ -630,7 +660,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
if (rc < 0) {
CAM_ERR(CAM_ACTUATOR,
"Manual move lens parsing failed: %d", rc);
- return rc;
+ goto rel_pkt_buf;
}
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
@@ -640,13 +670,32 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl,
CAM_WARN(CAM_ACTUATOR,
"Received NOP packets in invalid state: %d",
a_ctrl->cam_act_state);
- return -EINVAL;
+ goto rel_pkt_buf;
}
-
cam_actuator_update_req_mgr(a_ctrl, csl_packet);
break;
+ default:
+ CAM_ERR(CAM_ACTUATOR, "Wrong Opcode: %d",
+ csl_packet->header.op_code & 0xFFFFFF);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_ACTUATOR, "Fail to put cmd buffer: %llu",
+ config.packet_handle);
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_ACTUATOR, "Fail to put cmd buffer: %d",
+ cmd_desc[i].mem_handle);
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_ACTUATOR, "Fail to put cmd buffer: %llu",
+ config.packet_handle);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index 26d73a446a5b..228ccb8a39b3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_actuator/cam_actuator_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -216,9 +216,7 @@ static int32_t cam_actuator_driver_i2c_probe(struct i2c_client *client,
cam_actuator_establish_link;
a_ctrl->bridge_intf.ops.apply_req =
cam_actuator_apply_request;
-
- v4l2_set_subdevdata(&(a_ctrl->v4l2_dev_str.sd), a_ctrl);
-
+ a_ctrl->last_flush_req = 0;
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
return rc;
@@ -245,19 +243,24 @@ static int32_t cam_actuator_platform_remove(struct platform_device *pdev)
return 0;
}
+ CAM_INFO(CAM_ACTUATOR, "platform remove invoked");
+ mutex_lock(&(a_ctrl->actuator_mutex));
+ cam_actuator_shutdown(a_ctrl);
+ mutex_unlock(&(a_ctrl->actuator_mutex));
+ cam_unregister_subdev(&(a_ctrl->v4l2_dev_str));
+
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
kfree(a_ctrl->io_master_info.cci_client);
a_ctrl->io_master_info.cci_client = NULL;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
kfree(a_ctrl->soc_info.soc_private);
+ a_ctrl->soc_info.soc_private = NULL;
kfree(a_ctrl->i2c_data.per_frame);
a_ctrl->i2c_data.per_frame = NULL;
+ v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL);
+ platform_set_drvdata(pdev, NULL);
devm_kfree(&pdev->dev, a_ctrl);
return rc;
@@ -265,7 +268,6 @@ static int32_t cam_actuator_platform_remove(struct platform_device *pdev)
static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client)
{
- int32_t rc = 0;
struct cam_actuator_ctrl_t *a_ctrl =
i2c_get_clientdata(client);
struct cam_actuator_soc_private *soc_private;
@@ -277,6 +279,11 @@ static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client)
return -EINVAL;
}
+ CAM_INFO(CAM_ACTUATOR, "i2c remove invoked");
+ mutex_lock(&(a_ctrl->actuator_mutex));
+ cam_actuator_shutdown(a_ctrl);
+ mutex_unlock(&(a_ctrl->actuator_mutex));
+ cam_unregister_subdev(&(a_ctrl->v4l2_dev_str));
soc_private =
(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
@@ -284,14 +291,11 @@ static int32_t cam_actuator_driver_i2c_remove(struct i2c_client *client)
/*Free Allocated Mem */
kfree(a_ctrl->i2c_data.per_frame);
a_ctrl->i2c_data.per_frame = NULL;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- kfree(a_ctrl->soc_info.soc_private);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
a_ctrl->soc_info.soc_private = NULL;
+ v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, NULL);
kfree(a_ctrl);
- return rc;
+
+ return 0;
}
static const struct of_device_id cam_actuator_driver_dt_match[] = {
@@ -376,7 +380,6 @@ static int32_t cam_actuator_driver_platform_probe(
a_ctrl->last_flush_req = 0;
platform_set_drvdata(pdev, a_ctrl);
- v4l2_set_subdevdata(&a_ctrl->v4l2_dev_str.sd, a_ctrl);
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
index b0e810711c5d..f41cb4753f39 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -892,20 +892,39 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
soc_info = &cci_dev->soc_info;
base = soc_info->reg_map[0].mem_base;
- mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
- /*
- * Todo: If there is a change in frequency of operation
- * Wait for previos transaction to complete
- */
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ if (cci_dev->cci_master_info[master].is_first_req == true) {
+ cci_dev->cci_master_info[master].is_first_req = false;
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else if (c_ctrl->cci_info->i2c_freq_mode
+ != cci_dev->i2c_freq_mode[master]) {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ cci_dev->cci_master_info[master].freq_ref_cnt++;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+ }
/* Set the I2C Frequency */
rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
if (rc < 0) {
CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
- goto rel_mutex;
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ goto rel_master;
}
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
/*
* Call validate queue to make sure queue is empty before starting.
* If this call fails, don't proceed with i2c_read call. This is to
@@ -916,24 +935,24 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
master, queue);
if (rc < 0) {
CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
CAM_ERR(CAM_CCI, "More than max retries");
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->data == NULL) {
CAM_ERR(CAM_CCI, "Data ptr is NULL");
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
read_cfg->addr_type);
rc = -EINVAL;
- goto rel_mutex;
+ goto rel_mutex_q;
}
CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
@@ -945,14 +964,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_LOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -964,21 +983,21 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_UNLOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1009,7 +1028,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
cam_cci_dump_registers(cci_dev, master, queue);
#endif
cam_cci_flush_queue(cci_dev, master);
- goto rel_mutex;
+ goto rel_mutex_q;
}
read_words = cam_io_r_mb(base +
@@ -1090,7 +1109,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
master, queue);
#endif
cam_cci_flush_queue(cci_dev, master);
- goto rel_mutex;
+ goto rel_mutex_q;
}
break;
}
@@ -1099,8 +1118,15 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
CAM_DBG(CAM_CCI, "Burst read successful words_read %d",
total_read_words);
-rel_mutex:
+rel_mutex_q:
mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+rel_master:
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+ up(&cci_dev->cci_master_info[master].master_sem);
+ else
+ cci_dev->cci_master_info[master].freq_ref_cnt--;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
return rc;
}
@@ -1132,20 +1158,38 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
soc_info = &cci_dev->soc_info;
base = soc_info->reg_map[0].mem_base;
- mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
-
- /*
- * Todo: If there is a change in frequency of operation
- * Wait for previos transaction to complete
- */
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ if (cci_dev->cci_master_info[master].is_first_req == true) {
+ cci_dev->cci_master_info[master].is_first_req = false;
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else if (c_ctrl->cci_info->i2c_freq_mode
+ != cci_dev->i2c_freq_mode[master]) {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ cci_dev->cci_master_info[master].freq_ref_cnt++;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+ }
/* Set the I2C Frequency */
rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
if (rc < 0) {
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
- goto rel_mutex;
+ goto rel_master;
}
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
/*
* Call validate queue to make sure queue is empty before starting.
* If this call fails, don't proceed with i2c_read call. This is to
@@ -1156,17 +1200,17 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
master, queue);
if (rc < 0) {
CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
CAM_ERR(CAM_CCI, "More than max retries");
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->data == NULL) {
CAM_ERR(CAM_CCI, "Data ptr is NULL");
- goto rel_mutex;
+ goto rel_mutex_q;
}
CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
@@ -1179,21 +1223,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_LOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
read_cfg->addr_type);
rc = -EINVAL;
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -1205,21 +1249,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = CCI_I2C_UNLOCK_CMD;
rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
if (rc < 0) {
CAM_DBG(CAM_CCI, "failed rc: %d", rc);
- goto rel_mutex;
+ goto rel_mutex_q;
}
val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1247,7 +1291,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
"wait_for_completion_timeout rc = %d FIFO buf_lvl: 0x%x",
rc, val);
cam_cci_flush_queue(cci_dev, master);
- goto rel_mutex;
+ goto rel_mutex_q;
} else {
rc = 0;
}
@@ -1260,7 +1304,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
read_words, exp_words);
memset(read_cfg->data, 0, read_cfg->num_byte);
rc = -EINVAL;
- goto rel_mutex;
+ goto rel_mutex_q;
}
index = 0;
CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
@@ -1284,8 +1328,15 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
}
read_words--;
}
-rel_mutex:
+rel_mutex_q:
mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
+rel_master:
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+ up(&cci_dev->cci_master_info[master].master_sem);
+ else
+ cci_dev->cci_master_info[master].freq_ref_cnt--;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
return rc;
}
@@ -1309,12 +1360,36 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
c_ctrl->cci_info->id_map);
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ if (cci_dev->cci_master_info[master].is_first_req == true) {
+ cci_dev->cci_master_info[master].is_first_req = false;
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else if (c_ctrl->cci_info->i2c_freq_mode
+ != cci_dev->i2c_freq_mode[master]) {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ down(&cci_dev->cci_master_info[master].master_sem);
+ } else {
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
+ master, cci_dev->i2c_freq_mode[master],
+ c_ctrl->cci_info->i2c_freq_mode);
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ cci_dev->cci_master_info[master].freq_ref_cnt++;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
+ }
+
/* Set the I2C Frequency */
rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
if (rc < 0) {
CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
- return rc;
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ goto ERROR;
}
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
/*
* Call validate queue to make sure queue is empty before starting.
* If this call fails, don't proceed with i2c_write call. This is to
@@ -1326,18 +1401,25 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
if (rc < 0) {
CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
rc);
- return rc;
+ goto ERROR;
}
if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
CAM_ERR(CAM_CCI, "More than max retries");
- return rc;
+ goto ERROR;
}
rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
if (rc < 0) {
CAM_ERR(CAM_CCI, "failed rc: %d", rc);
- return rc;
+ goto ERROR;
}
+ERROR:
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
+ if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
+ up(&cci_dev->cci_master_info[master].master_sem);
+ else
+ cci_dev->cci_master_info[master].freq_ref_cnt--;
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
index 5e522a8a5959..7934aa50767c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -151,7 +151,6 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
complete(&cci_dev->cci_master_info[MASTER_1].th_complete);
complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
}
- rd_done_th_assert = false;
if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) &&
(!rd_done_th_assert)) {
cci_dev->cci_master_info[MASTER_1].status = 0;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
index 12abeabe0a38..349effcc057b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/semaphore.h>
#include <media/cam_sensor.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
@@ -144,6 +145,10 @@ struct cam_cci_master_info {
struct completion report_q[NUM_QUEUES];
atomic_t done_pending[NUM_QUEUES];
spinlock_t lock_q[NUM_QUEUES];
+ spinlock_t freq_cnt;
+ struct semaphore master_sem;
+ bool is_first_req;
+ uint16_t freq_ref_cnt;
};
struct cam_cci_clk_params_t {
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
index da714af3fde2..7d71cd57573e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -196,7 +196,10 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
for (i = 0; i < NUM_MASTERS; i++) {
new_cci_dev->cci_master_info[i].status = 0;
+ new_cci_dev->cci_master_info[i].is_first_req = true;
mutex_init(&new_cci_dev->cci_master_info[i].mutex);
+ sema_init(&new_cci_dev->cci_master_info[i].master_sem, 1);
+ spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt);
init_completion(
&new_cci_dev->cci_master_info[i].reset_complete);
init_completion(
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 9894b217ac2c..17499489184b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,8 @@
#include "cam_csiphy_dev.h"
#include "cam_csiphy_soc.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
+
#include <soc/qcom/scm.h>
#include <cam_mem_mgr.h>
@@ -159,11 +161,13 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
{
int32_t rc = 0;
uintptr_t generic_ptr;
+ uintptr_t generic_pkt_ptr;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
uint32_t *cmd_buf = NULL;
struct cam_csiphy_info *cam_cmd_csiphy_info = NULL;
size_t len;
+ size_t remain_len;
if (!cfg_dev || !csiphy_dev) {
CAM_ERR(CAM_CSIPHY, "Invalid Args");
@@ -171,21 +175,32 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
}
rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle,
- &generic_ptr, &len);
+ &generic_pkt_ptr, &len);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc);
return rc;
}
- if (cfg_dev->offset > len) {
+ remain_len = len;
+ if ((sizeof(struct cam_packet) > len) ||
+ ((size_t)cfg_dev->offset >= len - sizeof(struct cam_packet))) {
CAM_ERR(CAM_CSIPHY,
- "offset is out of bounds: offset: %lld len: %zu",
- cfg_dev->offset, len);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+ remain_len -= (size_t)cfg_dev->offset;
csl_packet = (struct cam_packet *)
- (generic_ptr + (uint32_t)cfg_dev->offset);
+ (generic_pkt_ptr + (uint32_t)cfg_dev->offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_CSIPHY, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&csl_packet->payload +
@@ -196,7 +211,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
if (rc < 0) {
CAM_ERR(CAM_CSIPHY,
"Failed to get cmd buf Mem address : %d", rc);
- return rc;
+ goto rel_pkt_buf;
+ }
+
+ if ((len < sizeof(struct cam_csiphy_info)) ||
+ (cmd_desc->offset > (len - sizeof(struct cam_csiphy_info)))) {
+ CAM_ERR(CAM_CSIPHY,
+ "Not enough buffer provided for cam_cisphy_info");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
cmd_buf = (uint32_t *)generic_ptr;
@@ -221,6 +244,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
cam_csiphy_update_secure_info(csiphy_dev,
cam_cmd_csiphy_info, cfg_dev);
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_CSIPHY, "Failed to put cmd buffer: %d",
+ cmd_desc->mem_handle);
+
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf((int32_t) cfg_dev->packet_handle))
+ CAM_WARN(CAM_CSIPHY, "Failed to put packet Mem address: %llu",
+ cfg_dev->packet_handle);
+
return rc;
}
@@ -567,6 +599,14 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_create_dev_hdl bridge_params;
+ if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
+ CAM_ERR(CAM_CSIPHY,
+ "Not in right state to acquire : %d",
+ csiphy_dev->csiphy_state);
+ rc = -EINVAL;
+ goto release_mutex;
+ }
+
rc = copy_from_user(&csiphy_acq_dev,
u64_to_user_ptr(cmd->handle),
sizeof(csiphy_acq_dev));
@@ -826,6 +866,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
if (rc < 0) {
csiphy_dev->csiphy_info.secure_mode[offset] =
CAM_SECURE_MODE_NON_SECURE;
+ cam_cpas_stop(csiphy_dev->cpas_handle);
goto release_mutex;
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
index 32bb34bb257b..972b0a549f30 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -165,7 +165,6 @@ static int32_t cam_csiphy_platform_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, &(new_csiphy_dev->v4l2_dev_str.sd));
- v4l2_set_subdevdata(&(new_csiphy_dev->v4l2_dev_str.sd), new_csiphy_dev);
new_csiphy_dev->bridge_intf.device_hdl[0] = -1;
new_csiphy_dev->bridge_intf.device_hdl[1] = -1;
@@ -211,9 +210,17 @@ static int32_t cam_csiphy_device_remove(struct platform_device *pdev)
struct csiphy_device *csiphy_dev =
v4l2_get_subdevdata(subdev);
+ CAM_INFO(CAM_CSIPHY, "device remove invoked");
cam_cpas_unregister_client(csiphy_dev->cpas_handle);
cam_csiphy_soc_release(csiphy_dev);
+ mutex_lock(&csiphy_dev->mutex);
+ cam_csiphy_shutdown(csiphy_dev);
+ mutex_unlock(&csiphy_dev->mutex);
+ cam_unregister_subdev(&(csiphy_dev->v4l2_dev_str));
kfree(csiphy_dev->ctrl_reg);
+ csiphy_dev->ctrl_reg = NULL;
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&(csiphy_dev->v4l2_dev_str.sd), NULL);
devm_kfree(&pdev->dev, csiphy_dev);
return 0;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
index a16fb888edc6..945910e96a55 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = {
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
.csiphy_common_array_size = 4,
- .csiphy_reset_array_size = 4,
+ .csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 21,
.csiphy_3ph_config_array_size = 31,
.csiphy_2ph_clock_lane = 0x1,
@@ -38,6 +38,7 @@ struct csiphy_reg_t csiphy_reset_reg_1_2[] = {
{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
index 8d7a5b58215a..b7345d4abeeb 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,8 +19,8 @@ struct csiphy_reg_parms_t csiphy_v2_0 = {
.mipi_csiphy_interrupt_status0_addr = 0x8B0,
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
- .csiphy_common_array_size = 6,
- .csiphy_reset_array_size = 3,
+ .csiphy_common_array_size = 8,
+ .csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 15,
.csiphy_3ph_config_array_size = 17,
.csiphy_2ph_clock_lane = 0x1,
@@ -31,6 +31,8 @@ struct csiphy_reg_t csiphy_common_reg_2_0[] = {
{0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE},
{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x06, 0x00, CSIPHY_3PH_REGS},
+ {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0164, 0x00, 0x00, CSIPHY_2PH_REGS},
{0x0364, 0x00, 0x00, CSIPHY_2PH_REGS},
{0x0564, 0x00, 0x00, CSIPHY_2PH_REGS},
@@ -40,6 +42,8 @@ struct csiphy_reg_t csiphy_reset_reg_2_0[] = {
{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+ {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
};
struct csiphy_reg_t csiphy_irq_reg_2_0[] = {
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 7d7c1a2977e5..220cd1598922 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
#include "cam_eeprom_soc.h"
#include "cam_debug_util.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
/**
* cam_eeprom_read_memory() - read map data into buffer
@@ -413,7 +414,7 @@ static int32_t cam_eeprom_update_slaveInfo(struct cam_eeprom_ctrl_t *e_ctrl,
static int32_t cam_eeprom_parse_memory_map(
struct cam_eeprom_memory_block_t *data,
void *cmd_buf, int cmd_length, uint16_t *cmd_length_bytes,
- int *num_map)
+ int *num_map, size_t remain_buf_len)
{
int32_t rc = 0;
int32_t cnt = 0;
@@ -427,8 +428,21 @@ static int32_t cam_eeprom_parse_memory_map(
struct cam_cmd_i2c_continuous_rd *i2c_cont_rd = NULL;
struct cam_cmd_conditional_wait *i2c_poll = NULL;
struct cam_cmd_unconditional_wait *i2c_uncond_wait = NULL;
+ size_t validate_size = 0;
generic_op_code = cmm_hdr->third_byte;
+
+ if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR)
+ validate_size = sizeof(struct cam_cmd_i2c_random_wr);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD)
+ validate_size = sizeof(struct cam_cmd_i2c_continuous_rd);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
+ validate_size = sizeof(struct cam_cmd_unconditional_wait);
+
+ if (remain_buf_len < validate_size) {
+ CAM_ERR(CAM_EEPROM, "not enough buffer");
+ return -EINVAL;
+ }
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
@@ -535,6 +549,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
uint32_t *cmd_buf = NULL;
uintptr_t generic_pkt_addr;
size_t pkt_len = 0;
+ size_t remain_len = 0;
uint32_t total_cmd_buf_in_bytes = 0;
uint32_t processed_cmd_buf_in_bytes = 0;
struct common_header *cmm_hdr = NULL;
@@ -575,15 +590,43 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
cmd_buf = (uint32_t *)generic_pkt_addr;
if (!cmd_buf) {
CAM_ERR(CAM_EEPROM, "invalid cmd buf");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+
+ if ((pkt_len < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (pkt_len -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ remain_len = pkt_len - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+
+ if (total_cmd_buf_in_bytes > remain_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer for command");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
/* Loop through multiple cmd formats in one cmd buffer */
while (processed_cmd_buf_in_bytes < total_cmd_buf_in_bytes) {
+ if ((remain_len - processed_cmd_buf_in_bytes) <
+ sizeof(struct common_header)) {
+ CAM_ERR(CAM_EEPROM, "Not enough buf");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
cmm_hdr = (struct common_header *)cmd_buf;
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+ if ((remain_len - processed_cmd_buf_in_bytes) <
+ sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_EEPROM, "Not enough buf");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
/* Configure the following map slave address */
map[num_map + 1].saddr = i2c_info->slave_addr;
rc = cam_eeprom_update_slaveInfo(e_ctrl,
@@ -599,14 +642,16 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
case CAMERA_SENSOR_CMD_TYPE_PWR_DOWN:
cmd_length_in_bytes = total_cmd_buf_in_bytes;
rc = cam_sensor_update_power_settings(cmd_buf,
- cmd_length_in_bytes, power_info);
+ cmd_length_in_bytes, power_info,
+ (remain_len -
+ processed_cmd_buf_in_bytes));
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/
sizeof(uint32_t);
if (rc) {
CAM_ERR(CAM_EEPROM, "Failed");
- return rc;
+ goto rel_cmd_buf;
}
break;
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
@@ -616,7 +661,9 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
rc = cam_eeprom_parse_memory_map(
&e_ctrl->cal_data, cmd_buf,
total_cmd_buf_in_bytes,
- &cmd_length_in_bytes, &num_map);
+ &cmd_length_in_bytes, &num_map,
+ (remain_len -
+ processed_cmd_buf_in_bytes));
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/sizeof(uint32_t);
@@ -626,7 +673,18 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl,
}
}
e_ctrl->cal_data.num_map = num_map + 1;
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_EEPROM, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
}
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_EEPROM, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
+
return rc;
}
@@ -647,6 +705,7 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
uintptr_t buf_addr;
size_t buf_size;
uint8_t *read_buffer;
+ size_t remain_len = 0;
io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
&csl_packet->payload +
@@ -660,6 +719,18 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
if (io_cfg->direction == CAM_BUF_OUTPUT) {
rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0],
&buf_addr, &buf_size);
+ if (rc) {
+ CAM_ERR(CAM_EEPROM, "Fail in get buffer: %d",
+ rc);
+ return rc;
+ }
+ if (buf_size <= io_cfg->offsets[0]) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
+ remain_len = buf_size - io_cfg->offsets[0];
CAM_DBG(CAM_EEPROM, "buf_addr : %pK, buf_size : %zu\n",
(void *)buf_addr, buf_size);
@@ -667,26 +738,38 @@ static int32_t cam_eeprom_get_cal_data(struct cam_eeprom_ctrl_t *e_ctrl,
if (!read_buffer) {
CAM_ERR(CAM_EEPROM,
"invalid buffer to copy data");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
read_buffer += io_cfg->offsets[0];
- if (buf_size < e_ctrl->cal_data.num_data) {
+ if (remain_len < e_ctrl->cal_data.num_data) {
CAM_ERR(CAM_EEPROM,
"failed to copy, Invalid size");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
CAM_DBG(CAM_EEPROM, "copy the data, len:%d",
e_ctrl->cal_data.num_data);
memcpy(read_buffer, e_ctrl->cal_data.mapdata,
e_ctrl->cal_data.num_data);
-
+ if (cam_mem_put_cpu_buf(io_cfg->mem_handle[0]))
+ CAM_WARN(CAM_EEPROM, "Fail in put buffer: 0x%x",
+ io_cfg->mem_handle[0]);
} else {
CAM_ERR(CAM_EEPROM, "Invalid direction");
rc = -EINVAL;
}
}
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(io_cfg->mem_handle[0]))
+ CAM_WARN(CAM_EEPROM, "Fail in put buffer : %d",
+ io_cfg->mem_handle[0]);
+
return rc;
}
@@ -704,6 +787,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
struct cam_config_dev_cmd dev_config;
uintptr_t generic_pkt_addr;
size_t pkt_len;
+ size_t remain_len = 0;
struct cam_packet *csl_packet = NULL;
struct cam_eeprom_soc_private *soc_private =
(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
@@ -723,15 +807,28 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
return rc;
}
- if (dev_config.offset > pkt_len) {
+ remain_len = pkt_len;
+ if ((sizeof(struct cam_packet) > pkt_len) ||
+ ((size_t)dev_config.offset >= pkt_len -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_EEPROM,
- "Offset is out of bound: off: %lld, %zu",
- dev_config.offset, pkt_len);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), pkt_len);
+ rc = -EINVAL;
+ goto release_buf;
}
+ remain_len -= (size_t)dev_config.offset;
csl_packet = (struct cam_packet *)
- (generic_pkt_addr + (uint32_t)dev_config.offset);
+ (generic_pkt_addr + (uint32_t)dev_config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_EEPROM, "Invalid packet params");
+ rc = -EINVAL;
+ goto release_buf;
+ }
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_EEPROM_PACKET_OPCODE_INIT:
if (e_ctrl->userspace_probe == false) {
@@ -739,7 +836,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
e_ctrl->soc_info.dev->of_node, e_ctrl);
if (rc < 0) {
CAM_ERR(CAM_EEPROM, "Failed: rc : %d", rc);
- return rc;
+ goto release_buf;
}
rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
vfree(e_ctrl->cal_data.mapdata);
@@ -754,7 +851,7 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
if (rc) {
CAM_ERR(CAM_EEPROM,
"Failed in parsing the pkt");
- return rc;
+ goto release_buf;
}
e_ctrl->cal_data.mapdata =
@@ -797,7 +894,13 @@ static int32_t cam_eeprom_pkt_parse(struct cam_eeprom_ctrl_t *e_ctrl, void *arg)
default:
break;
}
+
+ if (cam_mem_put_cpu_buf(dev_config.packet_handle))
+ CAM_WARN(CAM_EEPROM, "Put cpu buffer failed : %llu",
+ dev_config.packet_handle);
+
return rc;
+
power_down:
cam_eeprom_power_down(e_ctrl);
memdata_free:
@@ -811,6 +914,11 @@ error:
e_ctrl->cal_data.num_data = 0;
e_ctrl->cal_data.num_map = 0;
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
+release_buf:
+ if (cam_mem_put_cpu_buf(dev_config.packet_handle))
+ CAM_WARN(CAM_EEPROM, "Put cpu buffer failed : %llu",
+ dev_config.packet_handle);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
index 6d8820abb7d7..cf6854c7a527 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -219,7 +219,6 @@ static int cam_eeprom_i2c_driver_probe(struct i2c_client *client,
e_ctrl->bridge_intf.ops.get_dev_info = NULL;
e_ctrl->bridge_intf.ops.link_setup = NULL;
e_ctrl->bridge_intf.ops.apply_req = NULL;
- v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, e_ctrl);
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
return rc;
@@ -257,13 +256,17 @@ static int cam_eeprom_i2c_driver_remove(struct i2c_client *client)
return -EINVAL;
}
+ CAM_INFO(CAM_EEPROM, "i2c driver remove invoked");
soc_info = &e_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(e_ctrl->eeprom_mutex));
+ cam_eeprom_shutdown(e_ctrl);
+ mutex_unlock(&(e_ctrl->eeprom_mutex));
mutex_destroy(&(e_ctrl->eeprom_mutex));
+ cam_unregister_subdev(&(e_ctrl->v4l2_dev_str));
kfree(soc_private);
- kfree(e_ctrl->io_master_info.cci_client);
v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL);
kfree(e_ctrl);
@@ -388,14 +391,21 @@ static int cam_eeprom_spi_driver_remove(struct spi_device *sdev)
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(e_ctrl->eeprom_mutex));
+ cam_eeprom_shutdown(e_ctrl);
+ mutex_unlock(&(e_ctrl->eeprom_mutex));
+ mutex_destroy(&(e_ctrl->eeprom_mutex));
+ cam_unregister_subdev(&(e_ctrl->v4l2_dev_str));
kfree(e_ctrl->io_master_info.spi_client);
+ e_ctrl->io_master_info.spi_client = NULL;
soc_private =
(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
if (soc_private) {
kfree(soc_private->power_info.gpio_num_info);
+ soc_private->power_info.gpio_num_info = NULL;
kfree(soc_private);
+ soc_private = NULL;
}
- mutex_destroy(&(e_ctrl->eeprom_mutex));
v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL);
kfree(e_ctrl);
@@ -459,10 +469,7 @@ static int32_t cam_eeprom_platform_driver_probe(
e_ctrl->bridge_intf.ops.get_dev_info = NULL;
e_ctrl->bridge_intf.ops.link_setup = NULL;
e_ctrl->bridge_intf.ops.apply_req = NULL;
-
platform_set_drvdata(pdev, e_ctrl);
- v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, e_ctrl);
-
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
return rc;
@@ -472,6 +479,7 @@ free_cci_client:
kfree(e_ctrl->io_master_info.cci_client);
free_e_ctrl:
kfree(e_ctrl);
+
return rc;
}
@@ -487,17 +495,23 @@ static int cam_eeprom_platform_driver_remove(struct platform_device *pdev)
return -EINVAL;
}
+ CAM_INFO(CAM_EEPROM, "Platform driver remove invoked");
soc_info = &e_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(e_ctrl->eeprom_mutex));
+ cam_eeprom_shutdown(e_ctrl);
+ mutex_unlock(&(e_ctrl->eeprom_mutex));
mutex_destroy(&(e_ctrl->eeprom_mutex));
+ cam_unregister_subdev(&(e_ctrl->v4l2_dev_str));
kfree(soc_info->soc_private);
kfree(e_ctrl->io_master_info.cci_client);
platform_set_drvdata(pdev, NULL);
v4l2_set_subdevdata(&e_ctrl->v4l2_dev_str.sd, NULL);
kfree(e_ctrl);
+
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c
index 5c9df8ac7abf..4302d4897ea9 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,43 +16,78 @@
#include "cam_flash_core.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
bool regulator_enable)
{
int rc = 0;
+ struct cam_flash_private_soc *soc_private =
+ (struct cam_flash_private_soc *)
+ flash_ctrl->soc_info.soc_private;
if (!(flash_ctrl->switch_trigger)) {
CAM_ERR(CAM_FLASH, "Invalid argument");
return -EINVAL;
}
- if (regulator_enable &&
- (flash_ctrl->is_regulator_enabled == false)) {
- rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
- ENABLE_REGULATOR, NULL);
- if (rc) {
- CAM_ERR(CAM_FLASH, "regulator enable failed rc = %d",
- rc);
- return rc;
- }
- flash_ctrl->is_regulator_enabled = true;
- } else if ((!regulator_enable) &&
- (flash_ctrl->is_regulator_enabled == true)) {
- rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
- DISABLE_REGULATOR, NULL);
- if (rc) {
- CAM_ERR(CAM_FLASH, "regulator disable failed rc = %d",
- rc);
- return rc;
+ if (soc_private->is_wled_flash) {
+ if (regulator_enable &&
+ flash_ctrl->is_regulator_enabled == false) {
+ rc = wled_flash_led_prepare(flash_ctrl->switch_trigger,
+ ENABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "enable reg failed: rc: %d",
+ rc);
+ return rc;
+ }
+
+ flash_ctrl->is_regulator_enabled = true;
+ } else if (!regulator_enable &&
+ flash_ctrl->is_regulator_enabled == true) {
+ rc = wled_flash_led_prepare(flash_ctrl->switch_trigger,
+ DISABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "disalbe reg fail: rc: %d",
+ rc);
+ return rc;
+ }
+
+ flash_ctrl->is_regulator_enabled = false;
+ } else {
+ CAM_ERR(CAM_FLASH, "Wrong Wled flash state: %d",
+ flash_ctrl->flash_state);
+ rc = -EINVAL;
}
- flash_ctrl->is_regulator_enabled = false;
} else {
- CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
- flash_ctrl->flash_state);
- rc = -EINVAL;
- }
+ if (regulator_enable &&
+ (flash_ctrl->is_regulator_enabled == false)) {
+ rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
+ ENABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Regulator enable failed rc = %d", rc);
+ return rc;
+ }
+ flash_ctrl->is_regulator_enabled = true;
+ } else if ((!regulator_enable) &&
+ (flash_ctrl->is_regulator_enabled == true)) {
+ rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
+ DISABLE_REGULATOR, NULL);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "Regulator disable failed rc = %d", rc);
+ return rc;
+ }
+
+ flash_ctrl->is_regulator_enabled = false;
+ } else {
+ CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
+ flash_ctrl->flash_state);
+ rc = -EINVAL;
+ }
+ }
return rc;
}
@@ -171,6 +206,7 @@ int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl,
"Enable Regulator Failed rc = %d", rc);
return rc;
}
+ fctrl->last_flush_req = 0;
}
if (!regulator_enable) {
@@ -267,7 +303,6 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
}
if (type == FLUSH_ALL) {
- cam_flash_off(fctrl);
/* flush all requests*/
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
fctrl->per_frame[i].cmn_attr.request_id = 0;
@@ -360,7 +395,13 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush)
}
mutex_lock(&fctrl->flash_mutex);
+ if (fctrl->flash_state == CAM_FLASH_STATE_INIT)
+ goto end;
+
if (flush->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ fctrl->last_flush_req = flush->req_id;
+ CAM_DBG(CAM_FLASH, "last reqest to flush is %lld",
+ flush->req_id);
rc = fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
if (rc) {
CAM_ERR(CAM_FLASH, "FLUSH_TYPE_ALL failed rc: %d", rc);
@@ -398,37 +439,31 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
if (flash_ctrl->torch_trigger[i]) {
max_current = soc_private->torch_max_current[i];
-
if (flash_data->led_current_ma[i] <=
max_current)
curr = flash_data->led_current_ma[i];
else
- curr = soc_private->torch_op_current[i];
-
- CAM_DBG(CAM_PERF,
- "Led_Current[%d] = %d", i, curr);
- cam_res_mgr_led_trigger_event(
- flash_ctrl->torch_trigger[i],
- curr);
+ curr = max_current;
}
+ CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d",
+ i, curr);
+ cam_res_mgr_led_trigger_event(
+ flash_ctrl->torch_trigger[i], curr);
}
} else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
for (i = 0; i < flash_ctrl->flash_num_sources; i++) {
if (flash_ctrl->flash_trigger[i]) {
max_current = soc_private->flash_max_current[i];
-
if (flash_data->led_current_ma[i] <=
max_current)
curr = flash_data->led_current_ma[i];
else
- curr = soc_private->flash_op_current[i];
-
- CAM_DBG(CAM_PERF, "LED flash_current[%d]: %d",
- i, curr);
- cam_res_mgr_led_trigger_event(
- flash_ctrl->flash_trigger[i],
- curr);
+ curr = max_current;
}
+ CAM_DBG(CAM_FLASH, "LED_Flash[%d]: Current: %d",
+ i, curr);
+ cam_res_mgr_led_trigger_event(
+ flash_ctrl->flash_trigger[i], curr);
}
} else {
CAM_ERR(CAM_FLASH, "Wrong Operation: %d", op);
@@ -438,7 +473,7 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(
flash_ctrl->switch_trigger,
- LED_SWITCH_ON);
+ (enum led_brightness)LED_SWITCH_ON);
return 0;
}
@@ -452,7 +487,7 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
if (flash_ctrl->switch_trigger)
cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger,
- LED_SWITCH_OFF);
+ (enum led_brightness)LED_SWITCH_OFF);
flash_ctrl->flash_state = CAM_FLASH_STATE_START;
return 0;
@@ -591,11 +626,15 @@ static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl,
}
static int32_t cam_flash_slaveInfo_pkt_parser(struct cam_flash_ctrl *fctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+ if (len < sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
if (fctrl->io_master_info.master_type == CCI_MASTER) {
fctrl->io_master_info.cci_client->cci_i2c_master =
fctrl->cci_i2c_master;
@@ -870,6 +909,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
size_t len_of_buffer;
+ size_t remain_len;
struct cam_flash_init *flash_init = NULL;
struct common_header *cmn_hdr = NULL;
struct cam_control *ioctl_ctrl = NULL;
@@ -897,19 +937,42 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_mem_get_cpu_buf(config.packet_handle,
&generic_ptr, &len_of_buffer);
if (rc) {
- CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
+ CAM_ERR(CAM_FLASH, "Failed in getting the packet : %d", rc);
return rc;
}
-
- if (config.offset > len_of_buffer) {
+ remain_len = len_of_buffer;
+ if ((sizeof(struct cam_packet) > len_of_buffer) ||
+ ((size_t)config.offset >= len_of_buffer -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_FLASH,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buffer);
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buffer);
return -EINVAL;
}
+ remain_len -= (size_t)config.offset;
/* Add offset to the flash csl header */
csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_FLASH, "Invalid packet params");
+ return -EINVAL;
+ }
+
+ if ((csl_packet->header.op_code & 0xFFFFFF) !=
+ CAM_FLASH_PACKET_OPCODE_INIT &&
+ csl_packet->header.request_id <= fctrl->last_flush_req
+ && fctrl->last_flush_req != 0) {
+ CAM_DBG(CAM_FLASH,
+ "reject request %lld, last request to flush %lld",
+ csl_packet->header.request_id, fctrl->last_flush_req);
+ return -EINVAL;
+ }
+
+ if (csl_packet->header.request_id > fctrl->last_flush_req)
+ fctrl->last_flush_req = 0;
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
/* INIT packet*/
@@ -934,6 +997,15 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
CAM_ERR(CAM_FLASH, "invalid cmd buf");
return -EINVAL;
}
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset >
+ (len_of_buffer -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "invalid cmd buf length");
+ return -EINVAL;
+ }
+ remain_len = len_of_buffer - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmn_hdr = (struct common_header *)cmd_buf;
@@ -944,6 +1016,12 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
total_cmd_buf_in_bytes);
switch (cmn_hdr->cmd_type) {
case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO:
+ if (len_of_buffer <
+ sizeof(struct cam_flash_init)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ return -EINVAL;
+ }
+
flash_init = (struct cam_flash_init *)cmd_buf;
fctrl->flash_type = flash_init->flash_type;
cmd_length_in_bytes =
@@ -955,7 +1033,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
break;
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
rc = cam_flash_slaveInfo_pkt_parser(
- fctrl, cmd_buf);
+ fctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_FLASH,
"Failed parsing slave info: rc: %d",
@@ -978,7 +1056,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- &fctrl->power_info);
+ &fctrl->power_info, remain_len);
processed_cmd_buf_in_bytes +=
cmd_length_in_bytes;
cmd_buf += cmd_length_in_bytes/
@@ -1171,11 +1249,12 @@ update_req_mgr:
int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
{
int rc = 0, i = 0;
- uintptr_t generic_ptr;
+ uintptr_t generic_ptr, cmd_buf_ptr;
uint32_t *cmd_buf = NULL;
uint32_t *offset = NULL;
uint32_t frm_offset = 0;
size_t len_of_buffer;
+ size_t remain_len;
struct cam_control *ioctl_ctrl = NULL;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -1187,11 +1266,16 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
struct cam_flash_set_on_off *flash_operation_info = NULL;
struct cam_flash_query_curr *flash_query_info = NULL;
struct cam_flash_frame_setting *flash_data = NULL;
+ struct cam_flash_private_soc *soc_private = NULL;
if (!fctrl || !arg) {
CAM_ERR(CAM_FLASH, "fctrl/arg is NULL");
return -EINVAL;
}
+
+ soc_private = (struct cam_flash_private_soc *)
+ fctrl->soc_info.soc_private;
+
/* getting CSL Packet */
ioctl_ctrl = (struct cam_control *)arg;
@@ -1206,20 +1290,45 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = cam_mem_get_cpu_buf(config.packet_handle,
&generic_ptr, &len_of_buffer);
if (rc) {
- CAM_ERR(CAM_FLASH, "Failed in getting the buffer : %d", rc);
+ CAM_ERR(CAM_FLASH, "Failed in getting the packet: %d", rc);
return rc;
}
- if (config.offset > len_of_buffer) {
+ remain_len = len_of_buffer;
+ if ((sizeof(struct cam_packet) > len_of_buffer) ||
+ ((size_t)config.offset >= len_of_buffer -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_FLASH,
- "offset is out of bounds: offset: %lld len: %zu",
- config.offset, len_of_buffer);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buffer);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+ remain_len -= (size_t)config.offset;
/* Add offset to the flash csl header */
- csl_packet =
- (struct cam_packet *)(generic_ptr + (uint32_t)config.offset);
+ csl_packet = (struct cam_packet *)(generic_ptr + config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_FLASH, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ if ((csl_packet->header.op_code & 0xFFFFFF) !=
+ CAM_FLASH_PACKET_OPCODE_INIT &&
+ csl_packet->header.request_id <= fctrl->last_flush_req
+ && fctrl->last_flush_req != 0) {
+ CAM_WARN(CAM_FLASH,
+ "reject request %lld, last request to flush %u",
+ csl_packet->header.request_id, fctrl->last_flush_req);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ if (csl_packet->header.request_id > fctrl->last_flush_req)
+ fctrl->last_flush_req = 0;
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_FLASH_PACKET_OPCODE_INIT: {
@@ -1228,8 +1337,20 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
csl_packet->cmd_buf_offset);
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- &generic_ptr, &len_of_buffer);
- cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+ &cmd_buf_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc);
+ goto rel_pkt_buf;
+ }
+ if ((len_of_buffer < sizeof(struct cam_flash_init)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct cam_flash_init)))) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+ cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr +
cmd_desc->offset);
cam_flash_info = (struct cam_flash_init *)cmd_buf;
@@ -1248,7 +1369,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
if (rc) {
CAM_ERR(CAM_FLASH,
"Enable Regulator Failed rc = %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
fctrl->flash_state =
@@ -1258,8 +1379,26 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
case CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE: {
CAM_DBG(CAM_FLASH, "INIT_FIRE Operation");
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
+ if (!flash_operation_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_operation_info Null");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
fctrl->nrt_info.cmn_attr.count =
flash_operation_info->count;
fctrl->nrt_info.cmn_attr.request_id = 0;
@@ -1284,8 +1423,13 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
cam_flash_info->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: %d",
+ cmd_desc->mem_handle);
break;
}
case CAM_FLASH_PACKET_OPCODE_SET_OPS: {
@@ -1306,13 +1450,28 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
flash_data->cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- &generic_ptr, &len_of_buffer);
- cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
- cmd_desc->offset);
+ &cmd_buf_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: 0x%x",
+ cmd_desc->mem_handle);
+ goto rel_pkt_buf;
+ }
- if (!cmd_buf)
- return -EINVAL;
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+ cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr +
+ cmd_desc->offset);
+ if (!cmd_buf) {
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
cmn_hdr = (struct common_header *)cmd_buf;
switch (cmn_hdr->cmd_type) {
@@ -1325,7 +1484,12 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
CAM_WARN(CAM_FLASH,
"Rxed Flash fire ops without linking");
flash_data->cmn_attr.is_settings_valid = false;
- return 0;
+ goto rel_cmd_buf;
+ }
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
flash_operation_info =
@@ -1333,7 +1497,14 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
if (!flash_operation_info) {
CAM_ERR(CAM_FLASH,
"flash_operation_info Null");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
flash_data->opcode = flash_operation_info->opcode;
@@ -1350,8 +1521,12 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type = %d",
cmn_hdr->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: 0x%x",
+ cmd_desc->mem_handle);
break;
}
case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: {
@@ -1360,16 +1535,47 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->nrt_info.cmn_attr.is_settings_valid = true;
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- &generic_ptr, &len_of_buffer);
- cmd_buf = (uint32_t *)((uint8_t *)generic_ptr +
+ &cmd_buf_ptr, &len_of_buffer);
+ if (rc) {
+ CAM_ERR(CAM_FLASH, "Fail in get buffer: %d", rc);
+ goto rel_pkt_buf;
+ }
+
+ if ((len_of_buffer < sizeof(struct common_header)) ||
+ (cmd_desc->offset >
+ (len_of_buffer - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len_of_buffer - cmd_desc->offset;
+ cmd_buf = (uint32_t *)((uint8_t *)cmd_buf_ptr +
cmd_desc->offset);
cmn_hdr = (struct common_header *)cmd_buf;
switch (cmn_hdr->cmd_type) {
case CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET: {
CAM_DBG(CAM_FLASH, "Widget Flash Operation");
+ if (remain_len < sizeof(struct cam_flash_set_on_off)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
flash_operation_info =
(struct cam_flash_set_on_off *) cmd_buf;
+ if (!flash_operation_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_operation_info Null");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_operation_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
fctrl->nrt_info.cmn_attr.count =
flash_operation_info->count;
fctrl->nrt_info.cmn_attr.request_id = 0;
@@ -1386,29 +1592,61 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
if (rc)
CAM_ERR(CAM_FLASH, "Apply setting failed: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
case CAMERA_SENSOR_FLASH_CMD_TYPE_QUERYCURR: {
int query_curr_ma = 0;
+ if (remain_len < sizeof(struct cam_flash_query_curr)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
flash_query_info =
(struct cam_flash_query_curr *)cmd_buf;
- rc = qpnp_flash_led_prepare(fctrl->switch_trigger,
- QUERY_MAX_CURRENT, &query_curr_ma);
+ if (soc_private->is_wled_flash)
+ rc = wled_flash_led_prepare(
+ fctrl->switch_trigger,
+ QUERY_MAX_AVAIL_CURRENT,
+ &query_curr_ma);
+ else
+ rc = qpnp_flash_led_prepare(
+ fctrl->switch_trigger,
+ QUERY_MAX_AVAIL_CURRENT,
+ &query_curr_ma);
+
CAM_DBG(CAM_FLASH, "query_curr_ma = %d",
query_curr_ma);
if (rc) {
CAM_ERR(CAM_FLASH,
"Query current failed with rc=%d", rc);
- return rc;
+ goto rel_cmd_buf;
}
flash_query_info->query_current_ma = query_curr_ma;
break;
}
case CAMERA_SENSOR_FLASH_CMD_TYPE_RER: {
rc = 0;
+ if (remain_len < sizeof(struct cam_flash_set_rer)) {
+ CAM_ERR(CAM_FLASH, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
flash_rer_info = (struct cam_flash_set_rer *)cmd_buf;
+ if (!flash_rer_info) {
+ CAM_ERR(CAM_FLASH,
+ "flash_rer_info Null");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+ if (flash_rer_info->count >
+ CAM_FLASH_MAX_LED_TRIGGERS) {
+ CAM_ERR(CAM_FLASH, "led count out of limit");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
fctrl->nrt_info.cmn_attr.cmd_type =
CAMERA_SENSOR_FLASH_CMD_TYPE_RER;
fctrl->nrt_info.opcode = flash_rer_info->opcode;
@@ -1425,18 +1663,21 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->nrt_info.led_current_ma[i] =
flash_rer_info->led_current_ma[i];
-
rc = fctrl->func_tbl.apply_setting(fctrl, 0);
if (rc)
CAM_ERR(CAM_FLASH, "apply_setting failed: %d",
rc);
- return rc;
+ goto rel_cmd_buf;
}
default:
CAM_ERR(CAM_FLASH, "Wrong cmd_type : %d",
cmn_hdr->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: 0x%x",
+ cmd_desc->mem_handle);
break;
}
case CAM_PKT_NOP_OPCODE: {
@@ -1448,7 +1689,7 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
"Rxed NOP packets without linking");
fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid
= false;
- return 0;
+ goto rel_pkt_buf;
}
fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid = false;
@@ -1456,14 +1697,15 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
fctrl->per_frame[frm_offset].opcode = CAM_PKT_NOP_OPCODE;
CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %llu",
csl_packet->header.request_id);
- goto update_req_mgr;
+ break;
}
default:
CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
(csl_packet->header.op_code & 0xFFFFFF));
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
-update_req_mgr:
+
if (((csl_packet->header.op_code & 0xFFFFF) ==
CAM_PKT_NOP_OPCODE) ||
((csl_packet->header.op_code & 0xFFFFF) ==
@@ -1484,6 +1726,21 @@ update_req_mgr:
CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id);
}
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_FLASH, "Failed in put the buffer: %llu ",
+ config.packet_handle);
+
+ return 0;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_FLASH, "Fail in put buffer: %d",
+ cmd_desc->mem_handle);
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_FLASH, "Failed in put the buffer: %llu ",
+ config.packet_handle);
+
return rc;
}
@@ -1534,6 +1791,7 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
fctrl->bridge_intf.device_hdl = -1;
fctrl->bridge_intf.link_hdl = -1;
fctrl->bridge_intf.session_hdl = -1;
+ fctrl->last_flush_req = 0;
}
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h
index 1bd3b31c1668..875d13c51ee0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,15 +13,20 @@
#ifndef _CAM_FLASH_CORE_H_
#define _CAM_FLASH_CORE_H_
-#include <linux/leds-qpnp-flash.h>
#include <media/cam_sensor.h>
#include "cam_flash_dev.h"
+#define QUERY_MAX_AVAIL_CURRENT BIT(2)
+
int cam_flash_publish_dev_info(struct cam_req_mgr_device_info *info);
int cam_flash_establish_link(struct cam_req_mgr_core_dev_link_setup *link);
int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply);
int cam_flash_process_evt(struct cam_req_mgr_link_evt_data *event_data);
int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush);
-
+static inline int wled_flash_led_prepare(struct led_trigger *trig, int options,
+ int *max_current)
+{
+ return -EINVAL;
+}
#endif /*_CAM_FLASH_CORE_H_*/
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
index f5177d6796b5..948fc9a9c990 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -181,7 +181,9 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
goto release_mutex;
}
+ cam_flash_off(fctrl);
fctrl->func_tbl.flush_req(fctrl, FLUSH_ALL, 0);
+ fctrl->last_flush_req = 0;
fctrl->flash_state = CAM_FLASH_STATE_ACQUIRE;
break;
}
@@ -318,7 +320,14 @@ static int cam_flash_platform_remove(struct platform_device *pdev)
return 0;
}
- devm_kfree(&pdev->dev, fctrl);
+ CAM_INFO(CAM_FLASH, "Platform remove invoked");
+ mutex_lock(&fctrl->flash_mutex);
+ cam_flash_shutdown(fctrl);
+ mutex_unlock(&fctrl->flash_mutex);
+ cam_unregister_subdev(&(fctrl->v4l2_dev_str));
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&fctrl->v4l2_dev_str.sd, NULL);
+ kfree(fctrl);
return 0;
}
@@ -332,6 +341,8 @@ static int32_t cam_flash_i2c_driver_remove(struct i2c_client *client)
CAM_ERR(CAM_FLASH, "Flash device is NULL");
return -EINVAL;
}
+
+ CAM_INFO(CAM_FLASH, "i2c driver remove invoked");
/*Free Allocated Mem */
kfree(fctrl->i2c_data.per_frame);
fctrl->i2c_data.per_frame = NULL;
@@ -483,6 +494,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
+ fctrl->last_flush_req = 0;
mutex_init(&(fctrl->flash_mutex));
@@ -569,6 +581,7 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
fctrl->bridge_intf.ops.link_setup = cam_flash_establish_link;
fctrl->bridge_intf.ops.apply_req = cam_flash_apply_request;
fctrl->bridge_intf.ops.flush_req = cam_flash_flush_request;
+ fctrl->last_flush_req = 0;
mutex_init(&(fctrl->flash_mutex));
fctrl->flash_state = CAM_FLASH_STATE_INIT;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
index 8e5deef871e5..ea5ea3c9997b 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_dev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/leds-qpnp-flash.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
@@ -135,6 +136,7 @@ struct cam_flash_frame_setting {
* @torch_trigger_name : Torch trigger name array
* @torch_op_current : Torch operational current
* @torch_max_current : Max supported current for LED in torch mode
+ * @is_wled_flash : Detection between WLED/LED flash
*/
struct cam_flash_private_soc {
@@ -146,6 +148,7 @@ struct cam_flash_private_soc {
const char *torch_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
+ bool is_wled_flash;
};
struct cam_flash_func_tbl {
@@ -180,6 +183,7 @@ struct cam_flash_func_tbl {
* @cci_i2c_master : I2C structure
* @io_master_info : Information about the communication master
* @i2c_data : I2C register settings
+ * @last_flush_req : last request to flush
*/
struct cam_flash_ctrl {
struct cam_hw_soc_info soc_info;
@@ -205,6 +209,7 @@ struct cam_flash_ctrl {
enum cci_i2c_master_t cci_i2c_master;
struct camera_io_master io_master_info;
struct i2c_data_settings i2c_data;
+ uint32_t last_flush_req;
};
int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c
index 22a124d86f93..9195c8143d3c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_flash/cam_flash_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,9 +26,12 @@ static int32_t cam_get_source_node_info(
struct device_node *torch_src_node = NULL;
struct device_node *switch_src_node = NULL;
+ soc_private->is_wled_flash =
+ of_property_read_bool(of_node, "wled-flash-support");
+
switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
if (!switch_src_node) {
- CAM_DBG(CAM_FLASH, "switch_src_node NULL");
+ CAM_WARN(CAM_FLASH, "switch_src_node NULL");
} else {
rc = of_property_read_string(switch_src_node,
"qcom,default-led-trigger",
@@ -75,46 +78,61 @@ static int32_t cam_get_source_node_info(
continue;
}
- CAM_DBG(CAM_FLASH, "default trigger %s",
+ CAM_DBG(CAM_FLASH, "Flash default trigger %s",
soc_private->flash_trigger_name[i]);
+ cam_res_mgr_led_trigger_register(
+ soc_private->flash_trigger_name[i],
+ &fctrl->flash_trigger[i]);
+
+ if (soc_private->is_wled_flash) {
+ rc = wled_flash_led_prepare(
+ fctrl->flash_trigger[i],
+ QUERY_MAX_CURRENT,
+ &soc_private->flash_max_current[i]);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "WLED FLASH max_current read fail: %d",
+ rc);
+ of_node_put(flash_src_node);
+ rc = 0;
+ continue;
+ }
+ } else {
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,max-current",
+ &soc_private->flash_max_current[i]);
+ if (rc < 0) {
+ CAM_WARN(CAM_FLASH,
+ "LED FLASH max-current read fail: %d",
+ rc);
+ of_node_put(flash_src_node);
+ continue;
+ }
+ }
/* Read operational-current */
rc = of_property_read_u32(flash_src_node,
"qcom,current-ma",
&soc_private->flash_op_current[i]);
if (rc) {
- CAM_WARN(CAM_FLASH, "op-current: read failed");
- of_node_put(flash_src_node);
- continue;
- }
-
- /* Read max-current */
- rc = of_property_read_u32(flash_src_node,
- "qcom,max-current",
- &soc_private->flash_max_current[i]);
- if (rc) {
- CAM_WARN(CAM_FLASH,
- "max-current: read failed");
- of_node_put(flash_src_node);
- continue;
+ CAM_INFO(CAM_FLASH, "op-current: read failed");
+ rc = 0;
}
/* Read max-duration */
rc = of_property_read_u32(flash_src_node,
"qcom,duration-ms",
&soc_private->flash_max_duration[i]);
- if (rc)
- CAM_WARN(CAM_FLASH,
- "max-duration: read failed");
-
+ if (rc) {
+ CAM_INFO(CAM_FLASH,
+ "max-duration prop unavailable: %d",
+ rc);
+ rc = 0;
+ }
of_node_put(flash_src_node);
- CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
+ CAM_DBG(CAM_FLASH, "MainFlashMaxCurrent[%d]: %d",
i, soc_private->flash_max_current[i]);
-
- cam_res_mgr_led_trigger_register(
- soc_private->flash_trigger_name[i],
- &fctrl->flash_trigger[i]);
}
}
@@ -147,35 +165,51 @@ static int32_t cam_get_source_node_info(
continue;
}
+ CAM_DBG(CAM_FLASH, "Torch default trigger %s",
+ soc_private->torch_trigger_name[i]);
+ cam_res_mgr_led_trigger_register(
+ soc_private->torch_trigger_name[i],
+ &fctrl->torch_trigger[i]);
+
+ if (soc_private->is_wled_flash) {
+ rc = wled_flash_led_prepare(
+ fctrl->torch_trigger[i],
+ QUERY_MAX_CURRENT,
+ &soc_private->torch_max_current[i]);
+ if (rc) {
+ CAM_ERR(CAM_FLASH,
+ "WLED TORCH max_current read fail: %d",
+ rc);
+ of_node_put(torch_src_node);
+ continue;
+ }
+ } else {
+ rc = of_property_read_u32(torch_src_node,
+ "qcom,max-current",
+ &soc_private->torch_max_current[i]);
+ if (rc < 0) {
+ CAM_WARN(CAM_FLASH,
+ "LED-TORCH max-current read failed: %d",
+ rc);
+ of_node_put(torch_src_node);
+ continue;
+ }
+ }
+
/* Read operational-current */
rc = of_property_read_u32(torch_src_node,
"qcom,current-ma",
&soc_private->torch_op_current[i]);
if (rc < 0) {
- CAM_WARN(CAM_FLASH, "current: read failed");
- of_node_put(torch_src_node);
- continue;
- }
-
- /* Read max-current */
- rc = of_property_read_u32(torch_src_node,
- "qcom,max-current",
- &soc_private->torch_max_current[i]);
- if (rc < 0) {
CAM_WARN(CAM_FLASH,
- "max-current: read failed");
- of_node_put(torch_src_node);
- continue;
+ "op-current prop unavailable: %d", rc);
+ rc = 0;
}
of_node_put(torch_src_node);
- CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
+ CAM_DBG(CAM_FLASH, "TorchMaxCurrent[%d]: %d",
i, soc_private->torch_max_current[i]);
-
- cam_res_mgr_led_trigger_register(
- soc_private->torch_trigger_name[i],
- &fctrl->torch_trigger[i]);
}
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
index b8ebc15e7fd5..a5c7039cc2da 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#include "cam_debug_util.h"
#include "cam_res_mgr_api.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
int32_t cam_ois_construct_default_power_setting(
struct cam_sensor_power_ctrl_t *power_info)
@@ -256,12 +257,12 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl,
}
static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
- uint32_t *cmd_buf)
+ uint32_t *cmd_buf, size_t len)
{
int32_t rc = 0;
struct cam_cmd_ois_info *ois_info;
- if (!o_ctrl || !cmd_buf) {
+ if (!o_ctrl || !cmd_buf || len < sizeof(struct cam_cmd_ois_info)) {
CAM_ERR(CAM_OIS, "Invalid Args");
return -EINVAL;
}
@@ -274,7 +275,8 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
ois_info->slave_addr >> 1;
o_ctrl->ois_fw_flag = ois_info->ois_fw_flag;
o_ctrl->is_ois_calib = ois_info->is_ois_calib;
- memcpy(o_ctrl->ois_name, ois_info->ois_name, 32);
+ memcpy(o_ctrl->ois_name, ois_info->ois_name, OIS_NAME_LEN);
+ o_ctrl->ois_name[OIS_NAME_LEN - 1] = '\0';
o_ctrl->io_master_info.cci_client->retries = 3;
o_ctrl->io_master_info.cci_client->id_map = 0;
memcpy(&(o_ctrl->opcode), &(ois_info->opcode),
@@ -433,6 +435,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
struct cam_cmd_buf_desc *cmd_desc = NULL;
uintptr_t generic_pkt_addr;
size_t pkt_len;
+ size_t remain_len = 0;
struct cam_packet *csl_packet = NULL;
size_t len_of_buff = 0;
uint32_t *offset = NULL, *cmd_buf;
@@ -453,15 +456,29 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
return rc;
}
- if (dev_config.offset > pkt_len) {
+ remain_len = pkt_len;
+ if ((sizeof(struct cam_packet) > pkt_len) ||
+ ((size_t)dev_config.offset >= pkt_len -
+ sizeof(struct cam_packet))) {
CAM_ERR(CAM_OIS,
- "offset is out of bound: off: %lld len: %zu",
- dev_config.offset, pkt_len);
- return -EINVAL;
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), pkt_len);
+ rc = -EINVAL;
+ goto rel_pkt;
}
+ remain_len -= (size_t)dev_config.offset;
csl_packet = (struct cam_packet *)
(generic_pkt_addr + (uint32_t)dev_config.offset);
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_OIS, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt;
+ }
+
+
switch (csl_packet->header.op_code & 0xFFFFFF) {
case CAM_OIS_PACKET_OPCODE_INIT:
offset = (uint32_t *)&csl_packet->payload;
@@ -477,25 +494,37 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
&generic_ptr, &len_of_buff);
if (rc < 0) {
- CAM_ERR(CAM_OIS, "Failed to get cpu buf");
- return rc;
+ CAM_ERR(CAM_OIS, "Failed to get cpu buf : 0x%x",
+ cmd_desc[i].mem_handle);
+ goto rel_pkt;
}
cmd_buf = (uint32_t *)generic_ptr;
if (!cmd_buf) {
CAM_ERR(CAM_OIS, "invalid cmd buf");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
+ }
+
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset > (len_of_buff -
+ sizeof(struct common_header)))) {
+ CAM_ERR(CAM_OIS,
+ "Invalid length for sensor cmd");
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
+ remain_len = len_of_buff - cmd_desc[i].offset;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
cmm_hdr = (struct common_header *)cmd_buf;
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO:
rc = cam_ois_slaveInfo_pkt_parser(
- o_ctrl, cmd_buf);
+ o_ctrl, cmd_buf, remain_len);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"Failed in parsing slave info");
- return rc;
+ goto rel_cmd_buf;
}
break;
case CAMERA_SENSOR_CMD_TYPE_PWR_UP:
@@ -505,11 +534,11 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
rc = cam_sensor_update_power_settings(
cmd_buf,
total_cmd_buf_in_bytes,
- power_info);
+ power_info, remain_len);
if (rc) {
CAM_ERR(CAM_OIS,
"Failed: parse power settings");
- return rc;
+ goto rel_cmd_buf;
}
break;
default:
@@ -527,7 +556,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
if (rc < 0) {
CAM_ERR(CAM_OIS,
"init parsing failed: %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
} else if ((o_ctrl->is_ois_calib != 0) &&
(o_ctrl->i2c_calib_data.is_settings_valid ==
@@ -544,18 +573,21 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
if (rc < 0) {
CAM_ERR(CAM_OIS,
"Calib parsing failed: %d", rc);
- return rc;
+ goto rel_cmd_buf;
}
}
break;
}
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_OIS, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
}
if (o_ctrl->cam_ois_state != CAM_OIS_CONFIG) {
rc = cam_ois_power_up(o_ctrl);
if (rc) {
CAM_ERR(CAM_OIS, " OIS Power up failed");
- return rc;
+ goto rel_pkt;
}
o_ctrl->cam_ois_state = CAM_OIS_CONFIG;
}
@@ -602,7 +634,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
CAM_WARN(CAM_OIS,
"Not in right state to control OIS: %d",
o_ctrl->cam_ois_state);
- return rc;
+ goto rel_pkt;
}
offset = (uint32_t *)&csl_packet->payload;
offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
@@ -615,26 +647,43 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
cmd_desc, 1);
if (rc < 0) {
CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc);
- return rc;
+ goto rel_pkt;
}
rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings);
if (rc < 0) {
CAM_ERR(CAM_OIS, "Cannot apply mode settings");
- return rc;
+ goto rel_pkt;
}
rc = delete_request(i2c_reg_settings);
- if (rc < 0)
+ if (rc < 0) {
CAM_ERR(CAM_OIS,
"Fail deleting Mode data: rc: %d", rc);
+ goto rel_pkt;
+ }
break;
default:
- break;
+ CAM_ERR(CAM_OIS, "Invalid Opcode: %d",
+ (csl_packet->header.op_code & 0xFFFFFF));
+ rc = -EINVAL;
+ goto rel_pkt;
}
- return rc;
+
+ if (!rc)
+ goto rel_pkt;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_OIS, "Failed to put cpu buf: %d",
+ cmd_desc[i].mem_handle);
pwr_dwn:
cam_ois_power_down(o_ctrl);
+rel_pkt:
+ if (cam_mem_put_cpu_buf(dev_config.packet_handle))
+ CAM_WARN(CAM_OIS, "Fail in put buffer: %llu",
+ dev_config.packet_handle);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h
index d6f0ec564508..06022ababf4e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,8 @@
#include <linux/dma-contiguous.h>
#include "cam_ois_dev.h"
+#define OIS_NAME_LEN 32
+
/**
* @power_info: power setting info to control the power
*
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c
index 5d16a4e54d04..db583340dad4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_ois/cam_ois_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -229,20 +229,23 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client)
return -EINVAL;
}
+ CAM_INFO(CAM_OIS, "i2c driver remove invoked");
soc_info = &o_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(o_ctrl->ois_mutex));
+ cam_ois_shutdown(o_ctrl);
+ mutex_unlock(&(o_ctrl->ois_mutex));
+ cam_unregister_subdev(&(o_ctrl->v4l2_dev_str));
+
soc_private =
(struct cam_ois_soc_private *)soc_info->soc_private;
power_info = &soc_private->power_info;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
kfree(o_ctrl->soc_info.soc_private);
+ v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL);
kfree(o_ctrl);
return 0;
@@ -303,8 +306,6 @@ static int32_t cam_ois_platform_driver_probe(
o_ctrl->bridge_intf.device_hdl = -1;
platform_set_drvdata(pdev, o_ctrl);
- v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, o_ctrl);
-
o_ctrl->cam_ois_state = CAM_OIS_INIT;
return rc;
@@ -333,21 +334,26 @@ static int cam_ois_platform_driver_remove(struct platform_device *pdev)
return -EINVAL;
}
+ CAM_INFO(CAM_OIS, "platform driver remove invoked");
soc_info = &o_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
+ mutex_lock(&(o_ctrl->ois_mutex));
+ cam_ois_shutdown(o_ctrl);
+ mutex_unlock(&(o_ctrl->ois_mutex));
+ cam_unregister_subdev(&(o_ctrl->v4l2_dev_str));
+
soc_private =
(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
power_info = &soc_private->power_info;
- kfree(power_info->power_setting);
- kfree(power_info->power_down_setting);
- power_info->power_setting = NULL;
- power_info->power_down_setting = NULL;
kfree(o_ctrl->soc_info.soc_private);
kfree(o_ctrl->io_master_info.cci_client);
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL);
kfree(o_ctrl);
+
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
index d03faef4d3a6..ed2f9ad945a5 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -178,8 +178,10 @@ int cam_res_mgr_shared_pinctrl_init(void)
return 0;
}
+ mutex_lock(&cam_res->gpio_res_lock);
if (cam_res->pstatus != PINCTRL_STATUS_PUT) {
CAM_DBG(CAM_RES, "The shared pinctrl already been got.");
+ mutex_unlock(&cam_res->gpio_res_lock);
return 0;
}
@@ -190,6 +192,7 @@ int cam_res_mgr_shared_pinctrl_init(void)
if (IS_ERR_OR_NULL(pinctrl_info->pinctrl)) {
CAM_ERR(CAM_RES, "Pinctrl not available");
cam_res->shared_gpio_enabled = false;
+ mutex_unlock(&cam_res->gpio_res_lock);
return -EINVAL;
}
@@ -200,6 +203,7 @@ int cam_res_mgr_shared_pinctrl_init(void)
CAM_ERR(CAM_RES,
"Failed to get the active state pinctrl handle");
cam_res->shared_gpio_enabled = false;
+ mutex_unlock(&cam_res->gpio_res_lock);
return -EINVAL;
}
@@ -210,10 +214,10 @@ int cam_res_mgr_shared_pinctrl_init(void)
CAM_ERR(CAM_RES,
"Failed to get the active state pinctrl handle");
cam_res->shared_gpio_enabled = false;
+ mutex_unlock(&cam_res->gpio_res_lock);
return -EINVAL;
}
- mutex_lock(&cam_res->gpio_res_lock);
cam_res->pstatus = PINCTRL_STATUS_GOT;
mutex_unlock(&cam_res->gpio_res_lock);
@@ -313,6 +317,7 @@ int cam_res_mgr_shared_pinctrl_select_state(bool active)
pinctrl_info->gpio_state_suspend);
cam_res->pstatus = PINCTRL_STATUS_SUSPEND;
}
+
mutex_unlock(&cam_res->gpio_res_lock);
return rc;
@@ -379,12 +384,14 @@ static bool cam_res_mgr_gpio_is_shared(uint gpio)
bool found = false;
struct cam_res_mgr_dt *dt = &cam_res->dt;
+ mutex_lock(&cam_res->gpio_res_lock);
for (; index < dt->num_shared_gpio; index++) {
if (gpio == dt->shared_gpio[index]) {
found = true;
break;
}
}
+ mutex_unlock(&cam_res->gpio_res_lock);
return found;
}
@@ -441,13 +448,14 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio,
INIT_LIST_HEAD(&gpio_res->list);
INIT_LIST_HEAD(&gpio_res->dev_list);
+ mutex_lock(&cam_res->gpio_res_lock);
rc = cam_res_mgr_add_device(dev, gpio_res);
if (rc) {
kfree(gpio_res);
+ mutex_unlock(&cam_res->gpio_res_lock);
return rc;
}
- mutex_lock(&cam_res->gpio_res_lock);
list_add_tail(&gpio_res->list, &cam_res->gpio_res_list);
mutex_unlock(&cam_res->gpio_res_lock);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 2117cc1f9587..5f77ca0a5293 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,8 @@
#include "cam_soc_util.h"
#include "cam_trace.h"
#include "cam_common_util.h"
+#include "cam_packet_util.h"
+
static void cam_sensor_update_req_mgr(
struct cam_sensor_ctrl_t *s_ctrl,
@@ -94,6 +96,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
struct cam_cmd_buf_desc *cmd_desc = NULL;
struct i2c_settings_array *i2c_reg_settings = NULL;
size_t len_of_buff = 0;
+ size_t remain_len = 0;
uint32_t *offset = NULL;
struct cam_config_dev_cmd config;
struct i2c_data_settings *i2c_data = NULL;
@@ -115,27 +118,42 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
&generic_ptr,
&len_of_buff);
if (rc < 0) {
- CAM_ERR(CAM_SENSOR, "Failed in getting the buffer: %d", rc);
+ CAM_ERR(CAM_SENSOR, "Failed in getting the packet: %d", rc);
return rc;
}
+ remain_len = len_of_buff;
+ if ((sizeof(struct cam_packet) > len_of_buff) ||
+ ((size_t)config.offset >= len_of_buff -
+ sizeof(struct cam_packet))) {
+ CAM_ERR(CAM_SENSOR,
+ "Inval cam_packet strut size: %zu, len_of_buff: %zu",
+ sizeof(struct cam_packet), len_of_buff);
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ remain_len -= (size_t)config.offset;
csl_packet = (struct cam_packet *)(generic_ptr +
(uint32_t)config.offset);
- if (config.offset > len_of_buff) {
- CAM_ERR(CAM_SENSOR,
- "offset is out of bounds: off: %lld len: %zu",
- config.offset, len_of_buff);
- return -EINVAL;
+
+ if (cam_packet_util_validate_packet(csl_packet,
+ remain_len)) {
+ CAM_ERR(CAM_SENSOR, "Invalid packet params");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+
}
if ((csl_packet->header.op_code & 0xFFFFFF) !=
CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG &&
csl_packet->header.request_id <= s_ctrl->last_flush_req
&& s_ctrl->last_flush_req != 0) {
- CAM_DBG(CAM_SENSOR,
- "reject request %lld, last request to flush %lld",
+ CAM_ERR(CAM_SENSOR,
+ "reject request %lld, last request to flush %u",
csl_packet->header.request_id, s_ctrl->last_flush_req);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
if (csl_packet->header.request_id > s_ctrl->last_flush_req)
@@ -158,7 +176,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
}
case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON: {
if (s_ctrl->streamon_count > 0)
- return 0;
+ goto rel_pkt_buf;
s_ctrl->streamon_count = s_ctrl->streamon_count + 1;
i2c_reg_settings = &i2c_data->streamon_settings;
@@ -168,7 +186,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
}
case CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF: {
if (s_ctrl->streamoff_count > 0)
- return 0;
+ goto rel_pkt_buf;
s_ctrl->streamoff_count = s_ctrl->streamoff_count + 1;
i2c_reg_settings = &i2c_data->streamoff_settings;
@@ -182,7 +200,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
CAM_WARN(CAM_SENSOR,
"Rxed Update packets without linking");
- return 0;
+ goto rel_pkt_buf;
}
i2c_reg_settings =
@@ -202,7 +220,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
* fix it.
*/
cam_sensor_update_req_mgr(s_ctrl, csl_packet);
- return 0;
+ goto rel_pkt_buf;
}
break;
}
@@ -211,15 +229,16 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
CAM_WARN(CAM_SENSOR,
"Rxed NOP packets without linking");
- return 0;
+ goto rel_pkt_buf;
}
cam_sensor_update_req_mgr(s_ctrl, csl_packet);
- return 0;
+ goto rel_pkt_buf;
}
default:
CAM_ERR(CAM_SENSOR, "Invalid Packet Header");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
offset = (uint32_t *)&csl_packet->payload;
@@ -230,7 +249,7 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
i2c_reg_settings, cmd_desc, 1);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc);
- return rc;
+ goto rel_pkt_buf;
}
if ((csl_packet->header.op_code & 0xFFFFFF) ==
@@ -240,6 +259,11 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
cam_sensor_update_req_mgr(s_ctrl, csl_packet);
}
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(config.packet_handle))
+ CAM_WARN(CAM_SENSOR, "Failed in put the buffer: %llu",
+ config.packet_handle);
+
return rc;
}
@@ -359,7 +383,7 @@ int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info,
int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_sensor_ctrl_t *s_ctrl,
- int32_t cmd_buf_num, int cmd_buf_length)
+ int32_t cmd_buf_num, uint32_t cmd_buf_length, size_t remain_len)
{
int32_t rc = 0;
@@ -368,6 +392,13 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
struct cam_cmd_i2c_info *i2c_info = NULL;
struct cam_cmd_probe *probe_info;
+ if (remain_len <
+ (sizeof(struct cam_cmd_i2c_info) +
+ sizeof(struct cam_cmd_probe))) {
+ CAM_ERR(CAM_SENSOR,
+ "not enough buffer for cam_cmd_i2c_info");
+ return -EINVAL;
+ }
i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
rc = cam_sensor_update_i2c_info(i2c_info, s_ctrl);
if (rc < 0) {
@@ -386,7 +417,8 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
break;
case 1: {
rc = cam_sensor_update_power_settings(cmd_buf,
- cmd_buf_length, &s_ctrl->sensordata->power_info);
+ cmd_buf_length, &s_ctrl->sensordata->power_info,
+ remain_len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed in updating power settings");
@@ -407,10 +439,11 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
uint32_t *cmd_buf;
void *ptr;
size_t len;
- struct cam_packet *pkt;
- struct cam_cmd_buf_desc *cmd_desc;
+ struct cam_packet *pkt = NULL;
+ struct cam_cmd_buf_desc *cmd_desc = NULL;
uintptr_t cmd_buf1 = 0;
uintptr_t packet = 0;
+ size_t remain_len = 0;
rc = cam_mem_get_cpu_buf(handle,
&packet, &len);
@@ -418,18 +451,35 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
CAM_ERR(CAM_SENSOR, "Failed to get the command Buffer");
return -EINVAL;
}
+
pkt = (struct cam_packet *)packet;
+ if (pkt == NULL) {
+ CAM_ERR(CAM_SENSOR, "packet pos is invalid");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
+ if ((len < sizeof(struct cam_packet)) ||
+ (pkt->cmd_buf_offset >= (len - sizeof(struct cam_packet)))) {
+ CAM_ERR(CAM_SENSOR, "Not enough buf provided");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&pkt->payload + pkt->cmd_buf_offset/4);
if (cmd_desc == NULL) {
CAM_ERR(CAM_SENSOR, "command descriptor pos is invalid");
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
if (pkt->num_cmd_buf != 2) {
CAM_ERR(CAM_SENSOR, "Expected More Command Buffers : %d",
pkt->num_cmd_buf);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
+
for (i = 0; i < pkt->num_cmd_buf; i++) {
if (!(cmd_desc[i].length))
continue;
@@ -438,20 +488,54 @@ int32_t cam_handle_mem_ptr(uint64_t handle, struct cam_sensor_ctrl_t *s_ctrl)
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed to parse the command Buffer Header");
- return -EINVAL;
+ goto rel_pkt_buf;
+ }
+ if (cmd_desc[i].offset >= len) {
+ CAM_ERR(CAM_SENSOR,
+ "offset past length of buffer");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
+ }
+ remain_len = len - cmd_desc[i].offset;
+ if (cmd_desc[i].length > remain_len) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided for cmd");
+ rc = -EINVAL;
+ goto rel_pkt_buf;
}
cmd_buf = (uint32_t *)cmd_buf1;
cmd_buf += cmd_desc[i].offset/4;
ptr = (void *) cmd_buf;
rc = cam_handle_cmd_buffers_for_probe(ptr, s_ctrl,
- i, cmd_desc[i].length);
+ i, cmd_desc[i].length, remain_len);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed to parse the command Buffer Header");
- return -EINVAL;
+ goto rel_cmd_buf;
}
+
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR,
+ "Failed to put command Buffer : %d",
+ cmd_desc[i].mem_handle);
}
+
+ if (cam_mem_put_cpu_buf(handle))
+ CAM_WARN(CAM_SENSOR, "Failed to put the command Buffer: %llu",
+ handle);
+
+ return rc;
+
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR, "Failed to put command Buffer : 0x%x",
+ cmd_desc[i].mem_handle);
+rel_pkt_buf:
+ if (cam_mem_put_cpu_buf(handle))
+ CAM_WARN(CAM_SENSOR, "Failed to put the command Buffer: %llu",
+ handle);
+
return rc;
}
@@ -507,11 +591,13 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl)
cam_sensor_release_stream_rsc(s_ctrl);
cam_sensor_release_per_frame_resource(s_ctrl);
- cam_sensor_power_down(s_ctrl);
+
+ if (s_ctrl->sensor_state != CAM_SENSOR_INIT)
+ cam_sensor_power_down(s_ctrl);
rc = cam_destroy_device_hdl(s_ctrl->bridge_intf.device_hdl);
if (rc < 0)
- CAM_ERR(CAM_SENSOR, " failed destroying dhdl");
+ CAM_ERR(CAM_SENSOR, "dhdl already destroyed: rc = %d", rc);
s_ctrl->bridge_intf.device_hdl = -1;
s_ctrl->bridge_intf.link_hdl = -1;
s_ctrl->bridge_intf.session_hdl = -1;
@@ -843,7 +929,7 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
case CAM_CONFIG_DEV: {
rc = cam_sensor_i2c_pkt_parse(s_ctrl, arg);
if (rc < 0) {
- CAM_ERR(CAM_SENSOR, "Failed CCI Config: %d", rc);
+ CAM_ERR(CAM_SENSOR, "Failed i2c pkt parse: %d", rc);
goto release_mutex;
}
if (s_ctrl->i2c_data.init_settings.is_settings_valid &&
@@ -1210,12 +1296,19 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req)
return -EINVAL;
}
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
+ if (s_ctrl->sensor_state != CAM_SENSOR_START ||
+ s_ctrl->sensor_state != CAM_SENSOR_CONFIG) {
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+ return rc;
+ }
+
if (s_ctrl->i2c_data.per_frame == NULL) {
CAM_ERR(CAM_SENSOR, "i2c frame data is NULL");
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
return -EINVAL;
}
- mutex_lock(&(s_ctrl->cam_sensor_mutex));
if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
s_ctrl->last_flush_req = flush_req->req_id;
CAM_DBG(CAM_SENSOR, "last reqest to flush is %lld",
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c
index 8dcb6c73312f..5c5c97099d43 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -199,7 +199,7 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client,
s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request;
s_ctrl->sensordata->power_info.dev = soc_info->dev;
- v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), s_ctrl);
+
return rc;
unreg_subdev:
cam_unregister_subdev(&(s_ctrl->v4l2_dev_str));
@@ -220,11 +220,18 @@ static int cam_sensor_platform_remove(struct platform_device *pdev)
return 0;
}
+ CAM_INFO(CAM_SENSOR, "platform remove invoked");
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
+ cam_sensor_shutdown(s_ctrl);
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+ cam_unregister_subdev(&(s_ctrl->v4l2_dev_str));
soc_info = &s_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
kfree(s_ctrl->i2c_data.per_frame);
+ platform_set_drvdata(pdev, NULL);
+ v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL);
devm_kfree(&pdev->dev, s_ctrl);
return 0;
@@ -241,11 +248,17 @@ static int cam_sensor_driver_i2c_remove(struct i2c_client *client)
return 0;
}
+ CAM_INFO(CAM_SENSOR, "i2c remove invoked");
+ mutex_lock(&(s_ctrl->cam_sensor_mutex));
+ cam_sensor_shutdown(s_ctrl);
+ mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+ cam_unregister_subdev(&(s_ctrl->v4l2_dev_str));
soc_info = &s_ctrl->soc_info;
for (i = 0; i < soc_info->num_clk; i++)
devm_clk_put(soc_info->dev, soc_info->clk[i]);
kfree(s_ctrl->i2c_data.per_frame);
+ v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL);
kfree(s_ctrl);
return 0;
@@ -323,8 +336,6 @@ static int32_t cam_sensor_driver_platform_probe(
s_ctrl->sensordata->power_info.dev = &pdev->dev;
platform_set_drvdata(pdev, s_ctrl);
- v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), s_ctrl);
-
s_ctrl->sensor_state = CAM_SENSOR_INIT;
return rc;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 1e9ec3db054a..7a2c56e3b686 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -325,6 +325,9 @@ enum msm_sensor_camera_id_t {
CAMERA_1,
CAMERA_2,
CAMERA_3,
+ CAMERA_4,
+ CAMERA_5,
+ CAMERA_6,
MAX_CAMERAS,
};
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 713bcaa8643a..7f6f3aa40998 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -298,6 +298,8 @@ int cam_sensor_i2c_command_parser(
size_t len_of_buff = 0;
uintptr_t generic_ptr;
uint16_t cmd_length_in_bytes = 0;
+ size_t remain_len = 0;
+ size_t tot_size = 0;
for (i = 0; i < num_cmd_buffers; i++) {
uint32_t *cmd_buf = NULL;
@@ -319,16 +321,35 @@ int cam_sensor_i2c_command_parser(
rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
&generic_ptr, &len_of_buff);
- cmd_buf = (uint32_t *)generic_ptr;
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"cmd hdl failed:%d, Err: %d, Buffer_len: %zd",
cmd_desc[i].mem_handle, rc, len_of_buff);
return rc;
}
+
+ remain_len = len_of_buff;
+ if ((len_of_buff < sizeof(struct common_header)) ||
+ (cmd_desc[i].offset >
+ (len_of_buff - sizeof(struct common_header)))) {
+ CAM_ERR(CAM_SENSOR, "buffer provided too small");
+ return -EINVAL;
+ }
+ cmd_buf = (uint32_t *)generic_ptr;
cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+ if (remain_len < cmd_desc[i].length) {
+ CAM_ERR(CAM_SENSOR, "buffer provided too small");
+ return -EINVAL;
+ }
+
while (byte_cnt < cmd_desc[i].length) {
+ if ((remain_len - byte_cnt) <
+ sizeof(struct common_header)) {
+ CAM_ERR(CAM_SENSOR, "Not enough buffer");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
cmm_hdr = (struct common_header *)cmd_buf;
generic_op_code = cmm_hdr->third_byte;
switch (cmm_hdr->cmd_type) {
@@ -338,6 +359,24 @@ int cam_sensor_i2c_command_parser(
*cam_cmd_i2c_random_wr =
(struct cam_cmd_i2c_random_wr *)cmd_buf;
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_i2c_random_wr)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
+ tot_size = sizeof(struct i2c_rdwr_header) +
+ (sizeof(struct i2c_random_wr_payload) *
+ cam_cmd_i2c_random_wr->header.count);
+
+ if (tot_size > (remain_len - byte_cnt)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
+
rc = cam_sensor_handle_random_write(
cam_cmd_i2c_random_wr,
i2c_reg_settings,
@@ -345,7 +384,7 @@ int cam_sensor_i2c_command_parser(
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"Failed in random write %d", rc);
- return rc;
+ return -EINVAL;
}
cmd_buf += cmd_length_in_bytes /
@@ -360,6 +399,24 @@ int cam_sensor_i2c_command_parser(
(struct cam_cmd_i2c_continuous_wr *)
cmd_buf;
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_i2c_continuous_wr)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+
+ tot_size = sizeof(struct i2c_rdwr_header) +
+ sizeof(cam_cmd_i2c_continuous_wr->reg_addr) +
+ (sizeof(struct cam_cmd_read) *
+ cam_cmd_i2c_continuous_wr->header.count);
+
+ if (tot_size > (remain_len - byte_cnt)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer provided");
+ return -EINVAL;
+ }
+
rc = cam_sensor_handle_continuous_write(
cam_cmd_i2c_continuous_wr,
i2c_reg_settings,
@@ -376,11 +433,16 @@ int cam_sensor_i2c_command_parser(
break;
}
case CAMERA_SENSOR_CMD_TYPE_WAIT: {
+ if ((remain_len - byte_cnt) <
+ sizeof(struct cam_cmd_unconditional_wait)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer space");
+ return -EINVAL;
+ }
if (generic_op_code ==
CAMERA_SENSOR_WAIT_OP_HW_UCND ||
generic_op_code ==
CAMERA_SENSOR_WAIT_OP_SW_UCND) {
-
rc = cam_sensor_handle_delay(
&cmd_buf, generic_op_code,
i2c_reg_settings, j, &byte_cnt,
@@ -412,13 +474,20 @@ int cam_sensor_i2c_command_parser(
break;
}
case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: {
+ if (remain_len - byte_cnt <
+ sizeof(struct cam_cmd_i2c_info)) {
+ CAM_ERR(CAM_SENSOR,
+ "Not enough buffer space");
+ rc = -EINVAL;
+ goto rel_buf;
+ }
rc = cam_sensor_handle_slave_info(
io_master, cmd_buf);
if (rc) {
CAM_ERR(CAM_SENSOR,
- "Handle slave info failed with rc: %d",
- rc);
- return rc;
+ "Handle slave info failed with rc: %d",
+ rc);
+ goto rel_buf;
}
cmd_length_in_bytes =
sizeof(struct cam_cmd_i2c_info);
@@ -430,13 +499,23 @@ int cam_sensor_i2c_command_parser(
default:
CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d",
cmm_hdr->cmd_type);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_buf;
}
}
i2c_reg_settings->is_settings_valid = 1;
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR, "put failed for buffer :%d",
+ cmd_desc[i].mem_handle);
}
return rc;
+
+rel_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc[i].mem_handle))
+ CAM_WARN(CAM_SENSOR, "put failed for buffer :%d",
+ cmd_desc[i].mem_handle);
+ return rc;
}
int cam_sensor_util_i2c_apply_setting(
@@ -750,8 +829,32 @@ int cam_sensor_util_request_gpio_table(
return rc;
}
+
+static int32_t cam_sensor_validate(void *ptr, size_t remain_buf)
+{
+ struct common_header *cmm_hdr = (struct common_header *)ptr;
+ size_t validate_size = 0;
+
+ if (remain_buf < sizeof(struct common_header))
+ return -EINVAL;
+
+ if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_PWR_UP ||
+ cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_PWR_DOWN)
+ validate_size = sizeof(struct cam_cmd_power);
+ else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
+ validate_size = sizeof(struct cam_cmd_unconditional_wait);
+
+ if (remain_buf < validate_size) {
+ CAM_ERR(CAM_SENSOR, "Invalid cmd_buf len %zu min %zu",
+ remain_buf, validate_size);
+ return -EINVAL;
+ }
+ return 0;
+}
+
int32_t cam_sensor_update_power_settings(void *cmd_buf,
- int cmd_length, struct cam_sensor_power_ctrl_t *power_info)
+ uint32_t cmd_length, struct cam_sensor_power_ctrl_t *power_info,
+ size_t cmd_buf_len)
{
int32_t rc = 0, tot_size = 0, last_cmd_type = 0;
int32_t i = 0, pwr_up = 0, pwr_down = 0;
@@ -760,7 +863,8 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
struct cam_cmd_power *pwr_cmd = (struct cam_cmd_power *)cmd_buf;
struct common_header *cmm_hdr = (struct common_header *)cmd_buf;
- if (!pwr_cmd || !cmd_length) {
+ if (!pwr_cmd || !cmd_length || cmd_buf_len < (size_t)cmd_length ||
+ cam_sensor_validate(cmd_buf, cmd_buf_len)) {
CAM_ERR(CAM_SENSOR, "Invalid Args: pwr_cmd %pK, cmd_length: %d",
pwr_cmd, cmd_length);
return -EINVAL;
@@ -787,16 +891,29 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
}
while (tot_size < cmd_length) {
+ if (cam_sensor_validate(ptr, (cmd_length - tot_size))) {
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
if (cmm_hdr->cmd_type ==
CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
struct cam_cmd_power *pwr_cmd =
(struct cam_cmd_power *)ptr;
+ if ((U16_MAX - power_info->power_setting_size) <
+ pwr_cmd->count) {
+ CAM_ERR(CAM_SENSOR, "ERR: Overflow occurs");
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
+
power_info->power_setting_size += pwr_cmd->count;
- if (power_info->power_setting_size > MAX_POWER_CONFIG) {
+ if ((power_info->power_setting_size > MAX_POWER_CONFIG)
+ || (pwr_cmd->count >= SENSOR_SEQ_TYPE_MAX)) {
CAM_ERR(CAM_SENSOR,
- "Invalid: power up setting size %d",
- power_info->power_setting_size);
+ "pwr_up setting size %d, pwr_cmd->count: %d",
+ power_info->power_setting_size,
+ pwr_cmd->count);
rc = -EINVAL;
goto free_power_settings;
}
@@ -891,12 +1008,21 @@ int32_t cam_sensor_update_power_settings(void *cmd_buf,
scr = ptr + sizeof(struct cam_cmd_power);
tot_size = tot_size + sizeof(struct cam_cmd_power);
+ if ((U16_MAX - power_info->power_down_setting_size) <
+ pwr_cmd->count) {
+ CAM_ERR(CAM_SENSOR, "ERR: Overflow");
+ rc = -EINVAL;
+ goto free_power_settings;
+ }
+
power_info->power_down_setting_size += pwr_cmd->count;
- if (power_info->power_down_setting_size >
- MAX_POWER_CONFIG) {
+ if ((power_info->power_down_setting_size >
+ MAX_POWER_CONFIG) || (pwr_cmd->count >=
+ SENSOR_SEQ_TYPE_MAX)) {
CAM_ERR(CAM_SENSOR,
- "Invalid: power down setting size %d",
- power_info->power_down_setting_size);
+ "pwr_down_setting_size %d, pwr_cmd->count: %d",
+ power_info->power_down_setting_size,
+ pwr_cmd->count);
rc = -EINVAL;
goto free_power_settings;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
index 583ddb14243b..85497fda011c 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -60,7 +60,8 @@ int msm_camera_fill_vreg_params(struct cam_hw_soc_info *soc_info,
uint16_t power_setting_size);
int32_t cam_sensor_update_power_settings(void *cmd_buf,
- int cmd_length, struct cam_sensor_power_ctrl_t *power_info);
+ uint32_t cmd_length, struct cam_sensor_power_ctrl_t *power_info,
+ size_t cmd_buf_len);
int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info,
int bob_reg_idx, bool flag);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
index 7a772f1c4269..1be244bb7c3a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -196,8 +196,8 @@ int cam_sync_signal(int32_t sync_obj, uint32_t status)
if (row->state != CAM_SYNC_STATE_ACTIVE) {
spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
CAM_ERR(CAM_SYNC,
- "Error: Sync object already signaled sync_obj = %d",
- sync_obj);
+ "Sync object already signaled sync_obj = %d state = %d",
+ sync_obj, row->state);
return -EALREADY;
}
@@ -323,8 +323,8 @@ int cam_sync_get_obj_ref(int32_t sync_obj)
if (row->state != CAM_SYNC_STATE_ACTIVE) {
spin_unlock(&sync_dev->row_spinlocks[sync_obj]);
CAM_ERR(CAM_SYNC,
- "Error: accessing an uninitialized sync obj = %d",
- sync_obj);
+ "accessing an uninitialized sync obj = %d state = %d",
+ sync_obj, row->state);
return -EINVAL;
}
@@ -433,6 +433,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl)
static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
{
+ int rc = 0;
struct cam_sync_signal sync_signal;
if (k_ioctl->size != sizeof(struct cam_sync_signal))
@@ -447,7 +448,14 @@ static int cam_sync_handle_signal(struct cam_private_ioctl_arg *k_ioctl)
return -EFAULT;
/* need to get ref for UMD signaled fences */
- cam_sync_get_obj_ref(sync_signal.sync_obj);
+ rc = cam_sync_get_obj_ref(sync_signal.sync_obj);
+ if (rc) {
+ CAM_DBG(CAM_SYNC,
+ "Error: cannot signal an uninitialized sync obj = %d",
+ sync_signal.sync_obj);
+ return rc;
+ }
+
return cam_sync_signal(sync_signal.sync_obj,
sync_signal.sync_state);
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/Makefile b/drivers/media/platform/msm/camera_v3/cam_utils/Makefile
index 7e1ebd3b7c64..9b14dfb9f6a4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/Makefile
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/Makefile
@@ -3,3 +3,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_req_mgr/
ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_smmu/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o cam_common_util.o
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_cx_ipeak.o
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c
new file mode 100644
index 000000000000..99de0cba82ad
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.c
@@ -0,0 +1,135 @@
+/* Copyright (c) 2018, 2019, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <soc/qcom/cx_ipeak.h>
+#include "cam_soc_util.h"
+#include "cam_debug_util.h"
+
+static struct cx_ipeak_client *cam_cx_ipeak;
+static int cx_ipeak_level = CAM_NOMINAL_VOTE;
+static int cx_default_ipeak_mask;
+static int cx_current_ipeak_mask;
+static int cam_cx_client_cnt;
+
+int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info)
+{
+ int rc = 0;
+
+ soc_info->cam_cx_ipeak_enable = true;
+ soc_info->cam_cx_ipeak_bit = 1 << cam_cx_client_cnt++;
+ cx_default_ipeak_mask |= soc_info->cam_cx_ipeak_bit;
+
+ if (cam_cx_ipeak)
+ goto exit;
+
+ cam_cx_ipeak = cx_ipeak_register(soc_info->dev->of_node,
+ "qcom,cam-cx-ipeak");
+
+ if (cam_cx_ipeak) {
+ goto exit;
+ } else {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+exit:
+ CAM_DBG(CAM_UTIL, "cam_cx_ipeak is enabled for %s\n"
+ "mask = %x cx_default_ipeak_mask = %x",
+ soc_info->dev_name, soc_info->cam_cx_ipeak_bit,
+ cx_default_ipeak_mask);
+ return rc;
+}
+
+int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
+ int32_t apply_level)
+{
+ int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
+ int ret = 0;
+
+ CAM_DBG(CAM_UTIL, "E: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x",
+ apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
+
+ if (apply_level < cx_ipeak_level &&
+ (cx_current_ipeak_mask & soc_cx_ipeak_bit)) {
+ if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+ ret = cx_ipeak_update(cam_cx_ipeak, false);
+ if (ret)
+ goto exit;
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s UNVOTE",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ }
+ cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s DISABLE_BIT",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ goto exit;
+ } else if (apply_level < cx_ipeak_level) {
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x NO AI",
+ apply_level, cx_current_ipeak_mask, soc_cx_ipeak_bit);
+ goto exit;
+ }
+
+ cx_current_ipeak_mask |= soc_cx_ipeak_bit;
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s ENABLE_BIT",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+ ret = cx_ipeak_update(cam_cx_ipeak, true);
+ if (ret)
+ goto exit;
+ CAM_DBG(CAM_UTIL,
+ "X: apply_level = %d cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x %s VOTE",
+ apply_level, cx_current_ipeak_mask,
+ soc_cx_ipeak_bit, soc_info->dev_name);
+ }
+
+exit:
+ return ret;
+}
+
+int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info)
+{
+ int32_t soc_cx_ipeak_bit = soc_info->cam_cx_ipeak_bit;
+
+ CAM_DBG(CAM_UTIL, "E:cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x",
+ cx_current_ipeak_mask, soc_cx_ipeak_bit);
+ if (cx_current_ipeak_mask == cx_default_ipeak_mask) {
+ if (cam_cx_ipeak)
+ cx_ipeak_update(cam_cx_ipeak, false);
+ CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x UNVOTE",
+ cx_current_ipeak_mask, soc_cx_ipeak_bit);
+ }
+ cx_current_ipeak_mask &= (~soc_cx_ipeak_bit);
+ CAM_DBG(CAM_UTIL, "X:cx_current_ipeak_mask = %x\n"
+ "soc_cx_ipeak_bit = %x",
+ cx_current_ipeak_mask, soc_cx_ipeak_bit);
+
+ return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_log.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.h
index 321248a3e0eb..f811ac549429 100644
--- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_log.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_cx_ipeak.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,17 +10,17 @@
* GNU General Public License for more details.
*/
-#ifndef _CAM_ISP_LOG_H_
-#define _CAM_ISP_LOG_H_
+#ifndef _CAM_CX_IPEAK_H_
+#define _CAM_CX_IPEAK_H_
-#include <linux/kernel.h>
+#include <linux/clk/qcom.h>
+#include <soc/qcom/cx_ipeak.h>
+#include "cam_io_util.h"
-#define ISP_TRACE_ENABLE 1
+int cam_cx_ipeak_register_cx_ipeak(struct cam_hw_soc_info *soc_info);
-#if (ISP_TRACE_ENABLE == 1)
- #define ISP_TRACE(args...) trace_printk(args)
-#else
- #define ISP_TRACE(arg...)
-#endif
+int cam_cx_ipeak_update_vote_cx_ipeak(struct cam_hw_soc_info *soc_info,
+ int32_t apply_level);
+int cam_cx_ipeak_unvote_cx_ipeak(struct cam_hw_soc_info *soc_info);
-#endif /* __CAM_ISP_LOG_H__ */
+#endif /* _CAM_CX_IPEAK_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c
index acfae3622130..ba244e780336 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -50,23 +50,44 @@ int cam_packet_util_validate_cmd_desc(struct cam_cmd_buf_desc *cmd_desc)
return 0;
}
-int cam_packet_util_validate_packet(struct cam_packet *packet)
+int cam_packet_util_validate_packet(struct cam_packet *packet,
+ size_t remain_len)
{
+ size_t sum_cmd_desc = 0;
+ size_t sum_io_cfgs = 0;
+ size_t sum_patch_desc = 0;
+ size_t pkt_wo_payload = 0;
+
if (!packet)
return -EINVAL;
+ if ((size_t)packet->header.size > remain_len) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid packet size: %zu, CPU buf length: %zu",
+ (size_t)packet->header.size, remain_len);
+ return -EINVAL;
+ }
+
+
CAM_DBG(CAM_UTIL, "num cmd buf:%d num of io config:%d kmd buf index:%d",
packet->num_cmd_buf, packet->num_io_configs,
packet->kmd_cmd_buf_index);
- if ((packet->kmd_cmd_buf_index >= packet->num_cmd_buf) ||
- (!packet->header.size) ||
- (packet->cmd_buf_offset > packet->header.size) ||
- (packet->io_configs_offset > packet->header.size)) {
- CAM_ERR(CAM_UTIL, "invalid packet:%d %d %d %d %d",
- packet->kmd_cmd_buf_index,
- packet->num_cmd_buf, packet->cmd_buf_offset,
- packet->io_configs_offset, packet->header.size);
+ sum_cmd_desc = packet->num_cmd_buf * sizeof(struct cam_cmd_buf_desc);
+ sum_io_cfgs = packet->num_io_configs * sizeof(struct cam_buf_io_cfg);
+ sum_patch_desc = packet->num_patches * sizeof(struct cam_patch_desc);
+ pkt_wo_payload = offsetof(struct cam_packet, payload);
+
+ if ((!packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->cmd_buf_offset +
+ sum_cmd_desc) > (size_t)packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->io_configs_offset +
+ sum_io_cfgs) > (size_t)packet->header.size) ||
+ ((pkt_wo_payload + (size_t)packet->patch_offset +
+ sum_patch_desc) > (size_t)packet->header.size)) {
+ CAM_ERR(CAM_UTIL, "params not within mem len:%zu %zu %zu %zu",
+ (size_t)packet->header.size, sum_cmd_desc,
+ sum_io_cfgs, sum_patch_desc);
return -EINVAL;
}
@@ -78,6 +99,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
{
int rc = 0;
size_t len = 0;
+ size_t remain_len = 0;
struct cam_cmd_buf_desc *cmd_desc;
uint32_t *cpu_addr;
@@ -86,6 +108,13 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
return -EINVAL;
}
+ if ((packet->kmd_cmd_buf_index < 0) ||
+ (packet->kmd_cmd_buf_index > packet->num_cmd_buf)) {
+ CAM_ERR(CAM_UTIL, "Invalid kmd buf index: %d",
+ packet->kmd_cmd_buf_index);
+ return -EINVAL;
+ }
+
/* Take first command descriptor and add offset to it for kmd*/
cmd_desc = (struct cam_cmd_buf_desc *) ((uint8_t *)
&packet->payload + packet->cmd_buf_offset);
@@ -100,10 +129,21 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
if (rc)
return rc;
- if (len < cmd_desc->size) {
+ remain_len = len;
+ if (((size_t)cmd_desc->offset >= len) ||
+ ((size_t)cmd_desc->size > (len - (size_t)cmd_desc->offset))) {
CAM_ERR(CAM_UTIL, "invalid memory len:%zd and cmd desc size:%d",
len, cmd_desc->size);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_kmd_buf;
+ }
+
+ 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);
+ rc = -EINVAL;
+ goto rel_kmd_buf;
}
cpu_addr += (cmd_desc->offset / 4) + (packet->kmd_cmd_buf_offset / 4);
@@ -120,6 +160,11 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
kmd_buf->size = cmd_desc->size - cmd_desc->length;
kmd_buf->used_bytes = 0;
+rel_kmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_desc->mem_handle))
+ CAM_WARN(CAM_UTIL, "Put KMD Buf failed for: 0x%x",
+ cmd_desc->mem_handle);
+
return rc;
}
@@ -128,7 +173,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
{
struct cam_patch_desc *patch_desc = NULL;
dma_addr_t iova_addr;
- uintptr_t cpu_addr;
+ uintptr_t cpu_addr = 0;
uint32_t temp;
uint32_t *dst_cpu_addr;
uint32_t *src_buf_iova_addr;
@@ -147,7 +192,6 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
sizeof(struct cam_patch_desc));
for (i = 0; i < packet->num_patches; i++) {
-
hdl = cam_mem_is_secure_buf(patch_desc[i].src_buf_hdl) ?
sec_mmu_hdl : iommu_hdl;
rc = cam_mem_get_io_buf(patch_desc[i].src_buf_hdl,
@@ -161,7 +205,7 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl,
&cpu_addr, &dst_buf_len);
- if (rc < 0) {
+ if (rc < 0 || !cpu_addr || (dst_buf_len == 0)) {
CAM_ERR(CAM_UTIL, "unable to get dst buf address");
return rc;
}
@@ -171,6 +215,20 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
patch_desc[i].dst_buf_hdl, patch_desc[i].dst_offset,
patch_desc[i].src_buf_hdl, patch_desc[i].src_offset);
+ if ((size_t)patch_desc[i].src_offset >= src_buf_size) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid src buf patch offset");
+ return -EINVAL;
+ }
+
+ if ((dst_buf_len < sizeof(void *)) ||
+ ((dst_buf_len - sizeof(void *)) <
+ (size_t)patch_desc[i].dst_offset)) {
+ CAM_ERR(CAM_UTIL,
+ "Invalid dst buf patch offset");
+ return -EINVAL;
+ }
+
dst_cpu_addr = (uint32_t *)((uint8_t *)dst_cpu_addr +
patch_desc[i].dst_offset);
temp += patch_desc[i].src_offset;
@@ -181,6 +239,9 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
"patch is done for dst %pK with src %pK value %llx",
dst_cpu_addr, src_buf_iova_addr,
*((uint64_t *)dst_cpu_addr));
+ if (cam_mem_put_cpu_buf(patch_desc[i].dst_buf_hdl))
+ CAM_WARN(CAM_UTIL, "unable to put dst buf address:0x%x",
+ patch_desc[i].dst_buf_hdl);
}
return rc;
@@ -191,8 +252,9 @@ int cam_packet_util_process_generic_cmd_buffer(
cam_packet_generic_blob_handler blob_handler_cb, void *user_data)
{
int rc;
- uintptr_t cpu_addr;
+ uintptr_t cpu_addr = 0;
size_t buf_size;
+ size_t remain_len = 0;
uint32_t *blob_ptr;
uint32_t blob_type, blob_size, blob_block_size, len_read;
@@ -215,6 +277,21 @@ int cam_packet_util_process_generic_cmd_buffer(
return rc;
}
+ remain_len = buf_size;
+ if ((buf_size < sizeof(uint32_t)) ||
+ ((size_t)cmd_buf->offset > (buf_size - sizeof(uint32_t)))) {
+ CAM_ERR(CAM_UTIL, "Invalid offset for cmd buf: %zu",
+ (size_t)cmd_buf->offset);
+ goto rel_cmd_buf;
+ }
+ 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);
+ goto rel_cmd_buf;
+ }
+
blob_ptr = (uint32_t *)(((uint8_t *)cpu_addr) +
cmd_buf->offset);
@@ -244,7 +321,8 @@ int cam_packet_util_process_generic_cmd_buffer(
CAM_ERR(CAM_UTIL, "Invalid Blob %d %d %d %d",
blob_type, blob_size, len_read,
cmd_buf->length);
- return -EINVAL;
+ rc = -EINVAL;
+ goto rel_cmd_buf;
}
len_read += blob_block_size;
@@ -254,11 +332,16 @@ int cam_packet_util_process_generic_cmd_buffer(
if (rc) {
CAM_ERR(CAM_UTIL, "Error in handling blob type %d %d",
blob_type, blob_size);
- return rc;
+ goto rel_cmd_buf;
}
blob_ptr += (blob_block_size / sizeof(uint32_t));
}
- return 0;
+rel_cmd_buf:
+ if (cam_mem_put_cpu_buf(cmd_buf->mem_handle))
+ CAM_WARN(CAM_UTIL, "unable to put dst buf address: 0x%x",
+ cmd_buf->mem_handle);
+
+ return rc;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
index b2315232262d..412eba52b05a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -37,6 +37,9 @@ struct cam_kmd_buf_info {
typedef int (*cam_packet_generic_blob_handler)(void *user_data,
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data);
+/* set resource bitmap callback function type */
+typedef void (*cam_fill_res_bitmap)(uint32_t res_type, unsigned long *bitmap);
+
/**
* cam_packet_util_get_cmd_mem_addr()
*
@@ -59,10 +62,13 @@ int cam_packet_util_get_cmd_mem_addr(int handle, uint32_t **buf_addr,
*
* @packet: Packet to be validated
*
+ * @remain_len: CPU buff length after config offset
+ *
* @return: 0 for success
* -EINVAL for Fail
*/
-int cam_packet_util_validate_packet(struct cam_packet *packet);
+int cam_packet_util_validate_packet(struct cam_packet *packet,
+ size_t remain_len);
/**
* cam_packet_util_validate_cmd_desc()
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
index 4972a2a8cd08..693b0da29be2 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
#include <soc/qcom/socinfo.h>
#include "cam_soc_util.h"
#include "cam_debug_util.h"
+#include "cam_cx_ipeak.h"
#include <linux/nvmem-consumer.h>
uint32_t cam_soc_util_get_soc_id(void)
@@ -75,6 +76,33 @@ uint32_t cam_soc_util_get_hw_revision_node(struct cam_hw_soc_info *soc_info)
static char supported_clk_info[256];
static char debugfs_dir_name[64];
+static int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
+ int32_t src_clk_idx, int32_t clk_rate)
+{
+ int i;
+ long clk_rate_round;
+
+ clk_rate_round = clk_round_rate(soc_info->clk[src_clk_idx], clk_rate);
+ if (clk_rate_round < 0) {
+ CAM_ERR(CAM_UTIL, "round failed rc = %ld",
+ clk_rate_round);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < CAM_MAX_VOTE; i++) {
+ if (soc_info->clk_rate[i][src_clk_idx] >= clk_rate_round) {
+ CAM_DBG(CAM_UTIL,
+ "soc = %d round rate = %ld actual = %d",
+ soc_info->clk_rate[i][src_clk_idx],
+ clk_rate_round, clk_rate);
+ return i;
+ }
+ }
+
+ CAM_WARN(CAM_UTIL, "Invalid clock rate %ld", clk_rate_round);
+ return -EINVAL;
+}
+
/**
* cam_soc_util_get_string_from_level()
*
@@ -461,6 +489,7 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
{
int32_t src_clk_idx;
struct clk *clk = NULL;
+ int32_t apply_level;
if (!soc_info || (soc_info->src_clk_idx < 0))
return -EINVAL;
@@ -471,6 +500,17 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
src_clk_idx = soc_info->src_clk_idx;
clk = soc_info->clk[src_clk_idx];
+ if (soc_info->cam_cx_ipeak_enable && clk_rate >= 0) {
+ apply_level = cam_soc_util_get_clk_level(soc_info, src_clk_idx,
+ clk_rate);
+ CAM_DBG(CAM_UTIL, "set %s, rate %d dev_name = %s\n"
+ "apply level = %d",
+ soc_info->clk_name[src_clk_idx], clk_rate,
+ soc_info->dev_name, apply_level);
+ if (apply_level >= 0)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info,
+ apply_level);
+ }
return cam_soc_util_set_clk_rate(clk,
soc_info->clk_name[src_clk_idx], clk_rate);
@@ -623,17 +663,29 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
if (rc)
return rc;
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+
for (i = 0; i < soc_info->num_clk; i++) {
rc = cam_soc_util_clk_enable(soc_info->clk[i],
soc_info->clk_name[i],
soc_info->clk_rate[apply_level][i]);
if (rc)
goto clk_disable;
+ if (soc_info->cam_cx_ipeak_enable) {
+ CAM_DBG(CAM_UTIL,
+ "dev name = %s clk name = %s idx = %d\n"
+ "apply_level = %d clc idx = %d",
+ soc_info->dev_name, soc_info->clk_name[i], i,
+ apply_level, i);
+ }
}
return rc;
clk_disable:
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
for (i--; i >= 0; i--) {
cam_soc_util_clk_disable(soc_info->clk[i],
soc_info->clk_name[i]);
@@ -659,6 +711,8 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
if (soc_info->num_clk == 0)
return;
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_unvote_cx_ipeak(soc_info);
for (i = soc_info->num_clk - 1; i >= 0; i--)
cam_soc_util_clk_disable(soc_info->clk[i],
soc_info->clk_name[i]);
@@ -700,7 +754,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
count = of_property_count_strings(of_node, "clock-names");
- CAM_DBG(CAM_UTIL, "count = %d", count);
+ CAM_DBG(CAM_UTIL, "E: dev_name = %s count = %d",
+ soc_info->dev_name, count);
if (count > CAM_SOC_MAX_CLK) {
CAM_ERR(CAM_UTIL, "invalid count of clocks, count=%d", count);
rc = -EINVAL;
@@ -819,6 +874,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
if (strcmp("true", clk_control_debugfs) == 0)
soc_info->clk_control_enable = true;
+ CAM_DBG(CAM_UTIL, "X: dev_name = %s count = %d",
+ soc_info->dev_name, count);
end:
return rc;
}
@@ -841,12 +898,23 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
if (rc)
return rc;
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
+
for (i = 0; i < soc_info->num_clk; i++) {
rc = cam_soc_util_set_clk_rate(soc_info->clk[i],
soc_info->clk_name[i],
soc_info->clk_rate[apply_level][i]);
- if (rc)
+ if (rc < 0) {
+ CAM_DBG(CAM_UTIL,
+ "dev name = %s clk_name = %s idx = %d\n"
+ "apply_level = %d",
+ soc_info->dev_name, soc_info->clk_name[i],
+ i, apply_level);
+ if (soc_info->cam_cx_ipeak_enable)
+ cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
break;
+ }
}
return rc;
@@ -1214,6 +1282,9 @@ int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info)
if (rc)
return rc;
+ if (of_find_property(of_node, "qcom,cam-cx-ipeak", NULL))
+ rc = cam_cx_ipeak_register_cx_ipeak(soc_info);
+
return rc;
}
@@ -1322,7 +1393,8 @@ int cam_soc_util_regulator_enable(struct regulator *rgltr,
}
static int cam_soc_util_request_pinctrl(
- struct cam_hw_soc_info *soc_info) {
+ struct cam_hw_soc_info *soc_info)
+{
struct cam_soc_pinctrl_info *device_pctrl = &soc_info->pinctrl_info;
struct device *dev = soc_info->dev;
@@ -1698,3 +1770,25 @@ 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/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
index 91cc50daea83..ee07f0eb0a5d 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_soc_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -156,6 +156,7 @@ struct cam_soc_gpio_data {
* @clk: Array of associated clock resources
* @clk_rate: 2D array of clock rates representing clock rate
* values at different vote levels
+ * @prev_clk_level Last vote level
* @src_clk_idx: Source clock index that is rate-controllable
* @clk_level_valid: Indicates whether corresponding level is valid
* @gpio_data: Pointer to gpio info
@@ -163,6 +164,8 @@ struct cam_soc_gpio_data {
* @dentry: Debugfs entry
* @clk_level_override: Clk level set from debugfs
* @clk_control: Enable/disable clk rate control through debugfs
+ * @cam_cx_ipeak_enable cx-ipeak enable/disable flag
+ * @cam_cx_ipeak_bit cx-ipeak mask for driver
* @soc_private: Soc private data
*/
struct cam_hw_soc_info {
@@ -198,6 +201,7 @@ struct cam_hw_soc_info {
const char *clk_name[CAM_SOC_MAX_CLK];
struct clk *clk[CAM_SOC_MAX_CLK];
int32_t clk_rate[CAM_MAX_VOTE][CAM_SOC_MAX_CLK];
+ int32_t prev_clk_level;
int32_t src_clk_idx;
bool clk_level_valid[CAM_MAX_VOTE];
@@ -207,6 +211,8 @@ struct cam_hw_soc_info {
struct dentry *dentry;
uint32_t clk_level_override;
bool clk_control_enable;
+ bool cam_cx_ipeak_enable;
+ int32_t cam_cx_ipeak_bit;
void *soc_private;
};
@@ -631,6 +637,10 @@ 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);
+
/**
* cam_soc_util_get_soc_id()
*
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 0cdcbd6e0df1..225bd239d9c8 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -384,9 +384,10 @@ static int hfi_process_session_error(u32 device_id,
}
static int hfi_process_event_notify(u32 device_id,
- struct hfi_msg_event_notify_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_event_notify_packet *pkt = _pkt;
dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n");
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
@@ -425,9 +426,10 @@ static int hfi_process_event_notify(u32 device_id,
}
static int hfi_process_sys_init_done(u32 device_id,
- struct hfi_msg_sys_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
@@ -464,9 +466,10 @@ err_no_prop:
}
static int hfi_process_sys_rel_resource_done(u32 device_id,
- struct hfi_msg_sys_release_resource_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_release_resource_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
u32 pkt_size;
@@ -776,6 +779,11 @@ static int hfi_fill_codec_info(u8 *data_ptr,
vidc_get_hal_codec((1 << i) & codecs);
capability->domain =
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_DECODER);
+ if (codec_count == VIDC_MAX_DECODE_SESSIONS) {
+ dprintk(VIDC_ERR,
+ "Max supported decoder sessions reached");
+ break;
+ }
}
}
codecs = sys_init_done->enc_codec_supported;
@@ -787,6 +795,11 @@ static int hfi_fill_codec_info(u8 *data_ptr,
vidc_get_hal_codec((1 << i) & codecs);
capability->domain =
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_ENCODER);
+ if (codec_count == VIDC_MAX_SESSIONS) {
+ dprintk(VIDC_ERR,
+ "Max supported sessions reached");
+ break;
+ }
}
}
sys_init_done->codec_count = codec_count;
@@ -1264,9 +1277,10 @@ static void hfi_process_sess_get_prop_buf_req(
}
static int hfi_process_session_prop_info(u32 device_id,
- struct hfi_msg_session_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_property_info_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct buffer_requirements buff_req = { { {0} } };
@@ -1305,9 +1319,10 @@ static int hfi_process_session_prop_info(u32 device_id,
}
static int hfi_process_session_init_done(u32 device_id,
- struct hfi_msg_sys_session_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct vidc_hal_session_init_done session_init_done = { {0} };
@@ -1332,9 +1347,10 @@ static int hfi_process_session_init_done(u32 device_id,
}
static int hfi_process_session_load_res_done(u32 device_id,
- struct hfi_msg_session_load_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_load_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n",
@@ -1360,9 +1376,10 @@ static int hfi_process_session_load_res_done(u32 device_id,
}
static int hfi_process_session_flush_done(u32 device_id,
- struct hfi_msg_session_flush_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_flush_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
@@ -1403,9 +1420,10 @@ static int hfi_process_session_flush_done(u32 device_id,
}
static int hfi_process_session_etb_done(u32 device_id,
- struct hfi_msg_session_empty_buffer_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL;
@@ -1457,9 +1475,10 @@ static int hfi_process_session_etb_done(u32 device_id,
}
static int hfi_process_session_ftb_done(
- u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ u32 device_id, void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct vidc_hal_msg_pkt_hdr *msg_hdr = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
bool is_decoder = false, is_encoder = false;
@@ -1585,9 +1604,10 @@ static int hfi_process_session_ftb_done(
}
static int hfi_process_session_start_done(u32 device_id,
- struct hfi_msg_session_start_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_start_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%#x]\n",
@@ -1611,9 +1631,10 @@ static int hfi_process_session_start_done(u32 device_id,
}
static int hfi_process_session_stop_done(u32 device_id,
- struct hfi_msg_session_stop_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_stop_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%#x]\n",
@@ -1638,9 +1659,10 @@ static int hfi_process_session_stop_done(u32 device_id,
}
static int hfi_process_session_rel_res_done(u32 device_id,
- struct hfi_msg_session_release_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n",
@@ -1665,9 +1687,10 @@ static int hfi_process_session_rel_res_done(u32 device_id,
}
static int hfi_process_session_rel_buf_done(u32 device_id,
- struct hfi_msg_session_release_buffers_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_buffers_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
if (!pkt || pkt->size <
@@ -1698,9 +1721,10 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
}
static int hfi_process_session_end_done(u32 device_id,
- struct hfi_msg_sys_session_end_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_end_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
@@ -1723,9 +1747,10 @@ static int hfi_process_session_end_done(u32 device_id,
}
static int hfi_process_session_abort_done(u32 device_id,
- struct hfi_msg_sys_session_abort_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_abort_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
@@ -1793,9 +1818,10 @@ static void hfi_process_sys_get_prop_image_version(
}
static int hfi_process_sys_property_info(u32 device_id,
- struct hfi_msg_sys_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_property_info_packet *pkt = _pkt;
if (!pkt) {
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
return -EINVAL;
@@ -1827,7 +1853,7 @@ static int hfi_process_sys_property_info(u32 device_id,
}
static int hfi_process_ignore(u32 device_id,
- struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
*info = (struct msm_vidc_cb_info) {
@@ -1908,5 +1934,6 @@ int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
break;
}
- return pkt_func ? pkt_func(device_id, msg_hdr, info) : -ENOTSUPP;
+ return pkt_func ?
+ pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index f69b98e828b6..f1fbf990daef 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -66,6 +66,9 @@
/* 16 encoder and 16 decoder sessions */
#define VIDC_MAX_SESSIONS 32
+#define VIDC_MAX_DECODE_SESSIONS 16
+#define VIDC_MAX_ENCODE_SESSIONS 16
+
enum vidc_status {
VIDC_ERR_NONE = 0x0,
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index ca9edc8bebd1..9f85f5d8b0f0 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -322,9 +322,10 @@ static int hfi_process_session_error(u32 device_id,
}
static int hfi_process_event_notify(u32 device_id,
- struct hfi_msg_event_notify_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_event_notify_packet *pkt = _pkt;
dprintk(VIDC_DBG, "Received: EVENT_NOTIFY\n");
if (pkt->size < sizeof(struct hfi_msg_event_notify_packet)) {
@@ -363,9 +364,10 @@ static int hfi_process_event_notify(u32 device_id,
}
static int hfi_process_sys_init_done(u32 device_id,
- struct hfi_msg_sys_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
@@ -402,9 +404,10 @@ err_no_prop:
}
static int hfi_process_sys_rel_resource_done(u32 device_id,
- struct hfi_msg_sys_release_resource_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_release_resource_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
enum vidc_status status = VIDC_ERR_NONE;
u32 pkt_size;
@@ -608,6 +611,11 @@ static int hfi_fill_codec_info(u8 *data_ptr,
vidc_get_hal_codec((1 << i) & codecs);
capability->domain =
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_DECODER);
+ if (codec_count == VIDC_MAX_DECODE_SESSIONS) {
+ dprintk(VIDC_ERR,
+ "Max supported decoder sessions reached\n");
+ break;
+ }
}
}
codecs = sys_init_done->enc_codec_supported;
@@ -619,6 +627,11 @@ static int hfi_fill_codec_info(u8 *data_ptr,
vidc_get_hal_codec((1 << i) & codecs);
capability->domain =
vidc_get_hal_domain(HFI_VIDEO_DOMAIN_ENCODER);
+ if (codec_count == VIDC_MAX_SESSIONS) {
+ dprintk(VIDC_ERR,
+ "Max supported sessions reached\n");
+ break;
+ }
}
}
sys_init_done->codec_count = codec_count;
@@ -1218,9 +1231,10 @@ static void hfi_process_sess_get_prop_buf_req(
}
static int hfi_process_session_prop_info(u32 device_id,
- struct hfi_msg_session_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_property_info_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct hfi_profile_level profile_level = {0};
enum hal_h264_entropy entropy = HAL_UNUSED_ENTROPY;
@@ -1293,9 +1307,10 @@ static int hfi_process_session_prop_info(u32 device_id,
}
static int hfi_process_session_init_done(u32 device_id,
- struct hfi_msg_sys_session_init_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_init_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
struct vidc_hal_session_init_done session_init_done = { {0} };
@@ -1327,9 +1342,10 @@ static int hfi_process_session_init_done(u32 device_id,
}
static int hfi_process_session_load_res_done(u32 device_id,
- struct hfi_msg_session_load_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_load_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%#x]\n",
@@ -1357,9 +1373,10 @@ static int hfi_process_session_load_res_done(u32 device_id,
}
static int hfi_process_session_flush_done(u32 device_id,
- struct hfi_msg_session_flush_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_flush_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n",
@@ -1402,9 +1419,10 @@ static int hfi_process_session_flush_done(u32 device_id,
}
static int hfi_process_session_etb_done(u32 device_id,
- struct hfi_msg_session_empty_buffer_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL;
@@ -1453,9 +1471,10 @@ static int hfi_process_session_etb_done(u32 device_id,
}
static int hfi_process_session_ftb_done(
- u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ u32 device_id, void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct vidc_hal_msg_pkt_hdr *msg_hdr = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
bool is_decoder = false, is_encoder = false;
@@ -1580,9 +1599,10 @@ static int hfi_process_session_ftb_done(
}
static int hfi_process_session_start_done(u32 device_id,
- struct hfi_msg_session_start_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_start_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%#x]\n",
@@ -1608,9 +1628,10 @@ static int hfi_process_session_start_done(u32 device_id,
}
static int hfi_process_session_stop_done(u32 device_id,
- struct hfi_msg_session_stop_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_stop_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%#x]\n",
@@ -1637,9 +1658,10 @@ static int hfi_process_session_stop_done(u32 device_id,
}
static int hfi_process_session_rel_res_done(u32 device_id,
- struct hfi_msg_session_release_resources_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_resources_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%#x]\n",
@@ -1666,9 +1688,10 @@ static int hfi_process_session_rel_res_done(u32 device_id,
}
static int hfi_process_session_rel_buf_done(u32 device_id,
- struct hfi_msg_session_release_buffers_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_session_release_buffers_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
if (!pkt || pkt->size <
@@ -1701,9 +1724,10 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
}
static int hfi_process_session_end_done(u32 device_id,
- struct hfi_msg_sys_session_end_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_end_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
@@ -1728,9 +1752,10 @@ static int hfi_process_session_end_done(u32 device_id,
}
static int hfi_process_session_abort_done(u32 device_id,
- struct hfi_msg_sys_session_abort_done_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_session_abort_done_packet *pkt = _pkt;
struct msm_vidc_cb_cmd_done cmd_done = {0};
dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
@@ -1836,9 +1861,10 @@ static void hfi_process_sys_get_prop_image_version(
}
static int hfi_process_sys_property_info(u32 device_id,
- struct hfi_msg_sys_property_info_packet *pkt,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
+ struct hfi_msg_sys_property_info_packet *pkt = _pkt;
if (!pkt) {
dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
return -EINVAL;
@@ -1870,7 +1896,7 @@ static int hfi_process_sys_property_info(u32 device_id,
}
static int hfi_process_ignore(u32 device_id,
- struct vidc_hal_msg_pkt_hdr *msg_hdr,
+ void *_pkt,
struct msm_vidc_cb_info *info)
{
*info = (struct msm_vidc_cb_info) {
@@ -1954,5 +1980,6 @@ int hfi_process_msg_packet(u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr,
break;
}
- return pkt_func ? pkt_func(device_id, msg_hdr, info) : -ENOTSUPP;
+ return pkt_func ?
+ pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
}
diff --git a/drivers/media/platform/msm/vidc_3x/msm_smem.c b/drivers/media/platform/msm/vidc_3x/msm_smem.c
index a6d54765bd88..b67da1fc75b7 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_smem.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -476,7 +476,8 @@ bool msm_smem_compare_buffers(void *clt, int fd, void *priv)
}
handle = ion_import_dma_buf_fd(client->clnt, fd);
ret = handle == priv;
- handle ? ion_free(client->clnt, handle) : 0;
+ if (!IS_ERR_OR_NULL(handle))
+ ion_free(client->clnt, handle);
return ret;
}
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc.c b/drivers/media/platform/msm/vidc_3x/msm_vidc.c
index 983e600c6480..0a2d380dbbd7 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1278,13 +1278,12 @@ void *msm_vidc_open(int core_id, int session_type)
return inst;
fail_init:
+ mutex_lock(&core->lock);
v4l2_fh_del(&inst->event_handler);
v4l2_fh_exit(&inst->event_handler);
- vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
-
- mutex_lock(&core->lock);
list_del(&inst->list);
mutex_unlock(&core->lock);
+ vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
fail_bufq_output:
vb2_queue_release(&inst->bufq[CAPTURE_PORT].vb2_bufq);
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
index 22f49ce02e47..af2514c60065 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1638,11 +1638,11 @@ static void msm_comm_clean_notify_client(struct msm_vidc_core *core)
list_for_each_entry(inst, &core->instances, list) {
mutex_lock(&inst->lock);
inst->state = MSM_VIDC_CORE_INVALID;
- mutex_unlock(&inst->lock);
dprintk(VIDC_WARN,
"%s Send sys error for inst %pK\n", __func__, inst);
msm_vidc_queue_v4l2_event(inst,
V4L2_EVENT_MSM_VIDC_SYS_ERROR);
+ mutex_unlock(&inst->lock);
}
mutex_unlock(&core->lock);
}
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
index 552e578e15c0..e383a6c56ffe 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -40,8 +40,8 @@
#define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1)
#define MAX_DEBUGFS_NAME 50
#define DEFAULT_TIMEOUT 3
-#define DEFAULT_HEIGHT 1088
-#define DEFAULT_WIDTH 1920
+#define DEFAULT_HEIGHT 144
+#define DEFAULT_WIDTH 176
#define MIN_SUPPORTED_WIDTH 32
#define MIN_SUPPORTED_HEIGHT 32
#define DEFAULT_FPS 15
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h
index 875db097d9b2..a53d0b0f4f83 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -66,6 +66,9 @@
/* 16 encoder and 16 decoder sessions */
#define VIDC_MAX_SESSIONS 32
+#define VIDC_MAX_DECODE_SESSIONS 16
+#define VIDC_MAX_ENCODE_SESSIONS 16
+
enum vidc_status {
VIDC_ERR_NONE = 0x0,
diff --git a/drivers/misc/hdcp_qseecom.c b/drivers/misc/hdcp_qseecom.c
index 6ce377667623..f45dca30b11a 100644
--- a/drivers/misc/hdcp_qseecom.c
+++ b/drivers/misc/hdcp_qseecom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -42,7 +42,7 @@
#define HDCP1_APP_NAME "hdcp1"
#define QSEECOM_SBUFF_SIZE 0x1000
-#define MAX_TX_MESSAGE_SIZE 129
+#define MAX_TX_MESSAGE_SIZE 132
#define MAX_RX_MESSAGE_SIZE 534
#define MAX_TOPOLOGY_ELEMS 32
#define HDCP1_AKSV_SIZE 8
@@ -2037,6 +2037,30 @@ bool hdcp1_check_if_supported_load_app(void)
return hdcp1_supported;
}
+void hdcp1_unload_app(void)
+{
+ int rc = 0;
+
+ if (!hdcp1_supported) {
+ pr_debug("hdcp1 is not supported\n");
+ return;
+ }
+
+ if (!hdcp1_handle) {
+ pr_debug("invalid hdcp1 handle\n");
+ return;
+ }
+
+ rc = qseecom_shutdown_app(&hdcp1_handle);
+ if (rc) {
+ pr_debug("qseecom_shutdown_app failed with ERR = %d\n", rc);
+ return;
+ }
+
+ hdcp1_handle = NULL;
+ pr_debug("hdcp1 app unloaded\n");
+}
+
/* APIs exposed to all clients */
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb)
{
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 07dbf1740353..8c774bd72a6d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -50,6 +50,7 @@
#include <linux/compat.h>
#include "compat_qseecom.h"
+#include <linux/kthread.h>
#define QSEECOM_DEV "qseecom"
#define QSEOS_VERSION_14 0x14
@@ -109,6 +110,9 @@
#define DEFAULT_CE_INFO_UNIT 0
#define DEFAULT_NUM_CE_INFO_UNIT 1
+#define FDE_FLAG_POS 4
+#define ENABLE_KEY_WRAP_IN_KS (1 << FDE_FLAG_POS)
+
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
@@ -137,6 +141,11 @@ enum qseecom_ce_hw_instance {
CLK_INVALID,
};
+enum qseecom_listener_unregister_kthread_state {
+ LSNR_UNREG_KT_SLEEP = 0,
+ LSNR_UNREG_KT_WAKEUP,
+};
+
static struct class *driver_class;
static dev_t qseecom_device_no;
@@ -285,6 +294,7 @@ struct qseecom_control {
unsigned int ce_opp_freq_hz;
bool appsbl_qseecom_support;
uint32_t qsee_reentrancy_support;
+ bool enable_key_wrap_in_ks;
uint32_t app_block_ref_cnt;
wait_queue_head_t app_block_wq;
@@ -294,6 +304,9 @@ struct qseecom_control {
struct list_head unregister_lsnr_pending_list_head;
wait_queue_head_t register_lsnr_pending_wq;
+ struct task_struct *unregister_lsnr_kthread_task;
+ wait_queue_head_t unregister_lsnr_kthread_wq;
+ atomic_t unregister_lsnr_kthread_state;
};
struct qseecom_sec_buf_fd_info {
@@ -318,6 +331,7 @@ struct qseecom_client_handle {
char app_name[MAX_APP_NAME_SIZE];
u32 app_arch;
struct qseecom_sec_buf_fd_info sec_buf_fd[MAX_ION_FD];
+ bool from_smcinvoke;
};
struct qseecom_listener_handle {
@@ -403,6 +417,29 @@ static int get_qseecom_keymaster_status(char *str)
}
__setup("androidboot.keymaster=", get_qseecom_keymaster_status);
+
+#define QSEECOM_SCM_EBUSY_WAIT_MS 30
+#define QSEECOM_SCM_EBUSY_MAX_RETRY 67
+
+static int __qseecom_scm_call2_locked(uint32_t smc_id, struct scm_desc *desc)
+{
+ int ret = 0;
+ int retry_count = 0;
+
+ do {
+ ret = scm_call2_noretry(smc_id, desc);
+ if (ret == -EBUSY) {
+ mutex_unlock(&app_access_lock);
+ msleep(QSEECOM_SCM_EBUSY_WAIT_MS);
+ mutex_lock(&app_access_lock);
+ }
+ if (retry_count == 33)
+ pr_warn("secure world has been busy for 1 second!\n");
+ } while (ret == -EBUSY &&
+ (retry_count++ < QSEECOM_SCM_EBUSY_MAX_RETRY));
+ return ret;
+}
+
static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
const void *req_buf, void *resp_buf)
{
@@ -430,7 +467,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
svc_id, tz_cmd_id);
return -EINVAL;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case SCM_SVC_ES: {
@@ -453,7 +490,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = p_hash_req->partition_id;
desc.args[1] = virt_to_phys(tzbuf);
desc.args[2] = SHA256_DIGEST_LENGTH;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -488,7 +525,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64bit->phy_addr;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_APP_SHUTDOWN_COMMAND: {
@@ -498,7 +535,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
smc_id = TZ_OS_APP_SHUTDOWN_ID;
desc.arginfo = TZ_OS_APP_SHUTDOWN_ID_PARAM_ID;
desc.args[0] = req->app_id;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_APP_LOOKUP_COMMAND: {
@@ -517,7 +554,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = strlen(req->app_name);
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -541,7 +578,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[1] = req_64bit->size;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LOAD_SERV_IMAGE_COMMAND: {
@@ -565,14 +602,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64bit->phy_addr;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_UNLOAD_SERV_IMAGE_COMMAND: {
smc_id = TZ_OS_UNLOAD_SERVICES_IMAGE_ID;
desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_REGISTER_LISTENER: {
@@ -597,11 +634,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
}
qseecom.smcinvoke_support = true;
smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID;
- ret = scm_call2(smc_id, &desc);
- if (ret && ret != -EBUSY) {
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
+ if (ret == -EIO) {
+ /* smcinvoke is not supported */
qseecom.smcinvoke_support = false;
smc_id = TZ_OS_REGISTER_LISTENER_ID;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
}
break;
}
@@ -613,7 +651,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
smc_id = TZ_OS_DEREGISTER_LISTENER_ID;
desc.arginfo = TZ_OS_DEREGISTER_LISTENER_ID_PARAM_ID;
desc.args[0] = req->listener_id;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LISTENER_DATA_RSP_COMMAND: {
@@ -626,7 +664,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
TZ_OS_LISTENER_RESPONSE_HANDLER_ID_PARAM_ID;
desc.args[0] = req->listener_id;
desc.args[1] = req->status;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: {
@@ -654,7 +692,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64->sglistinfo_ptr;
desc.args[3] = req_64->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: {
@@ -676,14 +714,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[2] = req_64bit->phy_addr;
}
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND: {
smc_id = TZ_OS_UNLOAD_EXTERNAL_IMAGE_ID;
desc.arginfo = TZ_OS_UNLOAD_SERVICES_IMAGE_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
@@ -711,7 +749,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->rsp_ptr;
desc.args[4] = req_64bit->rsp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST: {
@@ -743,7 +781,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[5] = req_64bit->sglistinfo_ptr;
desc.args[6] = req_64bit->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_RPMB_PROVISION_KEY_COMMAND: {
@@ -755,21 +793,21 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.arginfo = TZ_OS_RPMB_PROVISION_KEY_ID_PARAM_ID;
desc.args[0] = req->key_type;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_RPMB_ERASE_COMMAND: {
smc_id = TZ_OS_RPMB_ERASE_ID;
desc.arginfo = TZ_OS_RPMB_ERASE_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_RPMB_CHECK_PROV_STATUS_COMMAND: {
smc_id = TZ_OS_RPMB_CHECK_PROV_STATUS_ID;
desc.arginfo = TZ_OS_RPMB_CHECK_PROV_STATUS_ID_PARAM_ID;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_GENERATE_KEY: {
@@ -790,7 +828,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -812,7 +850,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -834,7 +872,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -856,7 +894,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[0] = virt_to_phys(tzbuf);
desc.args[1] = tzbuflen;
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
kzfree(tzbuf);
break;
}
@@ -882,7 +920,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_OPEN_SESSION_WHITELIST: {
@@ -912,7 +950,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[5] = req_64bit->sglistinfo_ptr;
desc.args[6] = req_64bit->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_INVOKE_COMMAND: {
@@ -937,7 +975,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_INVOKE_COMMAND_WHITELIST: {
@@ -967,7 +1005,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[5] = req_64bit->sglistinfo_ptr;
desc.args[6] = req_64bit->sglistinfo_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_CLOSE_SESSION: {
@@ -992,7 +1030,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_TEE_REQUEST_CANCELLATION: {
@@ -1018,7 +1056,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.args[3] = req_64bit->resp_ptr;
desc.args[4] = req_64bit->resp_len;
}
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
case QSEOS_CONTINUE_BLOCKED_REQ_COMMAND: {
@@ -1033,7 +1071,7 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
desc.arginfo =
TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID;
desc.args[0] = req->app_or_session_id;
- ret = scm_call2(smc_id, &desc);
+ ret = __qseecom_scm_call2_locked(smc_id, &desc);
break;
}
default: {
@@ -1144,8 +1182,14 @@ static int __qseecom_set_sb_memory(struct qseecom_registered_listener_list *svc,
resp.result = QSEOS_RESULT_INCOMPLETE;
+ mutex_unlock(&listener_access_lock);
+ mutex_lock(&app_access_lock);
+ __qseecom_reentrancy_check_if_no_app_blocked(
+ TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID);
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len,
&resp, sizeof(resp));
+ mutex_unlock(&app_access_lock);
+ mutex_lock(&listener_access_lock);
if (ret) {
pr_err("qseecom_scm_call failed with err: %d\n", ret);
return -EINVAL;
@@ -1241,8 +1285,14 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data,
req.listener_id = data->listener.id;
resp.result = QSEOS_RESULT_INCOMPLETE;
+ mutex_unlock(&listener_access_lock);
+ mutex_lock(&app_access_lock);
+ __qseecom_reentrancy_check_if_no_app_blocked(
+ TZ_OS_DEREGISTER_LISTENER_ID);
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(req), &resp, sizeof(resp));
+ mutex_unlock(&app_access_lock);
+ mutex_lock(&listener_access_lock);
if (ret) {
pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
ret, data->listener.id);
@@ -1258,9 +1308,6 @@ static int __qseecom_unregister_listener(struct qseecom_dev_handle *data,
goto exit;
}
- data->abort = 1;
- wake_up_all(&ptr_svc->rcv_req_wq);
-
while (atomic_read(&data->ioctl_count) > 1) {
if (wait_event_freezable(data->abort_wq,
atomic_read(&data->ioctl_count) <= 1)) {
@@ -1299,6 +1346,10 @@ static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
ptr_svc->abort = 1;
wake_up_interruptible_all(&qseecom.send_resp_wq);
+ /* stop listener thread waiting for listener request */
+ data->abort = 1;
+ wake_up_all(&ptr_svc->rcv_req_wq);
+
/* return directly if pending*/
if (ptr_svc->unregister_pending)
return 0;
@@ -1356,6 +1407,30 @@ static void __qseecom_processing_pending_lsnr_unregister(void)
wake_up_interruptible(&qseecom.register_lsnr_pending_wq);
}
+static void __wakeup_unregister_listener_kthread(void)
+{
+ atomic_set(&qseecom.unregister_lsnr_kthread_state,
+ LSNR_UNREG_KT_WAKEUP);
+ wake_up_interruptible(&qseecom.unregister_lsnr_kthread_wq);
+}
+
+static int __qseecom_unregister_listener_kthread_func(void *data)
+{
+ while (!kthread_should_stop()) {
+ wait_event_freezable(
+ qseecom.unregister_lsnr_kthread_wq,
+ atomic_read(&qseecom.unregister_lsnr_kthread_state)
+ == LSNR_UNREG_KT_WAKEUP);
+ pr_debug("kthread to unregister listener is called %d\n",
+ atomic_read(&qseecom.unregister_lsnr_kthread_state));
+ __qseecom_processing_pending_lsnr_unregister();
+ atomic_set(&qseecom.unregister_lsnr_kthread_state,
+ LSNR_UNREG_KT_SLEEP);
+ }
+ pr_warn("kthread to unregister listener stopped\n");
+ return 0;
+}
+
static int __qseecom_set_msm_bus_request(uint32_t mode)
{
int ret = 0;
@@ -1832,7 +1907,7 @@ err_resp:
else
*(uint32_t *)cmd_buf =
QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST;
- if (ptr_svc) {
+ if (ptr_svc && ptr_svc->ihandle) {
ret = msm_ion_do_cache_op(qseecom.ion_clnt,
ptr_svc->ihandle,
ptr_svc->sb_virt, ptr_svc->sb_length,
@@ -1898,6 +1973,7 @@ static int __qseecom_process_reentrancy_blocked_on_listener(
sigset_t old_sigset;
unsigned long flags;
bool found_app = false;
+ struct qseecom_registered_app_list dummy_app_entry = { {NULL} };
if (!resp || !data) {
pr_err("invalid resp or data pointer\n");
@@ -1907,24 +1983,31 @@ static int __qseecom_process_reentrancy_blocked_on_listener(
/* find app_id & img_name from list */
if (!ptr_app) {
- spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
- list_for_each_entry(ptr_app, &qseecom.registered_app_list_head,
- list) {
- if ((ptr_app->app_id == data->client.app_id) &&
- (!strcmp(ptr_app->app_name,
+ if (data->client.from_smcinvoke) {
+ pr_debug("This request is from smcinvoke\n");
+ ptr_app = &dummy_app_entry;
+ ptr_app->app_id = data->client.app_id;
+ } else {
+ spin_lock_irqsave(&qseecom.registered_app_list_lock,
+ flags);
+ list_for_each_entry(ptr_app,
+ &qseecom.registered_app_list_head, list) {
+ if ((ptr_app->app_id == data->client.app_id) &&
+ (!strcmp(ptr_app->app_name,
data->client.app_name))) {
- found_app = true;
- break;
+ found_app = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(
+ &qseecom.registered_app_list_lock, flags);
+ if (!found_app) {
+ pr_err("app_id %d (%s) is not found\n",
+ data->client.app_id,
+ (char *)data->client.app_name);
+ ret = -ENOENT;
+ goto exit;
}
- }
- spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
- flags);
- if (!found_app) {
- pr_err("app_id %d (%s) is not found\n",
- data->client.app_id,
- (char *)data->client.app_name);
- ret = -ENOENT;
- goto exit;
}
}
@@ -2143,7 +2226,7 @@ err_resp:
else
*(uint32_t *)cmd_buf =
QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST;
- if (ptr_svc) {
+ if (ptr_svc && ptr_svc->ihandle) {
ret = msm_ion_do_cache_op(qseecom.ion_clnt,
ptr_svc->ihandle,
ptr_svc->sb_virt, ptr_svc->sb_length,
@@ -2627,6 +2710,7 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
bool unload = false;
bool found_app = false;
bool found_dead_app = false;
+ bool scm_called = false;
if (!data) {
pr_err("Invalid/uninitialized device handle\n");
@@ -2685,11 +2769,12 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(struct qseecom_unload_app_ireq),
&resp, sizeof(resp));
+ scm_called = true;
if (ret) {
pr_err("scm_call to unload app (id = %d) failed\n",
req.app_id);
ret = -EFAULT;
- goto unload_exit;
+ goto scm_exit;
} else {
pr_warn("App id %d now unloaded\n", req.app_id);
}
@@ -2697,7 +2782,7 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
pr_err("app (%d) unload_failed!!\n",
data->client.app_id);
ret = -EFAULT;
- goto unload_exit;
+ goto scm_exit;
}
if (resp.result == QSEOS_RESULT_SUCCESS)
pr_debug("App (%d) is unloaded!!\n",
@@ -2707,11 +2792,35 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data,
if (ret) {
pr_err("process_incomplete_cmd fail err: %d\n",
ret);
- goto unload_exit;
+ goto scm_exit;
}
}
}
+scm_exit:
+ if (scm_called) {
+ /* double check if this app_entry still exists */
+ bool doublecheck = false;
+
+ spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
+ list_for_each_entry(ptr_app,
+ &qseecom.registered_app_list_head, list) {
+ if ((ptr_app->app_id == data->client.app_id) &&
+ (!strcmp((void *)ptr_app->app_name,
+ (void *)data->client.app_name))) {
+ doublecheck = true;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
+ flags1);
+ if (!doublecheck) {
+ pr_warn("app %d(%s) entry is already removed\n",
+ data->client.app_id,
+ (char *)data->client.app_name);
+ found_app = false;
+ }
+ }
unload_exit:
if (found_app) {
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
@@ -3292,7 +3401,6 @@ exit:
pr_err("cache operation failed %d\n", ret2);
return ret2;
}
- __qseecom_processing_pending_lsnr_unregister();
return ret;
}
@@ -4139,6 +4247,7 @@ static int __qseecom_allocate_img_data(struct ion_handle **pihandle,
struct ion_handle *ihandle = NULL;
u8 *img_data = NULL;
int retry = 0;
+ int ion_flag = ION_FLAG_CACHED;
do {
if (retry++) {
@@ -4147,7 +4256,7 @@ static int __qseecom_allocate_img_data(struct ion_handle **pihandle,
mutex_lock(&app_access_lock);
}
ihandle = ion_alloc(qseecom.ion_clnt, fw_size,
- SZ_4K, ION_HEAP(ION_QSECOM_TA_HEAP_ID), 0);
+ SZ_4K, ION_HEAP(ION_QSECOM_TA_HEAP_ID), ion_flag);
} while (IS_ERR_OR_NULL(ihandle) &&
(retry <= QSEECOM_TA_ION_ALLOCATE_MAX_ATTEMP));
@@ -4509,7 +4618,7 @@ int qseecom_start_app(struct qseecom_handle **handle,
uint32_t fw_size, app_arch;
uint32_t app_id = 0;
- __qseecom_processing_pending_lsnr_unregister();
+ __wakeup_unregister_listener_kthread();
if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
pr_err("Not allowed to be called in %d state\n",
@@ -4684,7 +4793,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle)
unsigned long flags = 0;
bool found_handle = false;
- __qseecom_processing_pending_lsnr_unregister();
+ __wakeup_unregister_listener_kthread();
if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
pr_err("Not allowed to be called in %d state\n",
@@ -4734,7 +4843,7 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
struct qseecom_dev_handle *data;
bool perf_enabled = false;
- __qseecom_processing_pending_lsnr_unregister();
+ __wakeup_unregister_listener_kthread();
if (atomic_read(&qseecom.qseecom_state) != QSEECOM_STATE_READY) {
pr_err("Not allowed to be called in %d state\n",
@@ -4859,6 +4968,7 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc)
resp.data = desc->ret[2]; /*listener_id*/
dummy_private_data.client.app_id = desc->ret[1];
+ dummy_private_data.client.from_smcinvoke = true;
dummy_app_entry.app_id = desc->ret[1];
mutex_lock(&app_access_lock);
@@ -5978,6 +6088,9 @@ static int qseecom_create_key(struct qseecom_dev_handle *data,
else
flags |= QSEECOM_ICE_FDE_KEY_SIZE_16_BYTE;
+ if (qseecom.enable_key_wrap_in_ks == true)
+ flags |= ENABLE_KEY_WRAP_IN_KS;
+
generate_key_ireq.flags = flags;
generate_key_ireq.qsee_command_id = QSEOS_GENERATE_KEY;
memset((void *)generate_key_ireq.key_id,
@@ -6378,7 +6491,7 @@ static int qseecom_mdtp_cipher_dip(void __user *argp)
if (ret)
break;
- ret = scm_call2(TZ_MDTP_CIPHER_DIP_ID, &desc);
+ ret = __qseecom_scm_call2_locked(TZ_MDTP_CIPHER_DIP_ID, &desc);
__qseecom_disable_clk(CLK_QSEE);
@@ -7028,7 +7141,7 @@ static void __qseecom_clean_data_sglistinfo(struct qseecom_dev_handle *data)
}
}
-static inline long qseecom_ioctl(struct file *file,
+static long qseecom_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret = 0;
@@ -7049,7 +7162,7 @@ static inline long qseecom_ioctl(struct file *file,
cmd != QSEECOM_IOCTL_SEND_RESP_REQ &&
cmd != QSEECOM_IOCTL_SEND_MODFD_RESP &&
cmd != QSEECOM_IOCTL_SEND_MODFD_RESP_64)
- __qseecom_processing_pending_lsnr_unregister();
+ __wakeup_unregister_listener_kthread();
switch (cmd) {
case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
@@ -8649,11 +8762,14 @@ static int qseecom_probe(struct platform_device *pdev)
spin_lock_init(&qseecom.registered_kclient_list_lock);
init_waitqueue_head(&qseecom.send_resp_wq);
init_waitqueue_head(&qseecom.register_lsnr_pending_wq);
+ init_waitqueue_head(&qseecom.unregister_lsnr_kthread_wq);
qseecom.send_resp_flag = 0;
qseecom.qsee_version = QSEEE_VERSION_00;
+ mutex_lock(&app_access_lock);
rc = qseecom_scm_call(6, 3, &feature, sizeof(feature),
&resp, sizeof(resp));
+ mutex_unlock(&app_access_lock);
pr_info("qseecom.qsee_version = 0x%x\n", resp.result);
if (rc) {
pr_err("Failed to get QSEE version info %d\n", rc);
@@ -8715,6 +8831,14 @@ static int qseecom_probe(struct platform_device *pdev)
qseecom.qsee_reentrancy_support);
}
+ qseecom.enable_key_wrap_in_ks =
+ of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,enable-key-wrap-in-ks");
+ if (qseecom.enable_key_wrap_in_ks) {
+ pr_warn("qseecom.enable_key_wrap_in_ks = %d\n",
+ qseecom.enable_key_wrap_in_ks);
+ }
+
/*
* The qseecom bus scaling flag can not be enabled when
* crypto clock is not handled by HLOS.
@@ -8800,9 +8924,11 @@ static int qseecom_probe(struct platform_device *pdev)
rc = -EIO;
goto exit_deinit_clock;
}
+ mutex_lock(&app_access_lock);
rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
cmd_buf, cmd_len,
&resp, sizeof(resp));
+ mutex_unlock(&app_access_lock);
__qseecom_disable_clk(CLK_QSEE);
if (rc || (resp.result != QSEOS_RESULT_SUCCESS)) {
pr_err("send secapp reg fail %d resp.res %d\n",
@@ -8841,6 +8967,17 @@ static int qseecom_probe(struct platform_device *pdev)
if (!qseecom.qsee_perf_client)
pr_err("Unable to register bus client\n");
+ /*create a kthread to process pending listener unregister task */
+ qseecom.unregister_lsnr_kthread_task = kthread_run(
+ __qseecom_unregister_listener_kthread_func,
+ NULL, "qseecom-unreg-lsnr");
+ if (IS_ERR(qseecom.unregister_lsnr_kthread_task)) {
+ pr_err("failed to create kthread to unregister listener\n");
+ rc = -EINVAL;
+ goto exit_deinit_clock;
+ }
+ atomic_set(&qseecom.unregister_lsnr_kthread_state,
+ LSNR_UNREG_KT_SLEEP);
atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_READY);
return 0;
@@ -8957,6 +9094,8 @@ static int qseecom_remove(struct platform_device *pdev)
ion_client_destroy(qseecom.ion_clnt);
+ kthread_stop(qseecom.unregister_lsnr_kthread_task);
+
cdev_del(&qseecom.cdev);
device_destroy(driver_class, qseecom_device_no);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index eb9ff362184e..f0324ec5e1dc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -3434,8 +3434,14 @@ int mmc_resume_bus(struct mmc_host *host)
spin_unlock_irqrestore(&host->lock, flags);
mmc_bus_get(host);
- if (host->ops->get_cd)
+ if (host->ops->get_cd) {
card_present = host->ops->get_cd(host);
+ if (!card_present) {
+ pr_err("%s: Card removed - card_present:%d\n",
+ mmc_hostname(host), card_present);
+ mmc_card_set_removed(host->card);
+ }
+ }
if (host->bus_ops && !host->bus_dead && host->card && card_present) {
mmc_power_up(host, host->card->ocr);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 71a1cfb82d7e..6dd88ff389a3 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1376,11 +1376,21 @@ static int mmc_sd_resume(struct mmc_host *host)
MMC_TRACE(host, "%s: Enter\n", __func__);
err = _mmc_sd_resume(host);
- pm_runtime_set_active(&host->card->dev);
- pm_runtime_mark_last_busy(&host->card->dev);
- pm_runtime_enable(&host->card->dev);
- MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
+ if (err) {
+ pr_err("%s: sd resume err: %d\n", mmc_hostname(host), err);
+ if (host->ops->get_cd && !host->ops->get_cd(host)) {
+ err = -ENOMEDIUM;
+ mmc_card_set_removed(host->card);
+ }
+ }
+ if (err != -ENOMEDIUM) {
+ pm_runtime_set_active(&host->card->dev);
+ pm_runtime_mark_last_busy(&host->card->dev);
+ pm_runtime_enable(&host->card->dev);
+ }
+
+ MMC_TRACE(host, "%s: Exit err: %d\n", __func__, err);
return err;
}
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 87fc883e8a73..a4d35d94de0c 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -911,11 +911,13 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
cmdq_runtime_pm_put(cq_host);
- if (cq_host->ops->crypto_cfg_end) {
- err = cq_host->ops->crypto_cfg_end(mmc, mrq);
- if (err) {
- pr_err("%s: failed to end ice config: err %d tag %d\n",
- mmc_hostname(mmc), err, tag);
+ if (!(mrq->cmdq_req->cmdq_req_flags & DCMD)) {
+ if (cq_host->ops->crypto_cfg_end) {
+ err = cq_host->ops->crypto_cfg_end(mmc, mrq);
+ if (err) {
+ pr_err("%s: failed to end ice config: err %d tag %d\n",
+ mmc_hostname(mmc), err, tag);
+ }
}
}
if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) &&
diff --git a/drivers/net/ppp/pppolac.c b/drivers/net/ppp/pppolac.c
index 3a45cf805288..8ed809153120 100644
--- a/drivers/net/ppp/pppolac.c
+++ b/drivers/net/ppp/pppolac.c
@@ -83,7 +83,7 @@ static int pppolac_recv_core(struct sock *sk_udp, struct sk_buff *skb)
/* Put it back if it is a control packet. */
if (skb->data[sizeof(struct udphdr)] & L2TP_CONTROL_BIT)
- return opt->backlog_rcv(sk_udp, skb);
+ return 2;
/* Skip UDP header. */
skb_pull(skb, sizeof(struct udphdr));
@@ -190,9 +190,10 @@ drop:
static int pppolac_recv(struct sock *sk_udp, struct sk_buff *skb)
{
+ int retval;
sock_hold(sk_udp);
- sk_receive_skb(sk_udp, skb, 0);
- return 0;
+ retval = sk_receive_skb(sk_udp, skb, 0);
+ return (retval >> 1);
}
static struct sk_buff_head delivery_queue;
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 37df1bf277ca..09e8d38f57ae 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -752,11 +752,7 @@ static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd)
if (!event)
continue;
- /*
- * Check if an attempt was made to free this event during
- * the CPU went offline.
- */
- if (event->state == PERF_EVENT_STATE_ZOMBIE)
+ if (event->state != PERF_EVENT_STATE_ACTIVE)
continue;
switch (cmd) {
@@ -882,10 +878,8 @@ static int arm_perf_starting_cpu(unsigned int cpu, struct hlist_node *node)
if (!pmu || !cpumask_test_cpu(cpu, &pmu->supported_cpus))
return 0;
- data.cmd = CPU_PM_EXIT;
- cpu_pm_pmu_common(&data);
- if (data.ret == NOTIFY_DONE)
- return 0;
+ if (pmu->reset)
+ pmu->reset(pmu);
if (data.armpmu->pmu_state != ARM_PMU_STATE_OFF &&
data.armpmu->plat_device) {
@@ -911,8 +905,6 @@ static int arm_perf_stopping_cpu(unsigned int cpu, struct hlist_node *node)
if (!pmu || !cpumask_test_cpu(cpu, &pmu->supported_cpus))
return 0;
- data.cmd = CPU_PM_ENTER;
- cpu_pm_pmu_common(&data);
/* Disarm the PMU IRQ before disappearing. */
if (data.armpmu->pmu_state == ARM_PMU_STATE_RUNNING &&
data.armpmu->plat_device) {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index f1f6b900d474..b3c38b9d7f86 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -737,8 +737,14 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
IPADBG("msg=%pK\n", msg);
locked = 0;
mutex_unlock(&ipa_ctx->msg_lock);
+ if (count < sizeof(struct ipa_msg_meta)) {
+ kfree(msg);
+ msg = NULL;
+ ret = -EFAULT;
+ break;
+ }
if (copy_to_user(buf, &msg->meta,
- sizeof(struct ipa_msg_meta))) {
+ sizeof(struct ipa_msg_meta))) {
kfree(msg);
msg = NULL;
ret = -EFAULT;
@@ -747,8 +753,15 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
buf += sizeof(struct ipa_msg_meta);
count -= sizeof(struct ipa_msg_meta);
if (msg->buff) {
- if (copy_to_user(buf, msg->buff,
- msg->meta.msg_len)) {
+ if (count >= msg->meta.msg_len) {
+ if (copy_to_user(buf, msg->buff,
+ msg->meta.msg_len)) {
+ kfree(msg);
+ msg = NULL;
+ ret = -EFAULT;
+ break;
+ }
+ } else {
kfree(msg);
msg = NULL;
ret = -EFAULT;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index c348e26b6b69..d41cdb7c2f90 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -745,6 +745,12 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
if (msg) {
locked = 0;
mutex_unlock(&ipa3_ctx->msg_lock);
+ if (count < sizeof(struct ipa_msg_meta)) {
+ kfree(msg);
+ msg = NULL;
+ ret = -EFAULT;
+ break;
+ }
if (copy_to_user(buf, &msg->meta,
sizeof(struct ipa_msg_meta))) {
ret = -EFAULT;
@@ -755,8 +761,15 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
buf += sizeof(struct ipa_msg_meta);
count -= sizeof(struct ipa_msg_meta);
if (msg->buff) {
- if (copy_to_user(buf, msg->buff,
- msg->meta.msg_len)) {
+ if (count >= msg->meta.msg_len) {
+ if (copy_to_user(buf, msg->buff,
+ msg->meta.msg_len)) {
+ ret = -EFAULT;
+ kfree(msg);
+ msg = NULL;
+ break;
+ }
+ } else {
ret = -EFAULT;
kfree(msg);
msg = NULL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 92fa1ecc4864..1271175c031c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -4414,7 +4414,7 @@ int ipa3_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res)
return -EINVAL;
}
- if (iface < 0 || iface > IPA_VLAN_IF_MAX) {
+ if (iface < 0 || iface >= IPA_VLAN_IF_MAX) {
IPAERR("invalid iface %d\n", iface);
return -EINVAL;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index c7a7f6becd88..7f16f4bea79b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -3910,6 +3910,15 @@ int rmnet_ipa3_send_lan_client_msg(
IPAWANERR("Can't allocate memory for tether_info\n");
return -ENOMEM;
}
+
+ if (data->client_event != IPA_PER_CLIENT_STATS_CONNECT_EVENT &&
+ data->client_event != IPA_PER_CLIENT_STATS_DISCONNECT_EVENT) {
+ IPAWANERR("Wrong event given. Event:- %d\n",
+ data->client_event);
+ kfree(lan_client);
+ return -EINVAL;
+ }
+ data->lan_client.lanIface[IPA_RESOURCE_NAME_MAX-1] = '\0';
memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
memcpy(lan_client, &data->lan_client,
sizeof(struct ipa_lan_client_msg));
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 05a8c66d57aa..465e0793951c 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -675,7 +675,8 @@ int sps_get_bam_debug_info(unsigned long dev, u32 option, u32 para,
/* Search for the target BAM device */
bam = sps_h2bam(dev);
if (bam == NULL) {
- pr_err("sps:Can't find any BAM with handle 0x%lx.", dev);
+ pr_err("sps:Can't find any BAM with handle 0x%pK.",
+ (void *)dev);
mutex_unlock(&sps->lock);
return SPS_ERROR;
}
@@ -1226,7 +1227,7 @@ struct sps_bam *sps_h2bam(unsigned long h)
{
struct sps_bam *bam;
- SPS_DBG1(sps, "sps:%s: BAM handle:0x%lx.", __func__, h);
+ SPS_DBG1(sps, "sps:%s: BAM handle:0x%pK.", __func__, (void *)h);
if (h == SPS_DEV_HANDLE_MEM || h == SPS_DEV_HANDLE_INVALID)
return NULL;
@@ -1236,7 +1237,7 @@ struct sps_bam *sps_h2bam(unsigned long h)
return bam;
}
- SPS_ERR(sps, "sps:Can't find BAM device for handle 0x%lx.", h);
+ SPS_ERR(sps, "sps:Can't find BAM device for handle 0x%pK.", (void *)h);
return NULL;
}
@@ -1341,16 +1342,17 @@ int sps_connect(struct sps_pipe *h, struct sps_connect *connect)
bam = sps_h2bam(dev);
if (bam == NULL) {
- SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%lx", dev);
+ SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%pK",
+ (void *)dev);
result = SPS_ERROR;
goto exit_err;
}
mutex_lock(&bam->lock);
- SPS_DBG2(bam, "sps:sps_connect: bam %pa src 0x%lx dest 0x%lx mode %s",
+ SPS_DBG2(bam, "sps:sps_connect: bam %pa src 0x%pK dest 0x%pK mode %s",
BAM_ID(bam),
- connect->source,
- connect->destination,
+ (void *)connect->source,
+ (void *)connect->destination,
connect->mode == SPS_MODE_SRC ? "SRC" : "DEST");
/* Allocate resources for the specified connection */
@@ -1414,10 +1416,10 @@ int sps_disconnect(struct sps_pipe *h)
}
SPS_DBG2(bam,
- "sps:sps_disconnect: bam %pa src 0x%lx dest 0x%lx mode %s",
+ "sps:sps_disconnect: bam %pa src 0x%pK dest 0x%pK mode %s",
BAM_ID(bam),
- pipe->connect.source,
- pipe->connect.destination,
+ (void *)pipe->connect.source,
+ (void *)pipe->connect.destination,
pipe->connect.mode == SPS_MODE_SRC ? "SRC" : "DEST");
result = SPS_ERROR;
@@ -1813,7 +1815,8 @@ int sps_device_reset(unsigned long dev)
/* Search for the target BAM device */
bam = sps_h2bam(dev);
if (bam == NULL) {
- SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%lx", dev);
+ SPS_ERR(sps, "sps:Invalid BAM device handle: 0x%pK",
+ (void *)dev);
result = SPS_ERROR;
goto exit_err;
}
@@ -1824,7 +1827,8 @@ int sps_device_reset(unsigned long dev)
result = sps_bam_reset(bam);
mutex_unlock(&bam->lock);
if (result) {
- SPS_ERR(sps, "sps:Fail to reset BAM device: 0x%lx", dev);
+ SPS_ERR(sps, "sps:Fail to reset BAM device: 0x%pK",
+ (void *)dev);
goto exit_err;
}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 7d6a7eb039f6..475e9db39bd8 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -895,8 +895,8 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
else
iova = bam_pipe->connect.source_iova;
SPS_DBG2(dev,
- "sps:BAM %pa pipe %d uses IOVA 0x%lx.\n",
- BAM_ID(dev), pipe_index, iova);
+ "sps:BAM %pa pipe %d uses IOVA 0x%pK.\n",
+ BAM_ID(dev), pipe_index, (void *)iova);
hw_params.peer_phys_addr = (u32)iova;
} else {
hw_params.peer_phys_addr = peer_bam->props.phys_addr;
@@ -918,9 +918,9 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
hw_params.data_base =
(phys_addr_t)bam_pipe->connect.data.iova;
SPS_DBG2(dev,
- "sps:BAM %pa pipe %d uses IOVA 0x%lx for data FIFO.\n",
+ "sps:BAM %pa pipe %d uses IOVA 0x%pK for data FIFO.\n",
BAM_ID(dev), pipe_index,
- bam_pipe->connect.data.iova);
+ (void *)(bam_pipe->connect.data.iova));
} else {
hw_params.data_base = map->data.phys_base;
}
@@ -971,9 +971,9 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
hw_params.desc_base =
(phys_addr_t)bam_pipe->connect.desc.iova;
SPS_DBG2(dev,
- "sps:BAM %pa pipe %d uses IOVA 0x%lx for desc FIFO.\n",
+ "sps:BAM %pa pipe %d uses IOVA 0x%pK for desc FIFO.\n",
BAM_ID(dev), pipe_index,
- bam_pipe->connect.desc.iova);
+ (void *)(bam_pipe->connect.desc.iova));
} else {
hw_params.desc_base = map->desc.phys_base;
}
@@ -1424,8 +1424,9 @@ int sps_bam_pipe_transfer_one(struct sps_bam *dev,
u32 next_write;
static int show_recom;
- SPS_DBG(dev, "sps:BAM %pa pipe %d addr 0x%x size 0x%x flags 0x%x\n",
- BAM_ID(dev), pipe_index, addr, size, flags);
+ SPS_DBG(dev, "sps:BAM %pa pipe %d addr 0x%pK size 0x%x flags 0x%x\n",
+ BAM_ID(dev), pipe_index,
+ (void *)(long)addr, size, flags);
/* Is this a BAM-to-BAM or satellite connection? */
if ((pipe->state & (BAM_STATE_BAM2BAM | BAM_STATE_REMOTE))) {
@@ -1951,8 +1952,8 @@ static void pipe_handler_eot(struct sps_bam *dev, struct sps_pipe *pipe)
user = &pipe->sys.user_ptrs[offset / sizeof(struct sps_iovec)];
for (;;) {
SPS_DBG(dev,
- "sps:%s; pipe index:%d; iovec addr:0x%x; size:0x%x; flags:0x%x; enabled:0x%x; *user is %s NULL.\n",
- __func__, pipe->pipe_index, cache->addr,
+ "sps:%s; pipe index:%d; iovec addr:0x%pK; size:0x%x; flags:0x%x; enabled:0x%x; *user is %s NULL.\n",
+ __func__, pipe->pipe_index, (void *)(long)cache->addr,
cache->size, cache->flags, enabled,
(*user == NULL) ? "" : "not");
@@ -2240,8 +2241,8 @@ int sps_bam_pipe_get_iovec(struct sps_bam *dev, u32 pipe_index,
pipe->sys.acked_offset = 0;
SPS_DBG(dev,
- "sps:%s; pipe index:%d; iovec addr:0x%x; size:0x%x; flags:0x%x; acked_offset:0x%x.\n",
- __func__, pipe->pipe_index, desc->addr,
+ "sps:%s; pipe index:%d; iovec addr:0x%pK; size:0x%x; flags:0x%x; acked_offset:0x%x.\n",
+ __func__, pipe->pipe_index, (void *)(long)desc->addr,
desc->size, desc->flags, pipe->sys.acked_offset);
return 0;
diff --git a/drivers/platform/msm/sps/sps_dma.c b/drivers/platform/msm/sps/sps_dma.c
index abdcabc8cddd..0cc428399ecf 100644
--- a/drivers/platform/msm/sps/sps_dma.c
+++ b/drivers/platform/msm/sps/sps_dma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, 2015, 2017, The Linux Foundation. All rights
+/* Copyright (c) 2011-2013, 2015, 2017, 2019, The Linux Foundation. All rights
* reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -381,7 +381,7 @@ int sps_dma_device_de_init(unsigned long h)
dev = sps_dma_find_device(h);
if (dev == NULL) {
- SPS_ERR(sps, "sps:BAM-DMA: not registered: %lx", h);
+ SPS_ERR(sps, "sps:BAM-DMA: not registered: %pK", (void *)h);
result = SPS_ERROR;
goto exit_err;
}
@@ -547,8 +547,8 @@ int sps_alloc_dma_chan(const struct sps_alloc_dma_chan *alloc,
dev = sps_dma_find_device(alloc->dev);
if (dev == NULL) {
- SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %lx",
- alloc->dev);
+ SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %pK",
+ (void *)alloc->dev);
goto exit_err;
}
@@ -621,7 +621,8 @@ int sps_free_dma_chan(struct sps_dma_chan *chan)
dev = sps_dma_find_device(chan->dev);
if (dev == NULL) {
- SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %lx", chan->dev);
+ SPS_ERR(sps, "sps:BAM-DMA: invalid BAM handle: %pK",
+ (void *)chan->dev);
result = SPS_ERROR;
goto exit_err;
}
diff --git a/drivers/platform/msm/sps/sps_mem.c b/drivers/platform/msm/sps/sps_mem.c
index 105135a0e022..f5e026ba62ed 100644
--- a/drivers/platform/msm/sps/sps_mem.c
+++ b/drivers/platform/msm/sps/sps_mem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, 2015, 2017, The Linux Foundation.
+/* Copyright (c) 2011-2013, 2015, 2017, 2019, The Linux Foundation.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -75,8 +75,8 @@ phys_addr_t sps_mem_alloc_io(u32 bytes)
return SPS_ADDR_INVALID;
}
- SPS_DBG3(sps, "sps:sps_mem_alloc_io.phys=%pa.virt=0x%lx.size=0x%x.",
- &phys_addr, virt_addr, bytes);
+ SPS_DBG3(sps, "sps:sps_mem_alloc_io.phys=%pa.virt=0x%pK.size=0x%x.",
+ &phys_addr, (void *)virt_addr, bytes);
return phys_addr;
}
@@ -92,8 +92,8 @@ void sps_mem_free_io(phys_addr_t phys_addr, u32 bytes)
iomem_offset = phys_addr - iomem_phys;
virt_addr = (uintptr_t) iomem_virt + iomem_offset;
- SPS_DBG3(sps, "sps:sps_mem_free_io.phys=%pa.virt=0x%lx.size=0x%x.",
- &phys_addr, virt_addr, bytes);
+ SPS_DBG3(sps, "sps:sps_mem_free_io.phys=%pa.virt=0x%pK.size=0x%x.",
+ &phys_addr, (void *)virt_addr, bytes);
gen_pool_free(pool, virt_addr, bytes);
total_free += bytes;
diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c
index 276b847979e1..ef6029a9e518 100644
--- a/drivers/platform/msm/sps/sps_rm.c
+++ b/drivers/platform/msm/sps/sps_rm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2015, 2017, 2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -380,8 +380,8 @@ static struct sps_connection *sps_rm_create(struct sps_pipe *pipe)
map->src.bam = sps_h2bam(map->src.dev);
if (map->src.bam == NULL) {
if (map->src.dev != SPS_DEV_HANDLE_MEM) {
- SPS_ERR(sps, "sps:Invalid BAM handle: %pa",
- &map->src.dev);
+ SPS_ERR(sps, "sps:Invalid BAM handle: %pK",
+ (void *)(&map->src.dev));
goto exit_err;
}
map->src.pipe_index = SPS_BAM_PIPE_INVALID;
@@ -389,8 +389,8 @@ static struct sps_connection *sps_rm_create(struct sps_pipe *pipe)
map->dest.bam = sps_h2bam(map->dest.dev);
if (map->dest.bam == NULL) {
if (map->dest.dev != SPS_DEV_HANDLE_MEM) {
- SPS_ERR(sps, "sps:Invalid BAM handle: %pa",
- &map->dest.dev);
+ SPS_ERR(sps, "sps:Invalid BAM handle: %pK",
+ (void *)(&map->dest.dev));
goto exit_err;
}
map->dest.pipe_index = SPS_BAM_PIPE_INVALID;
@@ -399,8 +399,8 @@ static struct sps_connection *sps_rm_create(struct sps_pipe *pipe)
/* Check the BAM device for the pipe */
if ((dir == SPS_MODE_SRC && map->src.bam == NULL) ||
(dir != SPS_MODE_SRC && map->dest.bam == NULL)) {
- SPS_ERR(sps, "sps:Invalid BAM endpt: dir %d src %pa dest %pa",
- dir, &map->src.dev, &map->dest.dev);
+ SPS_ERR(sps, "sps:Invalid BAM endpt: dir %d src %pK dest %pK",
+ dir, (void *)(&map->src.dev), (void *)(&map->dest.dev));
goto exit_err;
}
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index bc1855ea5d48..f56b9837f259 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1115,10 +1115,14 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CYCLE_COUNT:
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_TEMP:
rc = smblib_get_prop_from_bms(chg, psp, val);
break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ rc = smblib_get_prop_from_bms(chg, psp, val);
+ if (!rc)
+ val->intval *= (-1);
+ break;
case POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE:
val->intval = chg->fcc_stepper_enable;
break;
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 7994741ccb1c..a4410734f6c5 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1367,6 +1367,8 @@ static int smb5_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_NOW:
rc = smblib_get_prop_from_bms(chg,
POWER_SUPPLY_PROP_CURRENT_NOW, val);
+ if (!rc)
+ val->intval *= (-1);
break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
val->intval = get_client_vote(chg->fcc_votable,
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index 896509dac561..523fe47a4d54 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -308,6 +308,7 @@ enum pmic_subtype {
PMI8950 = 17,
PMI8996 = 19,
PMI8937 = 55,
+ PMI8940 = 64,
};
enum smbchg_wa {
@@ -1133,6 +1134,28 @@ static int get_prop_batt_voltage_max_design(struct smbchg_chip *chip)
return uv;
}
+static int get_prop_batt_charge_counter(struct smbchg_chip *chip)
+{
+ int bcc = 0, rc;
+
+ rc = get_property_from_fg(chip,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER, &bcc);
+ if (rc)
+ pr_smb(PR_STATUS, "Couldn't get charge_counter rc = %d\n", rc);
+ return bcc;
+}
+
+static int get_prop_batt_cycle_count(struct smbchg_chip *chip)
+{
+ int bcc = 0, rc;
+
+ rc = get_property_from_fg(chip,
+ POWER_SUPPLY_PROP_CYCLE_COUNT, &bcc);
+ if (rc)
+ pr_smb(PR_STATUS, "Couldn't get cycle_count rc = %d\n", rc);
+ return bcc;
+}
+
static int get_prop_batt_health(struct smbchg_chip *chip)
{
if (chip->batt_hot)
@@ -5899,6 +5922,8 @@ static enum power_supply_property smbchg_battery_properties[] = {
POWER_SUPPLY_PROP_RESTRICTED_CHARGING,
POWER_SUPPLY_PROP_ALLOW_HVDCP3,
POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
};
static int smbchg_battery_set_property(struct power_supply *psy,
@@ -6118,6 +6143,12 @@ static int smbchg_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED:
val->intval = chip->max_pulse_allowed;
break;
+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ val->intval = get_prop_batt_charge_counter(chip);
+ break;
+ case POWER_SUPPLY_PROP_CYCLE_COUNT:
+ val->intval = get_prop_batt_cycle_count(chip);
+ break;
default:
return -EINVAL;
}
@@ -8096,6 +8127,8 @@ static int smbchg_check_chg_version(struct smbchg_chip *chip)
case PMI8950:
chip->wa_flags |= SMBCHG_RESTART_WA;
case PMI8937:
+ /* fall through */
+ case PMI8940:
chip->wa_flags |= SMBCHG_BATT_OV_WA;
if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */ {
chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA;
@@ -8110,7 +8143,9 @@ static int smbchg_check_chg_version(struct smbchg_chip *chip)
ARRAY_SIZE(aicl_rerun_period_schg_lite);
chip->schg_version = QPNP_SCHG_LITE;
- if (pmic_rev_id->pmic_subtype == PMI8937)
+ /* PMI8937/PMI8940 doesn't support HVDCP */
+ if ((pmic_rev_id->pmic_subtype == PMI8937)
+ || (pmic_rev_id->pmic_subtype == PMI8940))
chip->hvdcp_not_supported = true;
break;
case PMI8996:
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index e23f13e2236f..9b0ec47df85a 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -2888,6 +2888,7 @@ static int __smblib_set_prop_pd_active(struct smb_charger *chg, bool pd_active)
chg->pd_active = pd_active;
if (chg->pd_active) {
+ chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
vote(chg->apsd_disable_votable, PD_VOTER, true, 0);
vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
diff --git a/drivers/power/supply/qcom/smb1360-charger-fg.c b/drivers/power/supply/qcom/smb1360-charger-fg.c
index 4e98ec752fa7..41dcf1dca25d 100644
--- a/drivers/power/supply/qcom/smb1360-charger-fg.c
+++ b/drivers/power/supply/qcom/smb1360-charger-fg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,7 @@
#include <linux/qpnp/qpnp-adc.h>
#include <linux/completion.h>
#include <linux/pm_wakeup.h>
+#include <linux/of_irq.h>
#define _SMB1360_MASK(BITS, POS) \
((unsigned char)(((1 << (BITS)) - 1) << (POS)))
@@ -405,6 +406,7 @@ struct smb1360_chip {
bool otg_fet_present;
bool fet_gain_enabled;
int otg_fet_enable_gpio;
+ int usb_id_gpio;
/* status tracking */
int voltage_now;
@@ -466,6 +468,7 @@ struct smb1360_chip {
int cold_hysteresis;
int hot_hysteresis;
struct extcon_dev *extcon;
+ int usb_id_irq;
};
static int chg_time[] = {
@@ -2885,6 +2888,28 @@ static irqreturn_t smb1360_stat_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static irqreturn_t smb1360_usb_id_irq_handler(int irq, void *dev_id)
+{
+ struct smb1360_chip *chip = dev_id;
+ int rc = 0;
+ bool id_state;
+
+ id_state = gpio_get_value(chip->usb_id_gpio);
+
+ rc = smb1360_masked_write(chip, CMD_CHG_REG, CMD_OTG_EN_BIT,
+ !id_state ? CMD_OTG_EN_BIT : 0);
+ if (rc) {
+ pr_err("Couldn't enable OTG mode rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+ extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST,
+ !id_state ? true : false);
+
+ pr_debug("usb_id_irq triggered, id_state = %d\n", id_state);
+
+ return IRQ_HANDLED;
+}
+
static int show_irq_count(struct seq_file *m, void *data)
{
int i, j, total = 0;
@@ -3421,6 +3446,10 @@ static int smb1360_regulator_init(struct smb1360_chip *chip)
int rc = 0;
struct regulator_config cfg = {};
+ /* OTG is enabled by SMB1360 if usb-id config is defined */
+ if (chip->usb_id_gpio > 0 && chip->usb_id_irq > 0)
+ return 0;
+
chip->otg_vreg.rdesc.owner = THIS_MODULE;
chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops;
@@ -3557,6 +3586,7 @@ static int determine_initial_status(struct smb1360_chip *chip)
{
int rc;
u8 reg = 0;
+ bool id_state;
/*
* It is okay to read the IRQ status as the irq's are
@@ -3621,6 +3651,25 @@ static int determine_initial_status(struct smb1360_chip *chip)
else
extcon_set_cable_state_(chip->extcon, EXTCON_USB, true);
+ pr_debug("usb %s at boot\n", chip->usb_present ? "present" : "absent");
+
+ /*check otg presence and notify*/
+ if (chip->usb_id_gpio != -EINVAL) {
+ id_state = gpio_get_value(chip->usb_id_gpio);
+ /* usb-id is low, enable OTG */
+ if (!id_state) {
+ rc = smb1360_masked_write(chip, CMD_CHG_REG,
+ CMD_OTG_EN_BIT, CMD_OTG_EN_BIT);
+ if (rc) {
+ pr_err("Couldn't enable OTG mode rc=%d\n", rc);
+ return rc;
+ }
+ extcon_set_state_sync(chip->extcon, EXTCON_USB_HOST,
+ true);
+ pr_debug("OTG enabled at boot\n");
+ }
+ }
+
power_supply_changed(chip->usb_psy);
return 0;
}
@@ -4752,6 +4801,11 @@ static int smb_parse_dt(struct smb1360_chip *chip)
return rc;
}
}
+ chip->usb_id_gpio = -EINVAL;
+ if (of_find_property(node, "qcom,usb-id-gpio", NULL)) {
+ chip->usb_id_gpio = of_get_named_gpio(node,
+ "qcom,usb-id-gpio", 0);
+ }
chip->pulsed_irq = of_property_read_bool(node, "qcom,stat-pulsed-irq");
@@ -5073,6 +5127,28 @@ static int smb1360_probe(struct i2c_client *client,
enable_irq_wake(client->irq);
}
+ chip->usb_id_irq = of_irq_get_byname(chip->dev->of_node,
+ "smb1360_usb_id_irq");
+ if (chip->usb_id_irq > 0) {
+ if (chip->usb_id_gpio == -EINVAL) {
+ pr_err("usb-id gpio not defined\n");
+ } else {
+ rc = devm_request_threaded_irq(&client->dev,
+ chip->usb_id_irq, NULL,
+ smb1360_usb_id_irq_handler,
+ IRQF_ONESHOT
+ | IRQF_TRIGGER_FALLING
+ | IRQF_TRIGGER_RISING,
+ "smb1360_usb_id_irq", chip);
+ if (rc < 0) {
+ dev_err(&client->dev,
+ "usb-id request_irq for irq=%d failed rc = %d\n",
+ chip->usb_id_irq, rc);
+ goto unregister_batt_psy;
+ }
+ enable_irq_wake(chip->usb_id_irq);
+ }
+ }
chip->debug_root = debugfs_create_dir("smb1360", NULL);
if (!chip->debug_root)
dev_err(chip->dev, "Couldn't create debug dir\n");
@@ -5201,7 +5277,8 @@ static int smb1360_probe(struct i2c_client *client,
unregister_batt_psy:
power_supply_unregister(chip->batt_psy);
fail_hw_init:
- regulator_unregister(chip->otg_vreg.rdev);
+ if (chip->otg_vreg.rdev)
+ regulator_unregister(chip->otg_vreg.rdev);
destroy_mutex:
power_supply_unregister(chip->usb_psy);
wakeup_source_trash(&chip->smb1360_ws.source);
@@ -5218,8 +5295,9 @@ destroy_mutex:
static int smb1360_remove(struct i2c_client *client)
{
struct smb1360_chip *chip = i2c_get_clientdata(client);
+ if (chip->otg_vreg.rdev)
+ regulator_unregister(chip->otg_vreg.rdev);
- regulator_unregister(chip->otg_vreg.rdev);
power_supply_unregister(chip->usb_psy);
power_supply_unregister(chip->batt_psy);
wakeup_source_trash(&chip->smb1360_ws.source);
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 17b808ca843d..1b7af04730ba 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -526,9 +526,19 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
if (state->period != pwm->state.period ||
state->duty_cycle != pwm->state.duty_cycle) {
- err = pwm->chip->ops->config(pwm->chip, pwm,
- state->duty_cycle,
- state->period);
+ if (pwm->chip->ops->config_extend) {
+ err = pwm->chip->ops->config_extend(pwm->chip,
+ pwm, state->duty_cycle,
+ state->period);
+ } else {
+ if (state->period > UINT_MAX)
+ pr_warn("period %llu duty_cycle %llu will be truncated\n",
+ state->period,
+ state->duty_cycle);
+ err = pwm->chip->ops->config(pwm->chip, pwm,
+ state->duty_cycle,
+ state->period);
+ }
if (err)
return err;
@@ -1017,8 +1027,8 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
if (state.enabled)
seq_puts(s, " enabled");
- seq_printf(s, " period: %u ns", state.period);
- seq_printf(s, " duty: %u ns", state.duty_cycle);
+ seq_printf(s, " period: %llu ns", state.period);
+ seq_printf(s, " duty: %llu ns", state.duty_cycle);
seq_printf(s, " polarity: %s",
state.polarity ? "inverse" : "normal");
diff --git a/drivers/pwm/pwm-qti-lpg.c b/drivers/pwm/pwm-qti-lpg.c
index d24bef10c1d7..f5c5e399af7f 100644
--- a/drivers/pwm/pwm-qti-lpg.c
+++ b/drivers/pwm/pwm-qti-lpg.c
@@ -164,7 +164,7 @@ struct lpg_pwm_config {
u32 prediv;
u32 clk_exp;
u16 pwm_value;
- u32 best_period_ns;
+ u64 best_period_ns;
};
struct qpnp_lpg_lut {
@@ -185,8 +185,8 @@ struct qpnp_lpg_channel {
u8 src_sel;
u8 subtype;
bool lut_written;
- int current_period_ns;
- int current_duty_ns;
+ u64 current_period_ns;
+ u64 current_duty_ns;
};
struct qpnp_lpg_chip {
@@ -723,17 +723,17 @@ static int qpnp_lpg_set_ramp_config(struct qpnp_lpg_channel *lpg)
return rc;
}
-static void __qpnp_lpg_calc_pwm_period(int period_ns,
+static void __qpnp_lpg_calc_pwm_period(u64 period_ns,
struct lpg_pwm_config *pwm_config)
{
struct qpnp_lpg_channel *lpg = container_of(pwm_config,
struct qpnp_lpg_channel, pwm_config);
struct lpg_pwm_config configs[NUM_PWM_SIZE];
int i, j, m, n;
- int tmp1, tmp2;
- int clk_period_ns = 0, pwm_clk_period_ns;
- int clk_delta_ns = INT_MAX, min_clk_delta_ns = INT_MAX;
- int pwm_period_delta = INT_MAX, min_pwm_period_delta = INT_MAX;
+ u64 tmp1, tmp2;
+ u64 clk_period_ns = 0, pwm_clk_period_ns;
+ u64 clk_delta_ns = U64_MAX, min_clk_delta_ns = U64_MAX;
+ u64 pwm_period_delta = U64_MAX, min_pwm_period_delta = U64_MAX;
int pwm_size_step;
/*
@@ -755,7 +755,8 @@ static void __qpnp_lpg_calc_pwm_period(int period_ns,
for (m = 0; m < ARRAY_SIZE(pwm_exponent); m++) {
tmp1 = 1 << pwm_exponent[m];
tmp1 *= clk_prediv[j];
- tmp2 = NSEC_PER_SEC / clk_freq_hz[i];
+ tmp2 = NSEC_PER_SEC;
+ do_div(tmp2, clk_freq_hz[i]);
clk_period_ns = tmp1 * tmp2;
@@ -785,10 +786,7 @@ static void __qpnp_lpg_calc_pwm_period(int period_ns,
configs[n].best_period_ns *= 1 << pwm_size[n];
/* Find the closest setting for PWM period */
- if (min_clk_delta_ns < INT_MAX >> pwm_size[n])
- pwm_period_delta = min_clk_delta_ns << pwm_size[n];
- else
- pwm_period_delta = INT_MAX;
+ pwm_period_delta = min_clk_delta_ns << pwm_size[n];
if (pwm_period_delta < min_pwm_period_delta) {
min_pwm_period_delta = pwm_period_delta;
memcpy(pwm_config, &configs[n],
@@ -806,21 +804,20 @@ static void __qpnp_lpg_calc_pwm_period(int period_ns,
pwm_config->clk_exp -= pwm_size_step;
}
}
- pr_debug("PWM setting for period_ns %d: pwm_clk = %dHZ, prediv = %d, exponent = %d, pwm_size = %d\n",
+ pr_debug("PWM setting for period_ns %llu: pwm_clk = %dHZ, prediv = %d, exponent = %d, pwm_size = %d\n",
period_ns, pwm_config->pwm_clk, pwm_config->prediv,
pwm_config->clk_exp, pwm_config->pwm_size);
- pr_debug("Actual period: %dns\n", pwm_config->best_period_ns);
+ pr_debug("Actual period: %lluns\n", pwm_config->best_period_ns);
}
-static void __qpnp_lpg_calc_pwm_duty(int period_ns, int duty_ns,
+static void __qpnp_lpg_calc_pwm_duty(u64 period_ns, u64 duty_ns,
struct lpg_pwm_config *pwm_config)
{
u16 pwm_value, max_pwm_value;
+ u64 tmp;
- if ((1 << pwm_config->pwm_size) > (INT_MAX / duty_ns))
- pwm_value = duty_ns / (period_ns >> pwm_config->pwm_size);
- else
- pwm_value = (duty_ns << pwm_config->pwm_size) / period_ns;
+ tmp = (u64)duty_ns << pwm_config->pwm_size;
+ pwm_value = (u16)div64_u64(tmp, period_ns);
max_pwm_value = (1 << pwm_config->pwm_size) - 1;
if (pwm_value > max_pwm_value)
@@ -828,20 +825,13 @@ static void __qpnp_lpg_calc_pwm_duty(int period_ns, int duty_ns,
pwm_config->pwm_value = pwm_value;
}
-static int qpnp_lpg_pwm_config(struct pwm_chip *pwm_chip,
- struct pwm_device *pwm, int duty_ns, int period_ns)
+static int qpnp_lpg_config(struct qpnp_lpg_channel *lpg,
+ u64 duty_ns, u64 period_ns)
{
- struct qpnp_lpg_channel *lpg;
- int rc = 0;
-
- lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
- if (lpg == NULL) {
- dev_err(pwm_chip->dev, "lpg not found\n");
- return -ENODEV;
- }
+ int rc;
if (duty_ns > period_ns) {
- dev_err(pwm_chip->dev, "Duty %dns is larger than period %dns\n",
+ dev_err(lpg->chip->dev, "Duty %lluns is larger than period %lluns\n",
duty_ns, period_ns);
return -EINVAL;
}
@@ -855,7 +845,7 @@ static int qpnp_lpg_pwm_config(struct pwm_chip *pwm_chip,
lpg->ramp_config.pattern,
lpg->ramp_config.pattern_length);
if (rc < 0) {
- dev_err(pwm_chip->dev, "set LUT pattern failed for LPG%d, rc=%d\n",
+ dev_err(lpg->chip->dev, "set LUT pattern failed for LPG%d, rc=%d\n",
lpg->lpg_idx, rc);
return rc;
}
@@ -869,7 +859,7 @@ static int qpnp_lpg_pwm_config(struct pwm_chip *pwm_chip,
rc = qpnp_lpg_set_pwm_config(lpg);
if (rc < 0) {
- dev_err(pwm_chip->dev, "Config PWM failed for channel %d, rc=%d\n",
+ dev_err(lpg->chip->dev, "Config PWM failed for channel %d, rc=%d\n",
lpg->lpg_idx, rc);
return rc;
}
@@ -880,6 +870,34 @@ static int qpnp_lpg_pwm_config(struct pwm_chip *pwm_chip,
return rc;
}
+static int qpnp_lpg_pwm_config(struct pwm_chip *pwm_chip,
+ struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+ struct qpnp_lpg_channel *lpg;
+
+ lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
+ if (lpg == NULL) {
+ dev_err(pwm_chip->dev, "lpg not found\n");
+ return -ENODEV;
+ }
+
+ return qpnp_lpg_config(lpg, (u64)duty_ns, (u64)period_ns);
+}
+
+static int qpnp_lpg_pwm_config_extend(struct pwm_chip *pwm_chip,
+ struct pwm_device *pwm, u64 duty_ns, u64 period_ns)
+{
+ struct qpnp_lpg_channel *lpg;
+
+ lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
+ if (lpg == NULL) {
+ dev_err(pwm_chip->dev, "lpg not found\n");
+ return -ENODEV;
+ }
+
+ return qpnp_lpg_config(lpg, duty_ns, period_ns);
+}
+
static int qpnp_lpg_pbs_trigger_enable(struct qpnp_lpg_channel *lpg, bool en)
{
struct qpnp_lpg_chip *chip = lpg->chip;
@@ -1065,8 +1083,9 @@ static int qpnp_lpg_pwm_set_output_pattern(struct pwm_chip *pwm_chip,
struct pwm_device *pwm, struct pwm_output_pattern *output_pattern)
{
struct qpnp_lpg_channel *lpg;
- int rc = 0, i, period_ns, duty_ns;
+ u64 period_ns, duty_ns, tmp;
u32 *percentages;
+ int rc = 0, i;
lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
if (lpg == NULL) {
@@ -1086,19 +1105,17 @@ static int qpnp_lpg_pwm_set_output_pattern(struct pwm_chip *pwm_chip,
if (!percentages)
return -ENOMEM;
- period_ns = pwm_get_period(pwm);
+ period_ns = pwm_get_period_extend(pwm);
for (i = 0; i < output_pattern->num_entries; i++) {
duty_ns = output_pattern->duty_pattern[i];
if (duty_ns > period_ns) {
- dev_err(lpg->chip->dev, "duty %dns is larger than period %dns\n",
+ dev_err(lpg->chip->dev, "duty %lluns is larger than period %lluns\n",
duty_ns, period_ns);
goto err;
}
/* Translate the pattern in duty_ns to percentage */
- if ((INT_MAX / duty_ns) < 100)
- percentages[i] = duty_ns / (period_ns / 100);
- else
- percentages[i] = (duty_ns * 100) / period_ns;
+ tmp = (u64)duty_ns * 100;
+ percentages[i] = (u32)div64_u64(tmp, period_ns);
}
rc = qpnp_lpg_set_lut_pattern(lpg, percentages,
@@ -1114,12 +1131,10 @@ static int qpnp_lpg_pwm_set_output_pattern(struct pwm_chip *pwm_chip,
output_pattern->num_entries);
lpg->ramp_config.hi_idx = lpg->ramp_config.lo_idx +
output_pattern->num_entries - 1;
- if ((INT_MAX / period_ns) > output_pattern->cycles_per_duty)
- lpg->ramp_config.step_ms = output_pattern->cycles_per_duty *
- period_ns / NSEC_PER_MSEC;
- else
- lpg->ramp_config.step_ms = (period_ns / NSEC_PER_MSEC) *
- output_pattern->cycles_per_duty;
+
+ tmp = (u64)output_pattern->cycles_per_duty * period_ns;
+ do_div(tmp, NSEC_PER_MSEC);
+ lpg->ramp_config.step_ms = (u16)tmp;
rc = qpnp_lpg_set_ramp_config(lpg);
if (rc < 0)
@@ -1241,8 +1256,8 @@ static void qpnp_lpg_pwm_dbg_show(struct pwm_chip *pwm_chip, struct seq_file *s)
seq_printf(s, " prediv = %d\n", cfg->prediv);
seq_printf(s, " exponent = %d\n", cfg->clk_exp);
seq_printf(s, " pwm_value = %d\n", cfg->pwm_value);
- seq_printf(s, " Requested period: %dns, best period = %dns\n",
- pwm_get_period(pwm), cfg->best_period_ns);
+ seq_printf(s, " Requested period: %lluns, best period = %lluns\n",
+ pwm_get_period_extend(pwm), cfg->best_period_ns);
ramp = &lpg->ramp_config;
if (pwm_get_output_type(pwm) == PWM_OUTPUT_MODULATED) {
@@ -1273,6 +1288,7 @@ static void qpnp_lpg_pwm_dbg_show(struct pwm_chip *pwm_chip, struct seq_file *s)
static const struct pwm_ops qpnp_lpg_pwm_ops = {
.config = qpnp_lpg_pwm_config,
+ .config_extend = qpnp_lpg_pwm_config_extend,
.get_output_type_supported = qpnp_lpg_pwm_output_types_supported,
.set_output_type = qpnp_lpg_pwm_set_output_type,
.set_output_pattern = qpnp_lpg_pwm_set_output_pattern,
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index ea2b53d17199..50b7a3b278c1 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -50,7 +50,7 @@ static ssize_t period_show(struct device *child,
pwm_get_state(pwm, &state);
- return sprintf(buf, "%u\n", state.period);
+ return sprintf(buf, "%llu\n", state.period);
}
static ssize_t period_store(struct device *child,
@@ -85,7 +85,7 @@ static ssize_t duty_cycle_show(struct device *child,
pwm_get_state(pwm, &state);
- return sprintf(buf, "%u\n", state.duty_cycle);
+ return sprintf(buf, "%llu\n", state.duty_cycle);
}
static ssize_t duty_cycle_store(struct device *child,
@@ -220,7 +220,7 @@ static ssize_t capture_show(struct device *child,
if (ret)
return ret;
- return sprintf(buf, "%u %u\n", result.period, result.duty_cycle);
+ return sprintf(buf, "%llu %llu\n", result.period, result.duty_cycle);
}
static ssize_t output_type_show(struct device *child,
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index d4fe6eede3b4..a2b725706667 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -226,14 +226,17 @@ int ufs_qcom_ice_init(struct ufs_qcom_host *qcom_host)
}
qcom_host->dbg_print_en |= UFS_QCOM_ICE_DEFAULT_DBG_PRINT_EN;
- ice_workqueue = alloc_workqueue("ice-set-key",
- WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
if (!ice_workqueue) {
- dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
+ ice_workqueue = alloc_workqueue("ice-set-key",
+ WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+ if (!ice_workqueue) {
+ dev_err(ufs_dev, "%s: workqueue allocation failed.\n",
__func__);
- goto out;
+ err = -ENOMEM;
+ goto out;
+ }
+ INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
}
- INIT_WORK(&qcom_host->ice_cfg_work, ufs_qcom_ice_cfg_work);
out:
return err;
@@ -286,6 +289,17 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
* propagate so it will be re-queued.
*/
if (err == -EAGAIN) {
+ if (!ice_workqueue) {
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock,
+ flags);
+
+ dev_err(qcom_host->hba->dev,
+ "%s: error %d workqueue NULL\n",
+ __func__, err);
+ return -EINVAL;
+ }
+
dev_dbg(qcom_host->hba->dev,
"%s: scheduling task for ice setup\n",
__func__);
@@ -405,6 +419,16 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
* propagate so it will be re-queued.
*/
if (err == -EAGAIN) {
+ if (!ice_workqueue) {
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock,
+ flags);
+
+ dev_err(qcom_host->hba->dev,
+ "%s: error %d workqueue NULL\n",
+ __func__, err);
+ return -EINVAL;
+ }
dev_dbg(qcom_host->hba->dev,
"%s: scheduling task for ice setup\n",
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index a44c988ae8ce..1167c45e3b59 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1308,11 +1308,11 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
/*
* If we are here to disable this clock it might be immediately
* after entering into hibern8 in which case we need to make
- * sure that device ref_clk is active at least 1us after the
- * hibern8 enter.
+ * sure that device ref_clk is active for a given time after the
+ * hibern8 enter for pre UFS3.0 devices
*/
if (!enable)
- udelay(1);
+ udelay(host->hba->dev_ref_clk_gating_wait);
writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio);
@@ -1321,11 +1321,16 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
/*
* If we call hibern8 exit after this, we need to make sure that
- * device ref_clk is stable for at least 1us before the hibern8
+ * device ref_clk is stable for a given time before the hibern8
* exit command.
*/
- if (enable)
- udelay(1);
+ if (enable) {
+ if (host->hba->dev_info.quirks &
+ UFS_DEVICE_QUIRK_WAIT_AFTER_REF_CLK_UNGATE)
+ usleep_range(50, 60);
+ else
+ udelay(1);
+ }
host->is_dev_ref_clk_enabled = enable;
}
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 0ae51b9b81fa..9dd8f951e67b 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -505,6 +505,7 @@ struct ufs_dev_info {
u8 b_device_sub_class;
u16 w_manufacturer_id;
u8 i_product_name;
+ u16 w_spec_version;
/* query flags */
bool f_power_on_wp_en;
diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c
index a2b98fbc2b84..a12c651295f3 100644
--- a/drivers/scsi/ufs/ufs_quirks.c
+++ b/drivers/scsi/ufs/ufs_quirks.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,8 @@ static struct ufs_card_fix ufs_fixups[] = {
UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
+ UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
+ UFS_DEVICE_QUIRK_WAIT_AFTER_REF_CLK_UNGATE),
UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1",
UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH),
UFS_FIX(UFS_VENDOR_SKHYNIX, "hC8aL1",
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 0fa7d93727bd..9d1343987ebf 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -138,6 +138,13 @@ struct ufs_card_fix {
*/
#define UFS_DEVICE_QUIRK_HS_G1_TO_HS_G3_SWITCH (1 << 8)
+/*
+ * Some UFS devices need more delay after device reference clk is turned on
+ * but before initiation of the state transition to STALL from a LS-MODE or
+ * from the HIBERN8 state. Enable this quirk to give UFS devices 50us delay
+ * instead of the default delay.
+ */
+#define UFS_DEVICE_QUIRK_WAIT_AFTER_REF_CLK_UNGATE (1 << 9)
struct ufs_hba;
void ufs_advertise_fixup_device(struct ufs_hba *hba);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d70fc6bb9d72..cd7c68fbc387 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -244,6 +244,9 @@ static void ufshcd_update_uic_error_cnt(struct ufs_hba *hba, u32 reg, int type)
/* default value of auto suspend is 3 seconds */
#define UFSHCD_AUTO_SUSPEND_DELAY_MS 3000 /* millisecs */
+/* default value of ref clock gating wait time is 100 micro seconds */
+#define UFSHCD_REF_CLK_GATING_WAIT_US 100 /* microsecs */
+
#define UFSHCD_CLK_GATING_DELAY_MS_PWR_SAVE 10
#define UFSHCD_CLK_GATING_DELAY_MS_PERF 50
@@ -3445,18 +3448,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
int tag;
struct completion wait;
unsigned long flags;
- bool has_read_lock = false;
-
- /*
- * May get invoked from shutdown and IOCTL contexts.
- * In shutdown context, it comes in with lock acquired.
- * In error recovery context, it may come with lock acquired.
- */
-
- if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
- down_read(&hba->lock);
- has_read_lock = true;
- }
/*
* Get free slot, sleep if slots are unavailable.
@@ -3489,8 +3480,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
out_put_tag:
ufshcd_put_dev_cmd_tag(hba, tag);
wake_up(&hba->dev_cmd.tag_wq);
- if (has_read_lock)
- up_read(&hba->lock);
return err;
}
@@ -3565,10 +3554,15 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
struct ufs_query_res *response = NULL;
int err, index = 0, selector = 0;
int timeout = QUERY_REQ_TIMEOUT;
+ bool has_read_lock = false;
BUG_ON(!hba);
ufshcd_hold_all(hba);
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3612,6 +3606,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
out_unlock:
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
ufshcd_release_all(hba);
return err;
}
@@ -3634,6 +3630,7 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
int err;
+ bool has_read_lock = false;
BUG_ON(!hba);
@@ -3645,6 +3642,16 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
goto out;
}
+ /*
+ * May get invoked from shutdown and IOCTL contexts.
+ * In shutdown context, it comes in with lock acquired.
+ * In error recovery context, it may come with lock acquired.
+ */
+
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3677,6 +3684,8 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
out_unlock:
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
out:
ufshcd_release_all(hba);
return err;
@@ -3727,6 +3736,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
int err;
+ bool has_read_lock = false;
BUG_ON(!hba);
@@ -3745,6 +3755,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
goto out;
}
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
ufshcd_init_query(hba, &request, &response, opcode, idn, index,
selector);
@@ -3780,6 +3794,9 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
out_unlock:
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
+
out:
ufshcd_release_all(hba);
return err;
@@ -5301,8 +5318,13 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
{
int err = 0;
int retries;
+ bool has_read_lock = false;
ufshcd_hold_all(hba);
+ if (!ufshcd_is_shutdown_ongoing(hba) && !ufshcd_eh_in_progress(hba)) {
+ down_read(&hba->lock);
+ has_read_lock = true;
+ }
mutex_lock(&hba->dev_cmd.lock);
for (retries = NOP_OUT_RETRIES; retries > 0; retries--) {
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_NOP,
@@ -5314,6 +5336,8 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
}
mutex_unlock(&hba->dev_cmd.lock);
+ if (has_read_lock)
+ up_read(&hba->lock);
ufshcd_release_all(hba);
if (err)
@@ -7879,6 +7903,31 @@ out:
return err;
}
+static int ufshcd_get_dev_ref_clk_gating_wait(struct ufs_hba *hba)
+{
+ int err = 0;
+ u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US;
+
+ if (hba->dev_info.w_spec_version >= 0x300) {
+ err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0,
+ &gating_wait);
+
+ if (err)
+ dev_err(hba->dev, "failed reading bRefClkGatingWait. err = %d, use default %uus\n",
+ err, gating_wait);
+
+ if (gating_wait == 0) {
+ gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US;
+ dev_err(hba->dev, "undefined ref clk gating wait time, use default %uus\n",
+ gating_wait);
+ }
+ }
+
+ hba->dev_ref_clk_gating_wait = gating_wait;
+ return err;
+}
+
static int ufs_read_device_desc_data(struct ufs_hba *hba)
{
int err = 0;
@@ -7907,6 +7956,10 @@ static int ufs_read_device_desc_data(struct ufs_hba *hba)
hba->dev_info.b_device_sub_class =
desc_buf[DEVICE_DESC_PARAM_DEVICE_SUB_CLASS];
hba->dev_info.i_product_name = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
+ hba->dev_info.w_spec_version =
+ desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 |
+ desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1];
+
out:
kfree(desc_buf);
return err;
@@ -8017,6 +8070,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
"%s: Failed getting max supported power mode\n",
__func__);
} else {
+ ufshcd_get_dev_ref_clk_gating_wait(hba);
/*
* Set the right value to bRefClkFreq before attempting to
* switch to HS gears.
@@ -10252,12 +10306,9 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
* e.g. link_recovery. Hence, release the rw_sem
* before hibern8.
*/
- up_write(&hba->lock);
ret = ufshcd_uic_hibern8_enter(hba);
- down_write(&hba->lock);
if (ret)
- /* link will be bad state so no need to scale_up_gear */
- return ret;
+ goto scale_up_gear;
ufshcd_custom_cmd_log(hba, "Hibern8-entered");
}
@@ -10269,8 +10320,7 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
if (ufshcd_is_auto_hibern8_supported(hba)) {
ret = ufshcd_uic_hibern8_exit(hba);
if (ret)
- /* link will be bad state so no need to scale_up_gear */
- return ret;
+ goto scale_up_gear;
ufshcd_custom_cmd_log(hba, "Hibern8-Exited");
}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6e329c0c391d..0931eeedbcb0 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -3,7 +3,7 @@
*
* This code is based on drivers/scsi/ufs/ufshcd.h
* Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -808,6 +808,7 @@ struct ufs_hba {
unsigned int irq;
bool is_irq_enabled;
+ u32 dev_ref_clk_gating_wait;
u32 dev_ref_clk_freq;
/* Interrupt aggregation support is broken */
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 34be2301be20..44f34cf4227e 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -2083,7 +2083,7 @@ static int ngd_slim_runtime_suspend(struct device *device)
#ifdef CONFIG_PM_SLEEP
static int ngd_slim_suspend(struct device *dev)
{
- int ret = -EBUSY;
+ int ret = 0;
struct platform_device *pdev = to_platform_device(dev);
struct msm_slim_ctrl *cdev;
@@ -2092,6 +2092,13 @@ static int ngd_slim_suspend(struct device *dev)
return 0;
cdev = platform_get_drvdata(pdev);
+
+ if (cdev->state == MSM_CTRL_AWAKE) {
+ ret = -EBUSY;
+ SLIM_INFO(cdev, "system suspend: %d\n", ret);
+ return ret;
+
+ }
if (!pm_runtime_enabled(dev) ||
(!pm_runtime_suspended(dev) &&
cdev->state == MSM_CTRL_IDLE)) {
@@ -2109,17 +2116,6 @@ static int ngd_slim_suspend(struct device *dev)
cdev->qmi.deferred_resp = false;
}
}
- if (ret == -EBUSY) {
- /*
- * There is a possibility that some audio stream is active
- * during suspend. We dont want to return suspend failure in
- * that case so that display and relevant components can still
- * go to suspend.
- * If there is some other error, then it should be passed-on
- * to system level suspend
- */
- ret = 0;
- }
SLIM_INFO(cdev, "system suspend\n");
return ret;
}
diff --git a/drivers/soc/qcom/glink_spi_xprt.c b/drivers/soc/qcom/glink_spi_xprt.c
index a08c4bfde4a2..efcd94cdda01 100644
--- a/drivers/soc/qcom/glink_spi_xprt.c
+++ b/drivers/soc/qcom/glink_spi_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -484,6 +484,13 @@ static int glink_spi_xprt_rx_cmd(struct edge_info *einfo, void *dst,
int ret;
read_id = einfo->rx_fifo_read;
+ if ((read_id > (einfo->rx_fifo_start + einfo->fifo_size)) ||
+ (read_id < einfo->rx_fifo_start)) {
+ pr_err("%s: Invalid rx_fifo_read: %d, start: %d, size: %d\n",
+ __func__, read_id, einfo->rx_fifo_start,
+ einfo->fifo_size);
+ return -EINVAL;
+ }
do {
if ((read_id + size_to_read) >=
(einfo->rx_fifo_start + einfo->fifo_size))
@@ -722,11 +729,11 @@ static void process_rx_cmd(struct edge_info *einfo,
struct rx_short_data_desc {
unsigned char data[SHORT_PKT_SIZE];
};
- struct command *cmd;
+ struct command *cmd = NULL;
struct intent_desc *intents;
struct rx_desc *rx_descp;
struct rx_short_data_desc *rx_sd_descp;
- int offset = 0;
+ uint64_t offset = 0;
int rcu_id;
uint16_t rcid;
uint16_t name_len;
@@ -742,6 +749,8 @@ static void process_rx_cmd(struct edge_info *einfo,
}
while (offset < rx_size) {
+ if (offset + sizeof(*cmd) > rx_size)
+ goto err;
cmd = (struct command *)(rx_data + offset);
offset += sizeof(*cmd);
switch (cmd->id) {
@@ -760,7 +769,12 @@ static void process_rx_cmd(struct edge_info *einfo,
case OPEN_CMD:
rcid = cmd->param1;
name_len = (uint16_t)(cmd->param2 & 0xFFFF);
+ if (name_len > GLINK_NAME_SIZE)
+ goto err;
prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
+ if (offset + ALIGN(name_len, FIFO_ALIGNMENT) >
+ rx_size)
+ goto err;
name = (char *)(rx_data + offset);
offset += ALIGN(name_len, FIFO_ALIGNMENT);
einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
@@ -786,6 +800,8 @@ static void process_rx_cmd(struct edge_info *einfo,
case RX_INTENT_CMD:
for (i = 0; i < cmd->param2; i++) {
+ if (offset + sizeof(*intents) > rx_size)
+ goto err;
intents = (struct intent_desc *)
(rx_data + offset);
offset += sizeof(*intents);
@@ -821,6 +837,8 @@ static void process_rx_cmd(struct edge_info *einfo,
case TX_DATA_CONT_CMD:
case TRACER_PKT_CMD:
case TRACER_PKT_CONT_CMD:
+ if (offset + sizeof(*rx_descp) > rx_size)
+ goto err;
rx_descp = (struct rx_desc *)(rx_data + offset);
offset += sizeof(*rx_descp);
process_rx_data(einfo, cmd->id, cmd->param1,
@@ -830,6 +848,8 @@ static void process_rx_cmd(struct edge_info *einfo,
break;
case TX_SHORT_DATA_CMD:
+ if (offset + sizeof(*rx_sd_descp) > rx_size)
+ goto err;
rx_sd_descp = (struct rx_short_data_desc *)
(rx_data + offset);
offset += sizeof(*rx_sd_descp);
@@ -858,6 +878,13 @@ static void process_rx_cmd(struct edge_info *einfo,
}
}
srcu_read_unlock(&einfo->use_ref, rcu_id);
+ return;
+err:
+ srcu_read_unlock(&einfo->use_ref, rcu_id);
+ if (cmd)
+ pr_err("%s: invalid size of rx_data: %d, cmd : %d\n",
+ __func__, rx_size, cmd->id);
+ return;
}
/**
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 15e10907c6ef..f3acd4113b06 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -76,6 +76,8 @@ module_param(qmi_timeout, ulong, 0600);
#define ICNSS_MAX_PROBE_CNT 2
+#define PROBE_TIMEOUT 5000
+
#define icnss_ipc_log_string(_x...) do { \
if (icnss_ipc_log_context) \
ipc_log_string(icnss_ipc_log_context, _x); \
@@ -286,6 +288,7 @@ enum icnss_driver_state {
ICNSS_DRIVER_UNLOADING,
ICNSS_REJUVENATE,
ICNSS_MODE_ON,
+ ICNSS_BLOCK_SHUTDOWN,
};
struct ce_irq_list {
@@ -475,6 +478,7 @@ static struct icnss_priv {
struct mutex dev_lock;
uint32_t fw_error_fatal_irq;
uint32_t fw_early_crash_irq;
+ struct completion unblock_shutdown;
} *penv;
#ifdef CONFIG_ICNSS_DEBUG
@@ -1164,6 +1168,21 @@ bool icnss_is_fw_ready(void)
}
EXPORT_SYMBOL(icnss_is_fw_ready);
+void icnss_block_shutdown(bool status)
+{
+ if (!penv)
+ return;
+
+ if (status) {
+ set_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
+ reinit_completion(&penv->unblock_shutdown);
+ } else {
+ clear_bit(ICNSS_BLOCK_SHUTDOWN, &penv->state);
+ complete(&penv->unblock_shutdown);
+ }
+}
+EXPORT_SYMBOL(icnss_block_shutdown);
+
bool icnss_is_fw_down(void)
{
if (!penv)
@@ -2256,6 +2275,7 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
icnss_hw_power_on(priv);
+ icnss_block_shutdown(true);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = priv->ops->probe(&priv->pdev->dev);
probe_cnt++;
@@ -2265,9 +2285,11 @@ static int icnss_call_driver_probe(struct icnss_priv *priv)
if (ret < 0) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
ret, priv->state, probe_cnt);
+ icnss_block_shutdown(false);
goto out;
}
+ icnss_block_shutdown(false);
set_bit(ICNSS_DRIVER_PROBED, &priv->state);
return 0;
@@ -2406,6 +2428,7 @@ static int icnss_driver_event_register_driver(void *data)
if (ret)
goto out;
+ icnss_block_shutdown(true);
while (probe_cnt < ICNSS_MAX_PROBE_CNT) {
ret = penv->ops->probe(&penv->pdev->dev);
probe_cnt++;
@@ -2415,9 +2438,11 @@ static int icnss_driver_event_register_driver(void *data)
if (ret) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx, probe_cnt: %d\n",
ret, penv->state, probe_cnt);
+ icnss_block_shutdown(false);
goto power_off;
}
+ icnss_block_shutdown(false);
set_bit(ICNSS_DRIVER_PROBED, &penv->state);
return 0;
@@ -2436,9 +2461,14 @@ static int icnss_driver_event_unregister_driver(void *data)
}
set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
+
+ icnss_block_shutdown(true);
+
if (penv->ops)
penv->ops->remove(&penv->pdev->dev);
+ icnss_block_shutdown(false);
+
clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
clear_bit(ICNSS_DRIVER_PROBED, &penv->state);
@@ -2497,7 +2527,8 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv,
goto out;
}
- icnss_fw_crashed(priv, event_data);
+ if (!test_bit(ICNSS_PD_RESTART, &priv->state))
+ icnss_fw_crashed(priv, event_data);
out:
kfree(data);
@@ -2684,6 +2715,13 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
if (code != SUBSYS_BEFORE_SHUTDOWN)
return NOTIFY_OK;
+ if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
+ test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
+ if (!wait_for_completion_timeout(&priv->unblock_shutdown,
+ PROBE_TIMEOUT))
+ icnss_pr_err("wlan driver probe timeout\n");
+ }
+
if (test_bit(ICNSS_PDR_REGISTERED, &priv->state)) {
set_bit(ICNSS_FW_DOWN, &priv->state);
icnss_ignore_qmi_timeout(true);
@@ -4049,6 +4087,9 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
continue;
case ICNSS_MODE_ON:
seq_puts(s, "MODE ON DONE");
+ continue;
+ case ICNSS_BLOCK_SHUTDOWN:
+ seq_puts(s, "BLOCK SHUTDOWN");
}
seq_printf(s, "UNKNOWN-%d", i);
@@ -4720,6 +4761,8 @@ static int icnss_probe(struct platform_device *pdev)
penv = priv;
+ init_completion(&priv->unblock_shutdown);
+
icnss_pr_info("Platform driver probed successfully\n");
return 0;
@@ -4742,6 +4785,8 @@ static int icnss_remove(struct platform_device *pdev)
icnss_debugfs_destroy(penv);
+ complete_all(&penv->unblock_shutdown);
+
icnss_modem_ssr_unregister_notifier(penv);
destroy_ramdump_device(penv->msa0_dump_dev);
diff --git a/drivers/soc/qcom/pil-q6v5.c b/drivers/soc/qcom/pil-q6v5.c
index d23b0506ef02..142a6cdfbf30 100644
--- a/drivers/soc/qcom/pil-q6v5.c
+++ b/drivers/soc/qcom/pil-q6v5.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -169,7 +169,7 @@ err_vreg_pll:
err_cx_enable:
regulator_set_load(drv->vreg_cx, 0);
err_cx_mode:
- regulator_set_voltage(drv->vreg_cx, 0, uv);
+ regulator_set_voltage(drv->vreg_cx, 0, INT_MAX);
err_cx_voltage:
clk_disable_unprepare(drv->axis2_clk);
err_axis2_vote:
@@ -203,7 +203,7 @@ void pil_q6v5_remove_proxy_votes(struct pil_desc *pil)
}
regulator_disable(drv->vreg_cx);
regulator_set_load(drv->vreg_cx, 0);
- regulator_set_voltage(drv->vreg_cx, 0, uv);
+ regulator_set_voltage(drv->vreg_cx, 0, INT_MAX);
clk_disable_unprepare(drv->xo);
clk_disable_unprepare(drv->pnoc_clk);
clk_disable_unprepare(drv->qdss_clk);
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index e78a49a011d7..cad75e76f1fe 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -602,8 +602,8 @@ static struct msm_soc_info cpu_of_id[] = {
/* SDM710 ID */
[360] = {MSM_CPU_SDM710, "SDM710"},
- /* SDMNOBELIUM ID */
- [393] = {MSM_CPU_SDMNOBELIUM, "SDMNOBELIUM"},
+ /* SDM712 ID */
+ [393] = {MSM_CPU_SDM712, "SDM712"},
/* SXR1120 ID */
[370] = {MSM_CPU_SXR1120, "SXR1120"},
@@ -1560,9 +1560,9 @@ static void * __init setup_dummy_socinfo(void)
dummy_socinfo.id = 360;
strlcpy(dummy_socinfo.build_id, "sdm710 - ",
sizeof(dummy_socinfo.build_id));
- } else if (early_machine_is_sdmnobelium()) {
+ } else if (early_machine_is_sdm712()) {
dummy_socinfo.id = 393;
- strlcpy(dummy_socinfo.build_id, "sdmnobelium - ",
+ strlcpy(dummy_socinfo.build_id, "sdm712 - ",
sizeof(dummy_socinfo.build_id));
} else if (early_machine_is_sda670()) {
dummy_socinfo.id = 337;
diff --git a/drivers/soc/qcom/subsys-pil-bg.c b/drivers/soc/qcom/subsys-pil-bg.c
index 4f5e4d4f32c6..d1b5feadf989 100644
--- a/drivers/soc/qcom/subsys-pil-bg.c
+++ b/drivers/soc/qcom/subsys-pil-bg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -303,6 +303,8 @@ static int bg_powerup(const struct subsys_desc *subsys)
"%s: BG PIL Boot failed\n", __func__);
return ret;
}
+ /* wait for msm_gpio_irq_handler to get invoked before enable irq */
+ usleep_range(5000, 6000);
enable_irq(bg_data->status_irq);
ret = wait_for_err_ready(bg_data);
if (ret) {
diff --git a/drivers/spmi/spmi-pmic-arb-debug.c b/drivers/spmi/spmi-pmic-arb-debug.c
index 2c90bef1224f..48fe4e985ff5 100644
--- a/drivers/spmi/spmi-pmic-arb-debug.c
+++ b/drivers/spmi/spmi-pmic-arb-debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -365,17 +365,7 @@ static struct platform_driver spmi_pmic_arb_debug_driver = {
},
};
-int __init spmi_pmic_arb_debug_init(void)
-{
- return platform_driver_register(&spmi_pmic_arb_debug_driver);
-}
-arch_initcall(spmi_pmic_arb_debug_init);
-
-static void __exit spmi_pmic_arb_debug_exit(void)
-{
- platform_driver_unregister(&spmi_pmic_arb_debug_driver);
-}
-module_exit(spmi_pmic_arb_debug_exit);
+module_platform_driver(spmi_pmic_arb_debug_driver);
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spmi_pmic_arb_debug");
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index f05471d3f4aa..b664f1686da3 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -2,7 +2,7 @@
* drivers/staging/android/ion/ion_system_heap.c
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -275,6 +275,9 @@ static struct page_info *alloc_from_pool_preferred(
struct page_info *info;
int i;
+ if (buffer->flags & ION_FLAG_POOL_FORCE_ALLOC)
+ goto force_alloc;
+
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return NULL;
@@ -306,6 +309,7 @@ static struct page_info *alloc_from_pool_preferred(
}
kfree(info);
+force_alloc:
return alloc_largest_available(heap, buffer, size, max_order);
}
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index d9baac65bd0a..a866332b9e8e 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -424,6 +424,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
dwc->ep0_usb_req.request.buf = dwc->setup_buf;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
+ dwc->ep0_usb_req.request.dma = DMA_ERROR_CODE;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
}
@@ -760,6 +761,7 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
dwc->ep0_usb_req.request.buf = dwc->setup_buf;
dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
+ dwc->ep0_usb_req.request.dma = DMA_ERROR_CODE;
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
}
diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c
index f8e44580df41..5344b42ee791 100644
--- a/drivers/video/fbdev/msm/mdp3.c
+++ b/drivers/video/fbdev/msm/mdp3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This software is licensed under the terms of the GNU General Public
@@ -916,17 +916,6 @@ u64 mdp3_get_panic_lut_cfg(u32 panel_width)
return panic_config;
}
-int mdp3_enable_panic_ctrl(void)
-{
- int rc = 0;
-
- if (MDP3_REG_READ(MDP3_PANIC_ROBUST_CTRL) == 0) {
- pr_err("%s: Enable Panic Control\n", __func__);
- MDP3_REG_WRITE(MDP3_PANIC_ROBUST_CTRL, BIT(0));
- }
- return rc;
-}
-
int mdp3_qos_remapper_setup(struct mdss_panel_data *panel)
{
int rc = 0;
diff --git a/drivers/video/fbdev/msm/mdp3.h b/drivers/video/fbdev/msm/mdp3.h
index 6b560521ec53..3ab4652d0c72 100644
--- a/drivers/video/fbdev/msm/mdp3.h
+++ b/drivers/video/fbdev/msm/mdp3.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2016-2019, The Linux Foundation. All rights reserved.
* Copyright (C) 2007 Google Incorporated
*
* This program is free software; you can redistribute it and/or modify
@@ -281,7 +281,6 @@ u64 mdp3_clk_round_off(u64 clk_rate);
void mdp3_calc_dma_res(struct mdss_panel_info *panel_info, u64 *clk_rate,
u64 *ab, u64 *ib, uint32_t bpp);
void mdp3_clear_irq(u32 interrupt_mask);
-int mdp3_enable_panic_ctrl(void);
void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata, u32 bl_level);
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index ff7d7126df85..6e8cda0f1a8f 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -261,7 +261,8 @@ static void mdp3_vsync_retire_handle_vsync(void *arg)
return;
}
- schedule_work(&mdp3_session->retire_work);
+ kthread_queue_work(&mdp3_session->retire_worker,
+ &mdp3_session->retire_work);
}
void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
@@ -282,7 +283,7 @@ void mdp3_vsync_retire_signal(struct msm_fb_data_type *mfd, int val)
mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
}
-static void mdp3_vsync_retire_work_handler(struct work_struct *work)
+static void mdp3_vsync_retire_work_handler(struct kthread_work *work)
{
struct mdp3_session_data *mdp3_session =
container_of(work, struct mdp3_session_data, retire_work);
@@ -954,14 +955,12 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
mdp3_session->in_splash_screen) {
/* Turn on panel so that it can exit low power mode */
mdp3_clk_enable(1, 0);
- rc = panel->event_handler(panel,
+ rc = panel->event_handler(panel,
MDSS_EVENT_LINK_READY, NULL);
- rc |= panel->event_handler(panel,
+ rc |= panel->event_handler(panel,
MDSS_EVENT_UNBLANK, NULL);
- rc |= panel->event_handler(panel,
+ rc |= panel->event_handler(panel,
MDSS_EVENT_PANEL_ON, NULL);
- if (mdss_fb_is_power_on_lp(mfd))
- rc |= mdp3_enable_panic_ctrl();
mdp3_clk_enable(0, 0);
}
}
@@ -2981,6 +2980,7 @@ static int mdp3_vsync_retire_setup(struct msm_fb_data_type *mfd)
struct mdp3_session_data *mdp3_session;
struct mdp3_notification retire_client;
char name[24];
+ struct sched_param param = { .sched_priority = 16 };
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -2998,7 +2998,20 @@ static int mdp3_vsync_retire_setup(struct msm_fb_data_type *mfd)
if (mdp3_session->dma)
mdp3_session->dma->retire_client = retire_client;
- INIT_WORK(&mdp3_session->retire_work, mdp3_vsync_retire_work_handler);
+ kthread_init_worker(&mdp3_session->retire_worker);
+ kthread_init_work(&mdp3_session->retire_work,
+ mdp3_vsync_retire_work_handler);
+
+ mdp3_session->retire_thread = kthread_run(kthread_worker_fn,
+ &mdp3_session->retire_worker,
+ "vsync_retire_work");
+ if (IS_ERR(mdp3_session->retire_thread)) {
+ pr_err("unable to start vsync thread\n");
+ mdp3_session->retire_thread = NULL;
+ return -ENOMEM;
+ }
+
+ sched_setscheduler(mdp3_session->retire_thread, SCHED_FIFO, &param);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.h b/drivers/video/fbdev/msm/mdp3_ctrl.h
index 032debe1aa85..07377a92981e 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.h
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -61,6 +61,10 @@ struct mdp3_session_data {
struct kthread_worker worker;
struct task_struct *thread;
+ struct kthread_work retire_work;
+ struct kthread_worker retire_worker;
+ struct task_struct *retire_thread;
+
atomic_t dma_done_cnt;
int histo_status;
struct mutex histo_lock;
@@ -84,7 +88,6 @@ struct mdp3_session_data {
/* For retire fence */
struct mdss_timeline *vsync_timeline;
int retire_cnt;
- struct work_struct retire_work;
};
void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client);
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 631c1ecd4f5c..87f85d5620d3 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -3005,7 +3005,7 @@ static int __mdss_fb_wait_for_fence_sub(struct msm_sync_pt_data *sync_pt_data,
ret = mdss_wait_sync_fence(fences[i], wait_ms);
- if (ret == -ETIME) {
+ if (ret == -ETIMEDOUT) {
wait_jf = timeout - jiffies;
wait_ms = jiffies_to_msecs(wait_jf);
if (wait_jf < 0)
@@ -3022,14 +3022,14 @@ static int __mdss_fb_wait_for_fence_sub(struct msm_sync_pt_data *sync_pt_data,
MDSS_XLOG_TOUT_HANDLER("mdp");
ret = mdss_wait_sync_fence(fences[i], wait_ms);
- if (ret == -ETIME)
+ if (ret == -ETIMEDOUT)
break;
}
mdss_put_sync_fence(fences[i]);
}
if (ret < 0) {
- pr_err("%s: sync_fence_wait failed! ret = %x\n",
+ pr_err("%s: sync_fence_wait failed! ret = %d\n",
sync_pt_data->fence_name, ret);
for (; i < fence_cnt; i++)
mdss_put_sync_fence(fences[i]);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index 8c5f407c6510..1c70637e6191 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3232,6 +3232,7 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
struct mdss_mdp_cmd_ctx *sctx = NULL;
struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+ struct mdss_panel_data *pdata;
bool panel_off = false;
bool turn_off_clocks = false;
bool send_panel_events = false;
@@ -3242,6 +3243,7 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
return -ENODEV;
}
+ pdata = ctl->panel_data;
if (__mdss_mdp_cmd_is_panel_power_off(ctx)) {
pr_debug("%s: panel already off\n", __func__);
return 0;
@@ -3278,7 +3280,8 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl, int panel_power_state)
send_panel_events = true;
if (mdss_panel_is_power_on_ulp(panel_power_state)) {
turn_off_clocks = true;
- } else if (atomic_read(&ctx->koff_cnt)) {
+ } else if (atomic_read(&ctx->koff_cnt) &&
+ !pdata->panel_info.panel_dead) {
/*
* Transition from interactive to low power
* Wait for kickoffs to finish
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e69ebe648a34..be3e1db832b5 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -456,17 +456,12 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
return inode;
}
-int proc_fill_super(struct super_block *s, void *data, int silent)
+int proc_fill_super(struct super_block *s)
{
- struct pid_namespace *ns = get_pid_ns(s->s_fs_info);
struct inode *root_inode;
int ret;
- if (!proc_parse_options(data, ns))
- return -EINVAL;
-
- /* User space would break if executables or devices appear on proc */
- s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC | SB_I_NODEV;
+ s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NODEV;
s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index d8105cd8b01c..d8edf39e0c1d 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -213,7 +213,7 @@ extern const struct file_operations proc_reclaim_operations;
extern void proc_init_inodecache(void);
extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *);
-extern int proc_fill_super(struct super_block *, void *data, int flags);
+extern int proc_fill_super(struct super_block *);
extern void proc_entry_rundown(struct proc_dir_entry *);
/*
@@ -278,7 +278,6 @@ static inline void proc_tty_init(void) {}
* root.c
*/
extern struct proc_dir_entry proc_root;
-extern int proc_parse_options(char *options, struct pid_namespace *pid);
extern void proc_self_init(void);
extern int proc_remount(struct super_block *, int *, char *);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index c2f5014d642d..1d68fcd9313f 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -23,6 +23,21 @@
#include "internal.h"
+static int proc_test_super(struct super_block *sb, void *data)
+{
+ return sb->s_fs_info == data;
+}
+
+static int proc_set_super(struct super_block *sb, void *data)
+{
+ int err = set_anon_super(sb, NULL);
+ if (!err) {
+ struct pid_namespace *ns = (struct pid_namespace *)data;
+ sb->s_fs_info = get_pid_ns(ns);
+ }
+ return err;
+}
+
enum {
Opt_gid, Opt_hidepid, Opt_err,
};
@@ -33,7 +48,7 @@ static const match_table_t tokens = {
{Opt_err, NULL},
};
-int proc_parse_options(char *options, struct pid_namespace *pid)
+static int proc_parse_options(char *options, struct pid_namespace *pid)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -85,16 +100,45 @@ int proc_remount(struct super_block *sb, int *flags, char *data)
static struct dentry *proc_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
+ int err;
+ struct super_block *sb;
struct pid_namespace *ns;
+ char *options;
if (flags & MS_KERNMOUNT) {
- ns = data;
- data = NULL;
+ ns = (struct pid_namespace *)data;
+ options = NULL;
} else {
ns = task_active_pid_ns(current);
+ options = data;
+
+ /* Does the mounter have privilege over the pid namespace? */
+ if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+ return ERR_PTR(-EPERM);
+ }
+
+ sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
+ if (IS_ERR(sb))
+ return ERR_CAST(sb);
+
+ if (!proc_parse_options(options, ns)) {
+ deactivate_locked_super(sb);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!sb->s_root) {
+ err = proc_fill_super(sb);
+ if (err) {
+ deactivate_locked_super(sb);
+ return ERR_PTR(err);
+ }
+
+ sb->s_flags |= MS_ACTIVE;
+ /* User space would break if executables appear on proc */
+ sb->s_iflags |= SB_I_NOEXEC;
}
- return mount_ns(fs_type, flags, data, ns, ns->user_ns, proc_fill_super);
+ return dget(sb->s_root);
}
static void proc_kill_sb(struct super_block *sb)
diff --git a/include/dt-bindings/clock/msm-clocks-hwio-8952.h b/include/dt-bindings/clock/msm-clocks-hwio-8952.h
index cba5a864b1d2..a8483cb6ae98 100644
--- a/include/dt-bindings/clock/msm-clocks-hwio-8952.h
+++ b/include/dt-bindings/clock/msm-clocks-hwio-8952.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, 2018-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -294,7 +294,8 @@
#define dsi0_1phypll_source_val 3 /* byte1_clk & pclk1_clk */
#define dsi1_0phypll_source_val 3 /* byte0_clk & pclk0_clk */
#define dsi1_1phypll_source_val 1 /* byte1_clk & pclk1_clk */
-
+#define gpll0_gfx_source_val 5 /* GPLL0 GFX on QM215 */
+#define gpll6_gfx_source_val 6 /* GPLL6 GFX on QM215 */
#define F(f, s, div, m, n) \
{ \
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 62f4fa8b4e50..5e9bb82c5618 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -66,6 +66,7 @@
#define DIAG_IOCTL_REGISTER_CALLBACK 37
#define DIAG_IOCTL_HDLC_TOGGLE 38
#define DIAG_IOCTL_QUERY_PD_LOGGING 39
+#define DIAG_IOCTL_QUERY_MD_PID 41
/* PC Tools IDs */
#define APQ8060_TOOLS_ID 4062
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index 08f30a46726f..9d13f24a33d4 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -215,6 +215,7 @@ struct hdcp_register_data {
int hdcp_library_register(struct hdcp_register_data *data);
void hdcp_library_deregister(void *phdcpcontext);
bool hdcp1_check_if_supported_load_app(void);
+void hdcp1_unload_app(void);
int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb);
int hdcp1_set_enc(bool enable);
#endif /* __HDCP_QSEECOM_H */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 325f649d77ff..377417200728 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -210,6 +210,7 @@ extern struct task_group root_task_group;
.policy = SCHED_NORMAL, \
.cpus_allowed = CPU_MASK_ALL, \
.nr_cpus_allowed= NR_CPUS, \
+ .cpus_requested = CPU_MASK_ALL, \
.mm = NULL, \
.active_mm = &init_mm, \
.restart_block = { \
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index d32e7b8c0b87..29dedd4eb1b1 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -497,8 +497,8 @@ struct perf_addr_filters_head {
* enum perf_event_active_state - the states of a event
*/
enum perf_event_active_state {
- PERF_EVENT_STATE_DEAD = -5,
- PERF_EVENT_STATE_ZOMBIE = -4,
+ PERF_EVENT_STATE_DORMANT = -5,
+ PERF_EVENT_STATE_DEAD = -4,
PERF_EVENT_STATE_EXIT = -3,
PERF_EVENT_STATE_ERROR = -2,
PERF_EVENT_STATE_OFF = -1,
@@ -721,7 +721,13 @@ struct perf_event {
/* Is this event shared with other events */
bool shared;
- struct list_head zombie_entry;
+
+ /*
+ * Entry into the list that holds the events whose CPUs
+ * are offline. These events will be installed once the
+ * CPU wakes up and will be removed from the list after that
+ */
+ struct list_head dormant_event_entry;
#endif /* CONFIG_PERF_EVENTS */
};
@@ -1401,9 +1407,11 @@ static struct device_attribute format_attr_##_name = __ATTR_RO(_name)
#ifdef CONFIG_PERF_EVENTS
int perf_event_init_cpu(unsigned int cpu);
int perf_event_exit_cpu(unsigned int cpu);
+int perf_event_restart_events(unsigned int cpu);
#else
#define perf_event_init_cpu NULL
#define perf_event_exit_cpu NULL
+#define perf_event_restart_events NULL
#endif
#endif /* _LINUX_PERF_EVENT_H */
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 6c0168b0f44c..b40287e0ce16 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -38,7 +38,7 @@ enum pwm_polarity {
* current PWM hardware state.
*/
struct pwm_args {
- unsigned int period;
+ u64 period;
enum pwm_polarity polarity;
};
@@ -65,9 +65,9 @@ enum pwm_output_type {
* @cycles_per_duty: number of PWM period cycles an entry stays at
*/
struct pwm_output_pattern {
- unsigned int *duty_pattern;
+ u64 *duty_pattern;
unsigned int num_entries;
- unsigned int cycles_per_duty;
+ u64 cycles_per_duty;
};
/*
@@ -78,8 +78,8 @@ struct pwm_output_pattern {
* @enabled: PWM enabled status
*/
struct pwm_state {
- unsigned int period;
- unsigned int duty_cycle;
+ u64 period;
+ u64 duty_cycle;
enum pwm_polarity polarity;
enum pwm_output_type output_type;
struct pwm_output_pattern *output_pattern;
@@ -135,12 +135,30 @@ static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period)
pwm->state.period = period;
}
+static inline void pwm_set_period_extend(struct pwm_device *pwm, u64 period)
+{
+ if (pwm)
+ pwm->state.period = period;
+}
+
static inline unsigned int pwm_get_period(const struct pwm_device *pwm)
{
struct pwm_state state;
pwm_get_state(pwm, &state);
+ if (state.period > UINT_MAX)
+ pr_warn("PWM period %llu is truncated\n", state.period);
+
+ return (unsigned int)state.period;
+}
+
+static inline u64 pwm_get_period_extend(const struct pwm_device *pwm)
+{
+ struct pwm_state state;
+
+ pwm_get_state(pwm, &state);
+
return state.period;
}
@@ -150,12 +168,30 @@ static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty)
pwm->state.duty_cycle = duty;
}
+static inline void pwm_set_duty_cycle_extend(struct pwm_device *pwm, u64 duty)
+{
+ if (pwm)
+ pwm->state.duty_cycle = duty;
+}
+
static inline unsigned int pwm_get_duty_cycle(const struct pwm_device *pwm)
{
struct pwm_state state;
pwm_get_state(pwm, &state);
+ if (state.duty_cycle > UINT_MAX)
+ pr_warn("PWM duty cycle %llu is truncated\n", state.duty_cycle);
+
+ return (unsigned int)state.duty_cycle;
+}
+
+static inline u64 pwm_get_duty_cycle_extend(const struct pwm_device *pwm)
+{
+ struct pwm_state state;
+
+ pwm_get_state(pwm, &state);
+
return state.duty_cycle;
}
@@ -287,6 +323,8 @@ pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
* @request: optional hook for requesting a PWM
* @free: optional hook for freeing a PWM
* @config: configure duty cycles and period length for this PWM
+ * @config_extend: configure duty cycles and period length for this
+ * PWM with u64 data type
* @set_polarity: configure the polarity of this PWM
* @capture: capture and report PWM signal
* @enable: enable PWM output toggling
@@ -309,6 +347,8 @@ struct pwm_ops {
void (*free)(struct pwm_chip *chip, struct pwm_device *pwm);
int (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns);
+ int (*config_extend)(struct pwm_chip *chip, struct pwm_device *pwm,
+ u64 duty_ns, u64 period_ns);
int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm,
enum pwm_polarity polarity);
int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -366,8 +406,8 @@ struct pwm_chip {
* @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
*/
struct pwm_capture {
- unsigned int period;
- unsigned int duty_cycle;
+ u64 period;
+ u64 duty_cycle;
};
#if IS_ENABLED(CONFIG_PWM)
@@ -421,6 +461,31 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
}
/**
+ * pwm_config_extend() - change PWM period and duty length with u64 data type
+ * @pwm: PWM device
+ * @duty_ns: "on" time (in nanoseconds)
+ * @period_ns: duration (in nanoseconds) of one cycle
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+static inline int pwm_config_extend(struct pwm_device *pwm, u64 duty_ns,
+ u64 period_ns)
+{
+ struct pwm_state state;
+
+ if (!pwm)
+ return -EINVAL;
+
+ pwm_get_state(pwm, &state);
+ if (state.duty_cycle == duty_ns && state.period == period_ns)
+ return 0;
+
+ state.duty_cycle = duty_ns;
+ state.period = period_ns;
+ return pwm_apply_state(pwm, &state);
+}
+
+/**
* pwm_set_polarity() - configure the polarity of a PWM signal
* @pwm: PWM device
* @polarity: new polarity of the PWM signal
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 009ed0a7d4c7..e11e0232b25e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1803,6 +1803,7 @@ struct task_struct {
unsigned int policy;
int nr_cpus_allowed;
cpumask_t cpus_allowed;
+ cpumask_t cpus_requested;
#ifdef CONFIG_PREEMPT_RCU
int rcu_read_lock_nesting;
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 7ef3db418100..0732a6fd33d1 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -144,4 +144,5 @@ extern bool icnss_is_fw_ready(void);
extern bool icnss_is_fw_down(void);
extern bool icnss_is_rejuvenate(void);
extern int icnss_trigger_recovery(struct device *dev);
+extern void icnss_block_shutdown(bool status);
#endif /* _ICNSS_WLAN_H_ */
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index c7dcf366ef01..862153eae123 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -114,7 +114,7 @@
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sxr1120")
#define early_machine_is_msm8953() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8953")
-#define early_machine_is_sdmnobelium() \
+#define early_machine_is_sdm712() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm670")
#define early_machine_is_msm8937() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8937")
@@ -201,7 +201,7 @@
#define early_machine_is_sda429() 0
#define early_machine_is_mdm9650() 0
#define early_machine_is_qm215() 0
-#define early_machine_is_sdmnobelium() 0
+#define early_machine_is_sdm712() 0
#endif
#define PLATFORM_SUBTYPE_MDM 1
@@ -279,7 +279,7 @@ enum msm_cpu {
MSM_CPU_8940,
MSM_CPU_9607,
MSM_CPU_SDM439,
- MSM_CPU_SDMNOBELIUM,
+ MSM_CPU_SDM712,
MSM_CPU_SDM429,
MSM_CPU_SDA439,
MSM_CPU_SDA429,
diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h
index db433542860b..e69fe7ab5f96 100644
--- a/include/uapi/media/cam_defs.h
+++ b/include/uapi/media/cam_defs.h
@@ -163,7 +163,8 @@ struct cam_iommu_handle {
#define CAM_FORMAT_PLAIN8_10_SWAP 43
#define CAM_FORMAT_YV12 44
#define CAM_FORMAT_Y_ONLY 45
-#define CAM_FORMAT_MAX 46
+#define CAM_FORMAT_DPCM_12_10_12 46
+#define CAM_FORMAT_MAX 47
/* camera rotaion */
#define CAM_ROTATE_CW_0_DEGREE 0
diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h
index 2344b223ec0d..91360e240b49 100644
--- a/include/uapi/media/cam_isp.h
+++ b/include/uapi/media/cam_isp.h
@@ -89,6 +89,7 @@
#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG 2
#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG 3
#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 4
+#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 5
/* Query devices */
/**
@@ -386,6 +387,44 @@ struct cam_isp_bw_config {
struct cam_isp_bw_vote rdi_vote[1];
} __attribute__((packed));
+/**
+ * struct cam_fe_config - Fetch Engine configuration
+ *
+ * @version: fetch engine veriosn
+ * @min_vbi: require min vbi
+ * @fs_mode: indicates if fs mode enabled
+ * @fs_line_sync_en: frame level sync or line level
+ * sync for fetch engine
+ * @hbi_count: hbi count
+ * @fs_sync_enable: indicates if fetch engine working
+ * wokring in sync with write engine
+ * @go_cmd_sel: softwrae go_cmd or hw go_cmd
+ * @client_enable: enable read engine
+ * @source_addr: adrress of buffer to read from
+ * @width: buffer width
+ * @height: buffer height
+ * @stride: buffer stride (here equal to width)
+ * @format: format of image in buffer
+ * @unpacker_cfg: unpacker config type
+ * @latency_buf_size: latency buffer for read engine
+ */
+struct cam_fe_config {
+ uint64_t version;
+ uint32_t min_vbi;
+ uint32_t fs_mode;
+ uint32_t fs_line_sync_en;
+ uint32_t hbi_count;
+ uint32_t fs_sync_enable;
+ uint32_t go_cmd_sel;
+ uint32_t client_enable;
+ uint32_t source_addr;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ uint32_t unpacker_cfg;
+ uint32_t latency_buf_size;
+} __attribute__((packed));
/* Acquire Device/HW v2 */
diff --git a/include/uapi/media/cam_isp_ife.h b/include/uapi/media/cam_isp_ife.h
index b806befa2bed..7e9ba62c507f 100644
--- a/include/uapi/media/cam_isp_ife.h
+++ b/include/uapi/media/cam_isp_ife.h
@@ -27,7 +27,8 @@
#define CAM_ISP_IFE_OUT_RES_DS4_DISP (CAM_ISP_IFE_OUT_RES_BASE + 20)
#define CAM_ISP_IFE_OUT_RES_DS16_DISP (CAM_ISP_IFE_OUT_RES_BASE + 21)
#define CAM_ISP_IFE_OUT_RES_2PD (CAM_ISP_IFE_OUT_RES_BASE + 22)
-#define CAM_ISP_IFE_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_BASE + 23)
+#define CAM_ISP_IFE_OUT_RES_RDI_RD (CAM_ISP_IFE_OUT_RES_BASE + 23)
+#define CAM_ISP_IFE_OUT_RES_MAX (CAM_ISP_IFE_OUT_RES_BASE + 24)
/*IFE input port resource type (global unique) */
#define CAM_ISP_IFE_IN_RES_BASE 0x4000
@@ -37,6 +38,7 @@
#define CAM_ISP_IFE_IN_RES_PHY_1 (CAM_ISP_IFE_IN_RES_BASE + 2)
#define CAM_ISP_IFE_IN_RES_PHY_2 (CAM_ISP_IFE_IN_RES_BASE + 3)
#define CAM_ISP_IFE_IN_RES_PHY_3 (CAM_ISP_IFE_IN_RES_BASE + 4)
-#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 5)
+#define CAM_ISP_IFE_IN_RES_RD (CAM_ISP_IFE_IN_RES_BASE + 5)
+#define CAM_ISP_IFE_IN_RES_MAX (CAM_ISP_IFE_IN_RES_BASE + 6)
#endif /* __UAPI_CAM_ISP_IFE_H__ */
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index 0b4f1cc40df3..b903078dccbd 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -383,10 +383,12 @@ struct cam_mem_cache_ops_cmd {
* @CAM_REQ_MGR_ERROR_TYPE_DEVICE: Device error message, fatal to session
* @CAM_REQ_MGR_ERROR_TYPE_REQUEST: Error on a single request, not fatal
* @CAM_REQ_MGR_ERROR_TYPE_BUFFER: Buffer was not filled, not fatal
+ * @CAM_REQ_MGR_ERROR_TYPE_RECOVERY: Fatal error, can be recovered
*/
#define CAM_REQ_MGR_ERROR_TYPE_DEVICE 0
#define CAM_REQ_MGR_ERROR_TYPE_REQUEST 1
#define CAM_REQ_MGR_ERROR_TYPE_BUFFER 2
+#define CAM_REQ_MGR_ERROR_TYPE_RECOVERY 3
/**
* struct cam_req_mgr_error_msg
diff --git a/include/uapi/scsi/ufs/ufs.h b/include/uapi/scsi/ufs/ufs.h
index cd82b760bd92..e6a91030309f 100644
--- a/include/uapi/scsi/ufs/ufs.h
+++ b/include/uapi/scsi/ufs/ufs.h
@@ -36,8 +36,12 @@ enum attr_idn {
QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F,
QUERY_ATTR_IDN_CNTX_CONF = 0x10,
QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11,
+ QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME = 0x17,
};
+#define QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME \
+ QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME
+
#define QUERY_ATTR_IDN_BOOT_LU_EN_MAX 0x02
/* Descriptor idn for Query requests */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index aa035154bb72..df007c474778 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1463,7 +1463,7 @@ static struct cpuhp_step cpuhp_ap_states[] = {
},
[CPUHP_AP_PERF_ONLINE] = {
.name = "perf:online",
- .startup.single = perf_event_init_cpu,
+ .startup.single = perf_event_restart_events,
.teardown.single = perf_event_exit_cpu,
},
[CPUHP_AP_WORKQUEUE_ONLINE] = {
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index af9159a3bc9b..2714a17c80a9 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -847,6 +847,20 @@ void rebuild_sched_domains(void)
put_online_cpus();
}
+static int update_cpus_allowed(struct cpuset *cs, struct task_struct *p,
+ const struct cpumask *new_mask)
+{
+ int ret;
+
+ if (cpumask_subset(&p->cpus_requested, cs->cpus_requested)) {
+ ret = set_cpus_allowed_ptr(p, &p->cpus_requested);
+ if (!ret)
+ return ret;
+ }
+
+ return set_cpus_allowed_ptr(p, new_mask);
+}
+
/**
* update_tasks_cpumask - Update the cpumasks of tasks in the cpuset.
* @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
@@ -862,7 +876,7 @@ static void update_tasks_cpumask(struct cpuset *cs)
css_task_iter_start(&cs->css, &it);
while ((task = css_task_iter_next(&it)))
- set_cpus_allowed_ptr(task, cs->effective_cpus);
+ update_cpus_allowed(cs, task, cs->effective_cpus);
css_task_iter_end(&it);
}
@@ -1545,7 +1559,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
* can_attach beforehand should guarantee that this doesn't
* fail. TODO: have a better way to handle failure here
*/
- WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
+ WARN_ON_ONCE(update_cpus_allowed(cs, task, cpus_attach));
cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
cpuset_update_task_spread_flag(cs, task);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6be8ea2fb116..8dd675001654 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2315,6 +2315,23 @@ static void ctx_resched(struct perf_cpu_context *cpuctx,
perf_pmu_enable(cpuctx->ctx.pmu);
}
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static LIST_HEAD(dormant_event_list);
+static DEFINE_SPINLOCK(dormant_event_list_lock);
+
+static void perf_prepare_install_in_context(struct perf_event *event)
+{
+ spin_lock(&dormant_event_list_lock);
+ if (event->state == PERF_EVENT_STATE_DORMANT)
+ goto out;
+
+ event->state = PERF_EVENT_STATE_DORMANT;
+ list_add_tail(&event->dormant_event_entry, &dormant_event_list);
+out:
+ spin_unlock(&dormant_event_list_lock);
+}
+#endif
+
/*
* Cross CPU call to install and enable a performance event
*
@@ -2460,6 +2477,34 @@ again:
raw_spin_unlock_irq(&ctx->lock);
}
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+static void perf_deferred_install_in_context(int cpu)
+{
+ struct perf_event *event, *tmp;
+ struct perf_event_context *ctx;
+
+ spin_lock(&dormant_event_list_lock);
+ list_for_each_entry_safe(event, tmp, &dormant_event_list,
+ dormant_event_entry) {
+ if (cpu != event->cpu)
+ continue;
+
+ list_del(&event->dormant_event_entry);
+ event->state = PERF_EVENT_STATE_INACTIVE;
+ spin_unlock(&dormant_event_list_lock);
+
+ ctx = event->ctx;
+
+ mutex_lock(&ctx->mutex);
+ perf_install_in_context(ctx, event, cpu);
+ mutex_unlock(&ctx->mutex);
+
+ spin_lock(&dormant_event_list_lock);
+ }
+ spin_unlock(&dormant_event_list_lock);
+}
+#endif
+
/*
* Put a event into inactive state and update time fields.
* Enabling the leader of a group effectively enables all
@@ -4277,14 +4322,6 @@ static void put_event(struct perf_event *event)
}
/*
- * Maintain a zombie list to collect all the zombie events
- */
-#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-static LIST_HEAD(zombie_list);
-static DEFINE_SPINLOCK(zombie_list_lock);
-#endif
-
-/*
* Kill an event dead; while event:refcount will preserve the event
* object, it will not preserve its functionality. Once the last 'user'
* gives up the object, we'll destroy the thing.
@@ -4294,23 +4331,12 @@ static int __perf_event_release_kernel(struct perf_event *event)
struct perf_event_context *ctx = event->ctx;
struct perf_event *child, *tmp;
- /*
- * If the cpu associated to this event is offline, set the event as a
- * zombie event. The cleanup of the cpu would be done if the CPU is
- * back online.
- */
#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
- if (event->cpu != -1 && per_cpu(is_hotplugging, event->cpu)) {
- if (event->state == PERF_EVENT_STATE_ZOMBIE)
- return 0;
-
- event->state = PERF_EVENT_STATE_ZOMBIE;
-
- spin_lock(&zombie_list_lock);
- list_add_tail(&event->zombie_entry, &zombie_list);
- spin_unlock(&zombie_list_lock);
-
- return 0;
+ if (event->cpu != -1) {
+ spin_lock(&dormant_event_list_lock);
+ if (event->state == PERF_EVENT_STATE_DORMANT)
+ list_del(&event->dormant_event_entry);
+ spin_unlock(&dormant_event_list_lock);
}
#endif
@@ -4627,6 +4653,15 @@ perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct perf_event_context *ctx;
int ret;
+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
+ spin_lock(&dormant_event_list_lock);
+ if (event->state == PERF_EVENT_STATE_DORMANT) {
+ spin_unlock(&dormant_event_list_lock);
+ return 0;
+ }
+ spin_unlock(&dormant_event_list_lock);
+#endif
+
ctx = perf_event_ctx_lock(event);
ret = __perf_read(event, buf, count);
perf_event_ctx_unlock(event, ctx);
@@ -9455,13 +9490,13 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
mutex_init(&event->child_mutex);
INIT_LIST_HEAD(&event->child_list);
+ INIT_LIST_HEAD(&event->dormant_event_entry);
INIT_LIST_HEAD(&event->group_entry);
INIT_LIST_HEAD(&event->event_entry);
INIT_LIST_HEAD(&event->sibling_list);
INIT_LIST_HEAD(&event->rb_entry);
INIT_LIST_HEAD(&event->active_entry);
INIT_LIST_HEAD(&event->addr_filters.list);
- INIT_LIST_HEAD(&event->zombie_entry);
INIT_HLIST_NODE(&event->hlist_entry);
@@ -11114,111 +11149,27 @@ int perf_event_init_cpu(unsigned int cpu)
}
#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-static void
-check_hotplug_start_event(struct perf_event *event)
-{
- if (event->pmu->events_across_hotplug &&
- event->attr.type == PERF_TYPE_SOFTWARE &&
- event->pmu->start)
- event->pmu->start(event, 0);
-}
-
-static void perf_event_zombie_cleanup(unsigned int cpu)
+int perf_event_restart_events(unsigned int cpu)
{
- struct perf_event *event, *tmp;
-
- spin_lock(&zombie_list_lock);
-
- list_for_each_entry_safe(event, tmp, &zombie_list, zombie_entry) {
- if (event->cpu != cpu)
- continue;
-
- list_del(&event->zombie_entry);
- spin_unlock(&zombie_list_lock);
-
- /*
- * The detachment of the event with the
- * PMU expects it to be in an active state
- */
- event->state = PERF_EVENT_STATE_ACTIVE;
- __perf_event_release_kernel(event);
-
- spin_lock(&zombie_list_lock);
- }
-
- spin_unlock(&zombie_list_lock);
-}
-
-static int perf_event_start_swevents(unsigned int cpu)
-{
- struct perf_event_context *ctx;
- struct pmu *pmu;
- struct perf_event *event;
- int idx;
-
mutex_lock(&pmus_lock);
- perf_event_zombie_cleanup(cpu);
-
- idx = srcu_read_lock(&pmus_srcu);
- list_for_each_entry_rcu(pmu, &pmus, entry) {
- ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
- mutex_lock(&ctx->mutex);
- raw_spin_lock(&ctx->lock);
- list_for_each_entry(event, &ctx->event_list, event_entry)
- check_hotplug_start_event(event);
- raw_spin_unlock(&ctx->lock);
- mutex_unlock(&ctx->mutex);
- }
- srcu_read_unlock(&pmus_srcu, idx);
per_cpu(is_hotplugging, cpu) = false;
+ perf_deferred_install_in_context(cpu);
mutex_unlock(&pmus_lock);
return 0;
}
-/*
- * If keeping events across hotplugging is supported, do not
- * remove the event list so event lives beyond CPU hotplug.
- * The context is exited via an fd close path when userspace
- * is done and the target CPU is online. If software clock
- * event is active, then stop hrtimer associated with it.
- * Start the timer when the CPU comes back online.
- */
-static void
-check_hotplug_remove_from_context(struct perf_event *event,
- struct perf_cpu_context *cpuctx,
- struct perf_event_context *ctx)
-{
- if (event->pmu->events_across_hotplug &&
- event->attr.type == PERF_TYPE_SOFTWARE &&
- event->pmu->stop)
- event->pmu->stop(event, PERF_EF_UPDATE);
- else if (!event->pmu->events_across_hotplug)
- __perf_remove_from_context(event, cpuctx,
- ctx, (void *)DETACH_GROUP);
-}
-
-static void __perf_event_exit_context(void *__info)
-{
- struct perf_event_context *ctx = __info;
- struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
- struct perf_event *event;
-
- raw_spin_lock(&ctx->lock);
- list_for_each_entry(event, &ctx->event_list, event_entry)
- check_hotplug_remove_from_context(event, cpuctx, ctx);
- raw_spin_unlock(&ctx->lock);
-}
-
static void perf_event_exit_cpu_context(int cpu)
{
struct perf_cpu_context *cpuctx;
struct perf_event_context *ctx;
unsigned long flags;
+ struct perf_event *event, *event_tmp;
struct pmu *pmu;
int idx;
idx = srcu_read_lock(&pmus_srcu);
+ per_cpu(is_hotplugging, cpu) = true;
list_for_each_entry_rcu(pmu, &pmus, entry) {
cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
ctx = &cpuctx->ctx;
@@ -11233,7 +11184,12 @@ static void perf_event_exit_cpu_context(int cpu)
}
mutex_lock(&ctx->mutex);
- smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
+ list_for_each_entry_safe(event, event_tmp, &ctx->event_list,
+ event_entry) {
+ perf_remove_from_context(event, DETACH_GROUP);
+ if (event->pmu->events_across_hotplug)
+ perf_prepare_install_in_context(event);
+ }
mutex_unlock(&ctx->mutex);
}
srcu_read_unlock(&pmus_srcu, idx);
@@ -11246,8 +11202,8 @@ static void perf_event_exit_cpu_context(int cpu) { }
int perf_event_exit_cpu(unsigned int cpu)
{
+
mutex_lock(&pmus_lock);
- per_cpu(is_hotplugging, cpu) = true;
perf_event_exit_cpu_context(cpu);
mutex_unlock(&pmus_lock);
return 0;
@@ -11292,25 +11248,6 @@ static struct notifier_block perf_event_idle_nb = {
.notifier_call = event_idle_notif,
};
-#ifdef CONFIG_HOTPLUG_CPU
-static int perf_cpu_hp_init(void)
-{
- int ret;
-
- ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ONLINE,
- "PERF/CORE/CPUHP_AP_PERF_ONLINE",
- perf_event_start_swevents,
- perf_event_exit_cpu);
- if (ret)
- pr_err("CPU hotplug notifier for perf core could not be registered: %d\n",
- ret);
-
- return ret;
-}
-#else
-static int perf_cpu_hp_init(void) { return 0; }
-#endif
-
void __init perf_event_init(void)
{
int ret, cpu;
@@ -11337,8 +11274,6 @@ void __init perf_event_init(void)
perf_event_init_cpu(smp_processor_id());
idle_notifier_register(&perf_event_idle_nb);
register_reboot_notifier(&perf_reboot_notifier);
- ret = perf_cpu_hp_init();
- WARN(ret, "core perf_cpu_hp_init() failed with: %d", ret);
ret = init_hw_breakpoint();
WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f03942c9b2dc..e9bed0bd202d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5019,6 +5019,9 @@ again:
retval = -EINVAL;
}
+ if (!retval && !(p->flags & PF_KTHREAD))
+ cpumask_and(&p->cpus_requested, in_mask, cpu_possible_mask);
+
out_free_new_mask:
free_cpumask_var(new_mask);
out_free_cpus_allowed:
@@ -8146,6 +8149,7 @@ void __init sched_init_smp(void)
/* Move init over to a non-isolated CPU */
if (set_cpus_allowed_ptr(current, non_isolated_cpus) < 0)
BUG();
+ cpumask_copy(&current->cpus_requested, cpu_possible_mask);
sched_init_granularity();
free_cpumask_var(non_isolated_cpus);
diff --git a/lib/qmi_encdec.c b/lib/qmi_encdec.c
index d7221d898238..2808f7b72e3f 100644
--- a/lib/qmi_encdec.c
+++ b/lib/qmi_encdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2019 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -706,8 +706,8 @@ static int qmi_decode_string_elem(struct elem_info *ei_array, void *buf_dst,
decoded_bytes += rc;
}
- if (string_len > temp_ei->elem_len) {
- pr_err("%s: String len %d > Max Len %d\n",
+ if (string_len >= temp_ei->elem_len) {
+ pr_err("%s: String len %d >= Max Len %d\n",
__func__, string_len, temp_ei->elem_len);
return -ETOOSMALL;
} else if (string_len > tlv_len) {
diff --git a/mm/memory.c b/mm/memory.c
index ccf1a6b9f7e1..b8f1279e3728 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1971,7 +1971,7 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
unsigned long end = addr + size;
int err;
- if (WARN_ON(addr >= end))
+ if (WARN_ON(addr >= end - 1))
return -EINVAL;
pgd = pgd_offset(mm, addr);
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 7c1b14868313..8e471bec64c8 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -25,20 +25,20 @@ country AE: DFS-ETSI
country AF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country AI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country AL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -49,8 +49,8 @@ country AM: DFS-ETSI
country AN: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -73,8 +73,8 @@ country AS: DFS-FCC
country AT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -92,8 +92,8 @@ country AU: DFS-FCC
country AW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country AZ: DFS-ETSI
@@ -103,8 +103,8 @@ country AZ: DFS-ETSI
country BA: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -120,8 +120,8 @@ country BD:
country BE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -136,8 +136,8 @@ country BF: DFS-FCC
country BG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -150,8 +150,8 @@ country BH:
country BL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country BM: DFS-FCC
@@ -192,14 +192,14 @@ country BS: DFS-FCC
country BT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country BY: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country BZ:
@@ -226,8 +226,8 @@ country CF: DFS-FCC
country CH: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -280,8 +280,8 @@ country CX: DFS-FCC
country CY: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -291,8 +291,8 @@ country CY: DFS-ETSI
# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
country CZ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -306,8 +306,8 @@ country CZ: DFS-ETSI
country DE: DFS-ETSI
# entries 279004 and 280006
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -315,8 +315,8 @@ country DE: DFS-ETSI
country DK: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -351,8 +351,8 @@ country EC: DFS-FCC
country EE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -365,8 +365,8 @@ country EG: DFS-ETSI
country ES: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -374,14 +374,14 @@ country ES: DFS-ETSI
country ET: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country FI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -396,8 +396,8 @@ country FM: DFS-FCC
country FR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -405,8 +405,8 @@ country FR: DFS-ETSI
country GB: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -426,8 +426,8 @@ country GE: DFS-ETSI
country GF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -440,26 +440,26 @@ country GH: DFS-FCC
country GI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GP: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -467,8 +467,8 @@ country GR: DFS-ETSI
country GT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country GU: DFS-FCC
@@ -503,8 +503,8 @@ country HN:
country HR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -519,8 +519,8 @@ country HT: DFS-FCC
country HU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -533,8 +533,8 @@ country ID:
country IE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -547,21 +547,23 @@ country IL: DFS-ETSI
# 60 gHz band channels 1-4, base on Etsi En 302 567
(57000 - 66000 @ 2160), (40)
-country IN:
- (2402 - 2482 @ 40), (20)
- (5170 - 5330 @ 160), (23)
- (5735 - 5835 @ 80), (33)
+country IN: DFS-ETSI
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (30), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5875 @ 80), (30)
country IQ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country IS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -569,8 +571,8 @@ country IS: DFS-ETSI
country IT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -593,10 +595,10 @@ country JO:
(57000 - 66000 @ 2160), (40)
country JP: DFS-JP
- (2402 - 2482 @ 40), (20)
+ (2402 - 2482 @ 40), (23)
(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
- (5250 - 5330 @ 80), (26), DFS, AUTO-BW, NO-OUTDOOR
- (5490 - 5710 @ 160), (26), DFS
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
+ (5490 - 5710 @ 160), (23), DFS
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -608,8 +610,8 @@ country KE: DFS-ETSI
country KH: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country KN: DFS-FCC
@@ -660,8 +662,8 @@ country LC: DFS-FCC
country LI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -676,14 +678,14 @@ country LK: DFS-FCC
country LS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country LT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -691,8 +693,8 @@ country LT: DFS-ETSI
country LU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -700,8 +702,8 @@ country LU: DFS-ETSI
country LV: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -716,29 +718,29 @@ country MA: DFS-ETSI
country MC: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country MD: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country ME: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country MF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country MH: DFS-FCC
@@ -750,8 +752,8 @@ country MH: DFS-FCC
country MK: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -778,21 +780,21 @@ country MP: DFS-FCC
country MQ: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
country MR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country MT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -800,8 +802,8 @@ country MT: DFS-ETSI
country MU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -813,8 +815,8 @@ country MV: DFS-ETSI
country MW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country MX: DFS-FCC
@@ -858,8 +860,8 @@ country NI: DFS-FCC
country NL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -867,8 +869,8 @@ country NL: DFS-ETSI
country NO: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -890,8 +892,8 @@ country NZ: DFS-FCC
country OM: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country PA:
@@ -910,8 +912,8 @@ country PE: DFS-FCC
country PF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -937,8 +939,8 @@ country PK:
country PL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -946,8 +948,8 @@ country PL: DFS-ETSI
country PM: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -967,8 +969,8 @@ country PS: DFS-FCC
country PT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -999,14 +1001,14 @@ country QA: DFS-ETSI
country RE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country RO: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1016,8 +1018,8 @@ country RO: DFS-ETSI
# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
country RS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1047,8 +1049,8 @@ country SA: DFS-ETSI
country SE: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1065,8 +1067,8 @@ country SG: DFS-FCC
country SI: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1074,8 +1076,8 @@ country SI: DFS-ETSI
country SK: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
@@ -1089,8 +1091,8 @@ country SN:
country SR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country SV: DFS-FCC
@@ -1108,14 +1110,14 @@ country TC: DFS-FCC
country TD: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country TG: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 40), (23)
- (5250 - 5330 @ 40), (23), DFS
+ (5170 - 5250 @ 40), (23), NO-OUTDOOR
+ (5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR
(5490 - 5710 @ 40), (30), DFS
country TH: DFS-FCC
@@ -1134,8 +1136,8 @@ country TN: DFS-ETSI
country TR: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -1210,8 +1212,8 @@ country UZ: DFS-ETSI
country VC: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5730 @ 160), (30), DFS
(5735 - 5875 @ 80), (14)
@@ -1246,14 +1248,14 @@ country VU: DFS-FCC
country WF: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country WS: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 40), (23)
- (5250 - 5330 @ 40), (23), DFS
+ (5170 - 5250 @ 40), (23), NO-OUTDOOR
+ (5250 - 5330 @ 40), (23), DFS, NO-OUTDOOR
(5490 - 5710 @ 40), (30), DFS
country XA: DFS-JP
@@ -1268,8 +1270,8 @@ country YE:
country YT: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
country ZA: DFS-FCC
@@ -1283,6 +1285,6 @@ country ZA: DFS-FCC
country ZW: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW, NO-OUTDOOR
(5490 - 5710 @ 160), (30), DFS
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0534378309ff..409662fdc74c 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2618,7 +2618,7 @@ sub process {
$sig_nospace =~ s/\s//g;
$sig_nospace = lc($sig_nospace);
if (defined $signatures{$sig_nospace}) {
- WARN("BAD_SIGN_OFF",
+ WARN("DUPLICATE_SIGN_OFF",
"Duplicate signature\n" . $herecurr);
} else {
$signatures{$sig_nospace} = 1;
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 8a0e0af1c39a..76fb91c57264 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -55,7 +55,7 @@ def interpret_warning(line):
line = line.rstrip('\n')
m = warning_re.match(line)
if m and m.group(2) not in allowed_warnings:
- print "error, forbidden warning:", m.group(2)
+ print >> sys.stderr, "error, forbidden warning:", m.group(2)
# If there is a warning, remove any object if it exists.
if ofile:
@@ -80,17 +80,17 @@ def run_gcc():
try:
proc = subprocess.Popen(args, stderr=subprocess.PIPE)
for line in proc.stderr:
- print line,
+ print >> sys.stderr, line,
interpret_warning(line)
result = proc.wait()
except OSError as e:
result = e.errno
if result == errno.ENOENT:
- print args[0] + ':',e.strerror
- print 'Is your PATH set correctly?'
+ print >> sys.stderr, args[0] + ':',e.strerror
+ print >> sys.stderr, 'Is your PATH set correctly?'
else:
- print ' '.join(args), str(e)
+ print >> sys.stderr, ' '.join(args), str(e)
return result