Loading Documentation/devicetree/bindings/media/video/msm-vfe.txt +124 −55 Original line number Diff line number Diff line * Qualcomm MSM VFE Required properties: - cell-index: vfe hardware core index Required properties for parent node: - compatible : - "qcom,vfe" - #address-cells : Number of address related values in the reg field - #size-cells : Number of size related values in the reg field - ranges: How the register offsets for child translate to parent. Required properties for child node: - cell-index: vfe hardware core index - compatible : - "qcom,vfe32" - "qcom,vfe40" - "qcom,vfe44" - "qcom,vfe46" - "qcom,vfe47" - reg : offset and length of the register set for the device for the vfe operating in compatible mode. for the vfe operating in compatible mode. For parent node, add union of all registers for both vfe. - reg-names : should specify relevant names to each reg property defined. Only needed for child node. - "vfe" - Required. - "vfe_vbif" - Optional for "vfe32". Required for "vfe40". - interrupts : should contain the vfe interrupt. Loading Loading @@ -37,11 +47,69 @@ Required properties: Example: qcom,vfe@0xfda10000 { cell-index = <0>; qcom,vfe { compatible = "qcom,vfe"; #address-cells = <1>; #size-cells = <1>; vfe0: qcom,vfe0@fda10000 { cell-index = <0>; compatible = "qcom,vfe44"; reg = <0xfda10000 0x1000>; reg-names = "vfe"; <0xfda40000 0x200>; reg-names = "vfe", "vfe_vbif"; interrupts = <0 57 0>; interrupt-names = "vfe"; vdd-supply = <&gdsc_vfe>; qos-entries = <8>; qos-regs = <0x2C4 0x2C8 0x2CC 0x2D0 0x2D4 0x2D8 0x2DC 0x2E0>; qos-settings = <0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0x0002AAAA>; qos-v2-settings = <0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0x0001AAA9>; qos-v3-settings = <0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0x0001AAA9>; vbif-entries = <17>; vbif-regs = <0x4 0xB0 0xB4 0xB8 0xC0 0xC4 0xC8 0xD0 0xD4 0xD8 0xDC 0xF0 0x178 0x17C 0x124 0x160 0x164>; vbif-settings = <0x1 0x01010101 0x01010101 0x10010110 0x10101010 0x10101010 0x10101010 0x00001010 0x00001010 0x00000707 0x00000707 0x00000030 0x00000FFF 0x0FFF0FFF 0x00000001 0x22222222 0x00002222>; vbif-v2-entries = <16>; vbif-v2-regs = <0x4 0xB0 0xB4 0xB8 0xC0 0xC4 0xC8 0xD0 0xD4 0xD8 0xF0 0x178 0x17C 0x124 0x160 0x164>; vbif-v2-settings = <0x1 0x10101010 0x10101010 0x10101010 0x10101010 0x10101010 0x10101010 0x00000010 0x00000010 0x00000707 0x00000010 0x00000FFF 0x0FFF0FFF 0x00000003 0x22222222 0x00002222>; ds-entries = <17>; ds-regs = <0x988 0x98C 0x990 0x994 0x998 0x99C 0x9A0 0x9A4 0x9A8 0x9AC 0x9B0 0x9B4 0x9B8 0x9BC 0x9C0 0x9C4 0x9C8>; ds-settings = <0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x00000103>; max-clk-nominal = <465000000>; max-clk-turbo = <600000000>; }; vfe1: qcom,vfe1@fda14000 { cell-index = <1>; compatible = "qcom,vfe44"; reg = <0xfda14000 0x1000>; <0xfda40000 0x200>; reg-names = "vfe", "vfe_vbif"; interrupts = <0 58 0>; interrupt-names = "vfe"; vdd-supply = <&gdsc_vfe>; Loading Loading @@ -87,6 +155,7 @@ Example: max-clk-nominal = <465000000>; max-clk-turbo = <600000000>; }; }; In version specific file one needs to move only entries that differ between SoC versions with same VFE HW version: Loading arch/arm/boot/dts/qcom/msm8996-camera.dtsi +149 −140 Original line number Diff line number Diff line Loading @@ -265,7 +265,13 @@ status = "ok"; }; qcom,vfe@a10000 { qcom,vfe { compatible = "qcom,vfe"; #address-cells = <1>; #size-cells = <1>; ranges; vfe0: qcom,vfe0@a10000 { cell-index = <0>; compatible = "qcom,vfe47"; reg = <0xa10000 0x4000>, Loading @@ -292,7 +298,8 @@ clock-names = "mmagic_ahb_clk", "mmssnoc_axi_clk", "camss_axi_clk", "camss_top_ahb_clk" , "camss_ahb_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_vbif_ahb_clk", "vfe_ahb_clk", "bus_clk", "vfe_stream_clk", "smmu_vfe_axi_clk"; qcom,clock-rates = <0 0 0 0 0 320000000 0 0 0 0 0 0 0>; Loading Loading @@ -336,7 +343,7 @@ max-clk-turbo = <600000000>; }; qcom,vfe@a14000 { vfe1: qcom,vfe1@a14000 { cell-index = <1>; compatible = "qcom,vfe47"; reg = <0xa14000 0x4000>, Loading @@ -363,7 +370,8 @@ clock-names = "mmagic_ahb_clk", "mmssnoc_axi_clk", "camss_axi_clk", "camss_top_ahb_clk" , "camss_ahb_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_vbif_ahb_clk", "vfe_ahb_clk", "bus_clk", "vfe_stream_clk", "smmu_vfe_axi_clk"; qcom,clock-rates = <0 0 0 0 0 320000000 0 0 0 0 0 0 0>; Loading Loading @@ -406,6 +414,7 @@ max-clk-nominal = <465000000>; max-clk-turbo = <600000000>; }; }; qcom,cam_smmu { compatible = "qcom,msm-cam-smmu"; Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.c +96 −35 Original line number Diff line number Diff line Loading @@ -36,33 +36,18 @@ #include "msm_isp32.h" static struct msm_sd_req_vb2_q vfe_vb2_ops; static struct msm_isp_buf_mgr vfe_buf_mgr; static struct msm_vfe_common_dev_data vfe_common_data; static const struct of_device_id msm_vfe_dt_match[] = { { .compatible = "qcom,vfe47", .data = &vfe47_hw_info, }, { .compatible = "qcom,vfe46", .data = &vfe46_hw_info, }, { .compatible = "qcom,vfe44", .data = &vfe44_hw_info, }, { .compatible = "qcom,vfe40", .data = &vfe40_hw_info, .compatible = "qcom,vfe", }, {} }; MODULE_DEVICE_TABLE(of, msm_vfe_dt_match); static const struct platform_device_id msm_vfe_dev_id[] = { {} }; #define MAX_OVERFLOW_COUNTERS 29 #define OVERFLOW_LENGTH 1024 #define OVERFLOW_BUFFER_LENGTH 64 Loading @@ -72,8 +57,10 @@ static struct msm_isp_buf_mgr vfe_buf_mgr; static struct dual_vfe_resource dualvfe; struct msm_isp_statistics stats; struct msm_isp_ub_info ub_info; static int msm_isp_enable_debugfs(struct vfe_device *vfe_dev, struct msm_isp_bw_req_info *isp_req_hist); static char *stats_str[MAX_OVERFLOW_COUNTERS] = { "imgmaster0_overflow_cnt", "imgmaster1_overflow_cnt", Loading Loading @@ -119,6 +106,7 @@ static int msm_isp_bw_request_history_idx; static char bw_request_history_buff[MAX_BW_HISTORY_BUFF_LEN]; static char ub_info_buffer[MAX_UB_INFO_BUFF_LEN]; static spinlock_t req_history_lock; static int vfe_debugfs_statistics_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; Loading Loading @@ -417,20 +405,88 @@ static long msm_isp_subdev_do_ioctl( } } static long msm_isp_subdev_fops_ioctl(struct file *file, unsigned int cmd, static struct v4l2_subdev_core_ops msm_vfe_v4l2_subdev_core_ops = { .ioctl = msm_isp_ioctl, .subscribe_event = msm_isp_subscribe_event, .unsubscribe_event = msm_isp_unsubscribe_event, }; static struct v4l2_subdev_ops msm_vfe_v4l2_subdev_ops = { .core = &msm_vfe_v4l2_subdev_core_ops, }; static struct v4l2_subdev_internal_ops msm_vfe_subdev_internal_ops = { .open = msm_isp_open_node, .close = msm_isp_close_node, }; static long msm_isp_v4l2_fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, msm_isp_subdev_do_ioctl); } static struct v4l2_file_operations msm_isp_v4l2_subdev_fops = { static struct v4l2_file_operations msm_isp_v4l2_fops = { #ifdef CONFIG_COMPAT .compat_ioctl32 = msm_isp_subdev_fops_ioctl, .compat_ioctl32 = msm_isp_v4l2_fops_ioctl, #endif .unlocked_ioctl = msm_isp_subdev_fops_ioctl .unlocked_ioctl = msm_isp_v4l2_fops_ioctl }; static int vfe_probe(struct platform_device *pdev) { struct vfe_parent_device *vfe_parent_dev; int rc = 0; struct device_node *node; struct platform_device *new_dev = NULL; const struct device_node *dt_node = pdev->dev.of_node; vfe_parent_dev = kzalloc(sizeof(struct vfe_parent_device), GFP_KERNEL); if (!vfe_parent_dev) { rc = -ENOMEM; goto end; } vfe_parent_dev->common_sd = kzalloc( sizeof(struct msm_vfe_common_subdev), GFP_KERNEL); if (!vfe_parent_dev->common_sd) { rc = -ENOMEM; goto probe_fail1; } vfe_parent_dev->common_sd->common_data = &vfe_common_data; memset(&vfe_common_data, 0, sizeof(vfe_common_data)); spin_lock_init(&vfe_common_data.common_dev_data_lock); for_each_available_child_of_node(dt_node, node) { new_dev = of_platform_device_create(node, NULL, &pdev->dev); if (!new_dev) { pr_err("Failed to create device %s\n", node->name); goto probe_fail2; } vfe_parent_dev->child_list[vfe_parent_dev->num_hw_sd++] = new_dev; new_dev->dev.platform_data = (void *)vfe_parent_dev->common_sd->common_data; pr_debug("%s: device creation done\n", __func__); } vfe_parent_dev->num_sd = vfe_parent_dev->num_hw_sd; vfe_parent_dev->pdev = pdev; return rc; probe_fail2: kfree(vfe_parent_dev->common_sd); probe_fail1: kfree(vfe_parent_dev); end: return rc; } int vfe_hw_probe(struct platform_device *pdev) { struct vfe_device *vfe_dev; /*struct msm_cam_subdev_info sd_info;*/ Loading @@ -456,10 +512,16 @@ static int vfe_probe(struct platform_device *pdev) rc = -ENOMEM; goto probe_fail2; } vfe_dev->common_data = (struct msm_vfe_common_dev_data *) pdev->dev.platform_data; if (pdev->dev.of_node) { of_property_read_u32((&pdev->dev)->of_node, of_property_read_u32(pdev->dev.of_node, "cell-index", &pdev->id); match_dev = of_match_device(msm_vfe_dt_match, &pdev->dev); match_dev = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); if (!match_dev) { pr_err("%s: No vfe hardware info\n", __func__); rc = -EINVAL; Loading Loading @@ -498,9 +560,9 @@ static int vfe_probe(struct platform_device *pdev) tasklet_init(&vfe_dev->vfe_tasklet, msm_isp_do_tasklet, (unsigned long)vfe_dev); v4l2_subdev_init(&vfe_dev->subdev.sd, vfe_dev->hw_info->subdev_ops); v4l2_subdev_init(&vfe_dev->subdev.sd, &msm_vfe_v4l2_subdev_ops); vfe_dev->subdev.sd.internal_ops = vfe_dev->hw_info->subdev_internal_ops; &msm_vfe_subdev_internal_ops; snprintf(vfe_dev->subdev.sd.name, ARRAY_SIZE(vfe_dev->subdev.sd.name), "vfe"); Loading @@ -526,12 +588,12 @@ static int vfe_probe(struct platform_device *pdev) goto probe_fail3; } msm_isp_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner; msm_isp_v4l2_subdev_fops.open = v4l2_subdev_fops.open; msm_isp_v4l2_subdev_fops.release = v4l2_subdev_fops.release; msm_isp_v4l2_subdev_fops.poll = v4l2_subdev_fops.poll; msm_isp_v4l2_fops.owner = v4l2_subdev_fops.owner; msm_isp_v4l2_fops.open = v4l2_subdev_fops.open; msm_isp_v4l2_fops.release = v4l2_subdev_fops.release; msm_isp_v4l2_fops.poll = v4l2_subdev_fops.poll; vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_subdev_fops; vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_fops; vfe_dev->buf_mgr = &vfe_buf_mgr; v4l2_subdev_notify(&vfe_dev->subdev.sd, Loading Loading @@ -568,7 +630,6 @@ static struct platform_driver vfe_driver = { .owner = THIS_MODULE, .of_match_table = msm_vfe_dt_match, }, .id_table = msm_vfe_dev_id, }; static int __init msm_vfe_init_module(void) Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.h +54 −3 Original line number Diff line number Diff line Loading @@ -65,6 +65,20 @@ struct vfe_device; struct msm_vfe_axi_stream; struct msm_vfe_stats_stream; #define VFE_SD_HW_MAX VFE_SD_COMMON struct msm_vfe_sof_info { uint32_t timestamp_ms; uint32_t mono_timestamp_ms; uint32_t frame_id; }; struct msm_vfe_dual_hw_ms_info { enum msm_vfe_dual_hw_ms_type dual_hw_ms_type; struct msm_vfe_sof_info *sof_info; uint8_t slave_id; }; struct vfe_subscribe_info { struct v4l2_fh *vfh; uint32_t active; Loading Loading @@ -259,8 +273,6 @@ struct msm_vfe_hardware_info { struct msm_vfe_ops vfe_ops; struct msm_vfe_axi_hardware_info *axi_hw_info; struct msm_vfe_stats_hardware_info *stats_hw_info; struct v4l2_subdev_internal_ops *subdev_internal_ops; struct v4l2_subdev_ops *subdev_ops; uint32_t dmi_reg_offset; }; Loading Loading @@ -388,6 +400,8 @@ struct msm_vfe_src_info { uint32_t last_updt_frm_id; uint32_t sof_counter_step; struct timeval time_stamp; enum msm_vfe_dual_hw_type dual_hw_type; struct msm_vfe_dual_hw_ms_info dual_hw_ms_info; }; struct msm_vfe_fetch_engine_info { Loading Loading @@ -495,7 +509,7 @@ struct msm_vfe_error_info { uint32_t error_mask1; uint32_t violation_status; uint32_t camif_status; uint8_t stream_framedrop_count[MAX_NUM_STREAM]; uint8_t stream_framedrop_count[VFE_AXI_SRC_MAX]; uint8_t stats_framedrop_count[MSM_ISP_STATS_MAX]; uint32_t info_dump_frame_count; uint32_t error_count; Loading Loading @@ -584,8 +598,35 @@ struct dual_vfe_resource { uint32_t wm_reload_mask[MAX_VFE]; }; struct msm_vfe_common_dev_data { spinlock_t common_dev_data_lock; enum msm_vfe_dual_hw_type dual_hw_type; struct msm_vfe_sof_info master_sof_info; uint8_t master_active; uint32_t sof_delta_threshold; /* Updated by Master */ uint32_t num_slave; uint32_t reserved_slave_mask; uint32_t slave_active_mask; struct msm_vfe_sof_info slave_sof_info[MS_NUM_SLAVE_MAX]; }; struct msm_vfe_common_subdev { /* parent reference */ struct vfe_parent_device *parent; /* Media Subdevice */ struct msm_sd_subdev *subdev; /* Buf Mgr */ struct msm_isp_buf_mgr *buf_mgr; /* Common Data */ struct msm_vfe_common_dev_data *common_data; }; struct vfe_device { struct platform_device *pdev; struct msm_vfe_common_dev_data *common_data; struct msm_sd_subdev subdev; struct resource *vfe_irq; struct resource *vfe_mem; Loading Loading @@ -657,4 +698,14 @@ struct vfe_device { unsigned long page_fault_addr; }; struct vfe_parent_device { struct platform_device *pdev; uint32_t num_sd; uint32_t num_hw_sd; struct platform_device *child_list[VFE_SD_HW_MAX]; struct msm_vfe_common_subdev *common_sd; }; int vfe_hw_probe(struct platform_device *pdev); #endif drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +41 −17 Original line number Diff line number Diff line Loading @@ -21,6 +21,11 @@ #include "msm.h" #include "msm_camera_io_util.h" static const struct platform_device_id msm_vfe32_dev_id[] = { {"msm_vfe32", (kernel_ulong_t) &vfe32_hw_info}, {} }; #define VFE32_BURST_LEN 2 #define VFE32_UB_SIZE 1024 #define VFE32_UB_SIZE_32KB 2048 Loading Loading @@ -1459,21 +1464,6 @@ static struct msm_vfe_stats_hardware_info msm_vfe32_stats_hw_info = { .num_stats_comp_mask = 0, }; static struct v4l2_subdev_core_ops msm_vfe32_subdev_core_ops = { .ioctl = msm_isp_ioctl, .subscribe_event = msm_isp_subscribe_event, .unsubscribe_event = msm_isp_unsubscribe_event, }; static struct v4l2_subdev_ops msm_vfe32_subdev_ops = { .core = &msm_vfe32_subdev_core_ops, }; static struct v4l2_subdev_internal_ops msm_vfe32_internal_ops = { .open = msm_isp_open_node, .close = msm_isp_close_node, }; struct msm_vfe_hardware_info vfe32_hw_info = { .num_iommu_ctx = 2, .num_iommu_secure_ctx = 0, Loading Loading @@ -1550,7 +1540,41 @@ struct msm_vfe_hardware_info vfe32_hw_info = { .dmi_reg_offset = 0x5A0, .axi_hw_info = &msm_vfe32_axi_hw_info, .stats_hw_info = &msm_vfe32_stats_hw_info, .subdev_ops = &msm_vfe32_subdev_ops, .subdev_internal_ops = &msm_vfe32_internal_ops, }; EXPORT_SYMBOL(vfe32_hw_info); static const struct of_device_id msm_vfe32_dt_match[] = { { .compatible = "qcom,vfe32", .data = &vfe32_hw_info, }, {} }; MODULE_DEVICE_TABLE(of, msm_vfe32_dt_match); static struct platform_driver vfe32_driver = { .probe = vfe_hw_probe, .driver = { .name = "msm_vfe32", .owner = THIS_MODULE, .of_match_table = msm_vfe32_dt_match, }, .id_table = msm_vfe32_dev_id, }; static int __init msm_vfe32_init_module(void) { return platform_driver_register(&vfe32_driver); } static void __exit msm_vfe32_exit_module(void) { platform_driver_unregister(&vfe32_driver); } module_init(msm_vfe32_init_module); module_exit(msm_vfe32_exit_module); MODULE_DESCRIPTION("MSM VFE32 driver"); MODULE_LICENSE("GPL v2"); Loading
Documentation/devicetree/bindings/media/video/msm-vfe.txt +124 −55 Original line number Diff line number Diff line * Qualcomm MSM VFE Required properties: - cell-index: vfe hardware core index Required properties for parent node: - compatible : - "qcom,vfe" - #address-cells : Number of address related values in the reg field - #size-cells : Number of size related values in the reg field - ranges: How the register offsets for child translate to parent. Required properties for child node: - cell-index: vfe hardware core index - compatible : - "qcom,vfe32" - "qcom,vfe40" - "qcom,vfe44" - "qcom,vfe46" - "qcom,vfe47" - reg : offset and length of the register set for the device for the vfe operating in compatible mode. for the vfe operating in compatible mode. For parent node, add union of all registers for both vfe. - reg-names : should specify relevant names to each reg property defined. Only needed for child node. - "vfe" - Required. - "vfe_vbif" - Optional for "vfe32". Required for "vfe40". - interrupts : should contain the vfe interrupt. Loading Loading @@ -37,11 +47,69 @@ Required properties: Example: qcom,vfe@0xfda10000 { cell-index = <0>; qcom,vfe { compatible = "qcom,vfe"; #address-cells = <1>; #size-cells = <1>; vfe0: qcom,vfe0@fda10000 { cell-index = <0>; compatible = "qcom,vfe44"; reg = <0xfda10000 0x1000>; reg-names = "vfe"; <0xfda40000 0x200>; reg-names = "vfe", "vfe_vbif"; interrupts = <0 57 0>; interrupt-names = "vfe"; vdd-supply = <&gdsc_vfe>; qos-entries = <8>; qos-regs = <0x2C4 0x2C8 0x2CC 0x2D0 0x2D4 0x2D8 0x2DC 0x2E0>; qos-settings = <0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0xAAAAAAAA 0x0002AAAA>; qos-v2-settings = <0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0x0001AAA9>; qos-v3-settings = <0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0xAAA9AAA9 0x0001AAA9>; vbif-entries = <17>; vbif-regs = <0x4 0xB0 0xB4 0xB8 0xC0 0xC4 0xC8 0xD0 0xD4 0xD8 0xDC 0xF0 0x178 0x17C 0x124 0x160 0x164>; vbif-settings = <0x1 0x01010101 0x01010101 0x10010110 0x10101010 0x10101010 0x10101010 0x00001010 0x00001010 0x00000707 0x00000707 0x00000030 0x00000FFF 0x0FFF0FFF 0x00000001 0x22222222 0x00002222>; vbif-v2-entries = <16>; vbif-v2-regs = <0x4 0xB0 0xB4 0xB8 0xC0 0xC4 0xC8 0xD0 0xD4 0xD8 0xF0 0x178 0x17C 0x124 0x160 0x164>; vbif-v2-settings = <0x1 0x10101010 0x10101010 0x10101010 0x10101010 0x10101010 0x10101010 0x00000010 0x00000010 0x00000707 0x00000010 0x00000FFF 0x0FFF0FFF 0x00000003 0x22222222 0x00002222>; ds-entries = <17>; ds-regs = <0x988 0x98C 0x990 0x994 0x998 0x99C 0x9A0 0x9A4 0x9A8 0x9AC 0x9B0 0x9B4 0x9B8 0x9BC 0x9C0 0x9C4 0x9C8>; ds-settings = <0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x44441111 0x00000103>; max-clk-nominal = <465000000>; max-clk-turbo = <600000000>; }; vfe1: qcom,vfe1@fda14000 { cell-index = <1>; compatible = "qcom,vfe44"; reg = <0xfda14000 0x1000>; <0xfda40000 0x200>; reg-names = "vfe", "vfe_vbif"; interrupts = <0 58 0>; interrupt-names = "vfe"; vdd-supply = <&gdsc_vfe>; Loading Loading @@ -87,6 +155,7 @@ Example: max-clk-nominal = <465000000>; max-clk-turbo = <600000000>; }; }; In version specific file one needs to move only entries that differ between SoC versions with same VFE HW version: Loading
arch/arm/boot/dts/qcom/msm8996-camera.dtsi +149 −140 Original line number Diff line number Diff line Loading @@ -265,7 +265,13 @@ status = "ok"; }; qcom,vfe@a10000 { qcom,vfe { compatible = "qcom,vfe"; #address-cells = <1>; #size-cells = <1>; ranges; vfe0: qcom,vfe0@a10000 { cell-index = <0>; compatible = "qcom,vfe47"; reg = <0xa10000 0x4000>, Loading @@ -292,7 +298,8 @@ clock-names = "mmagic_ahb_clk", "mmssnoc_axi_clk", "camss_axi_clk", "camss_top_ahb_clk" , "camss_ahb_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_vbif_ahb_clk", "vfe_ahb_clk", "bus_clk", "vfe_stream_clk", "smmu_vfe_axi_clk"; qcom,clock-rates = <0 0 0 0 0 320000000 0 0 0 0 0 0 0>; Loading Loading @@ -336,7 +343,7 @@ max-clk-turbo = <600000000>; }; qcom,vfe@a14000 { vfe1: qcom,vfe1@a14000 { cell-index = <1>; compatible = "qcom,vfe47"; reg = <0xa14000 0x4000>, Loading @@ -363,7 +370,8 @@ clock-names = "mmagic_ahb_clk", "mmssnoc_axi_clk", "camss_axi_clk", "camss_top_ahb_clk" , "camss_ahb_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_clk_src", "camss_vfe_clk", "camss_csi_vfe_clk", "vfe_vbif_ahb_clk", "vfe_ahb_clk", "bus_clk", "vfe_stream_clk", "smmu_vfe_axi_clk"; qcom,clock-rates = <0 0 0 0 0 320000000 0 0 0 0 0 0 0>; Loading Loading @@ -406,6 +414,7 @@ max-clk-nominal = <465000000>; max-clk-turbo = <600000000>; }; }; qcom,cam_smmu { compatible = "qcom,msm-cam-smmu"; Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.c +96 −35 Original line number Diff line number Diff line Loading @@ -36,33 +36,18 @@ #include "msm_isp32.h" static struct msm_sd_req_vb2_q vfe_vb2_ops; static struct msm_isp_buf_mgr vfe_buf_mgr; static struct msm_vfe_common_dev_data vfe_common_data; static const struct of_device_id msm_vfe_dt_match[] = { { .compatible = "qcom,vfe47", .data = &vfe47_hw_info, }, { .compatible = "qcom,vfe46", .data = &vfe46_hw_info, }, { .compatible = "qcom,vfe44", .data = &vfe44_hw_info, }, { .compatible = "qcom,vfe40", .data = &vfe40_hw_info, .compatible = "qcom,vfe", }, {} }; MODULE_DEVICE_TABLE(of, msm_vfe_dt_match); static const struct platform_device_id msm_vfe_dev_id[] = { {} }; #define MAX_OVERFLOW_COUNTERS 29 #define OVERFLOW_LENGTH 1024 #define OVERFLOW_BUFFER_LENGTH 64 Loading @@ -72,8 +57,10 @@ static struct msm_isp_buf_mgr vfe_buf_mgr; static struct dual_vfe_resource dualvfe; struct msm_isp_statistics stats; struct msm_isp_ub_info ub_info; static int msm_isp_enable_debugfs(struct vfe_device *vfe_dev, struct msm_isp_bw_req_info *isp_req_hist); static char *stats_str[MAX_OVERFLOW_COUNTERS] = { "imgmaster0_overflow_cnt", "imgmaster1_overflow_cnt", Loading Loading @@ -119,6 +106,7 @@ static int msm_isp_bw_request_history_idx; static char bw_request_history_buff[MAX_BW_HISTORY_BUFF_LEN]; static char ub_info_buffer[MAX_UB_INFO_BUFF_LEN]; static spinlock_t req_history_lock; static int vfe_debugfs_statistics_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; Loading Loading @@ -417,20 +405,88 @@ static long msm_isp_subdev_do_ioctl( } } static long msm_isp_subdev_fops_ioctl(struct file *file, unsigned int cmd, static struct v4l2_subdev_core_ops msm_vfe_v4l2_subdev_core_ops = { .ioctl = msm_isp_ioctl, .subscribe_event = msm_isp_subscribe_event, .unsubscribe_event = msm_isp_unsubscribe_event, }; static struct v4l2_subdev_ops msm_vfe_v4l2_subdev_ops = { .core = &msm_vfe_v4l2_subdev_core_ops, }; static struct v4l2_subdev_internal_ops msm_vfe_subdev_internal_ops = { .open = msm_isp_open_node, .close = msm_isp_close_node, }; static long msm_isp_v4l2_fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(file, cmd, arg, msm_isp_subdev_do_ioctl); } static struct v4l2_file_operations msm_isp_v4l2_subdev_fops = { static struct v4l2_file_operations msm_isp_v4l2_fops = { #ifdef CONFIG_COMPAT .compat_ioctl32 = msm_isp_subdev_fops_ioctl, .compat_ioctl32 = msm_isp_v4l2_fops_ioctl, #endif .unlocked_ioctl = msm_isp_subdev_fops_ioctl .unlocked_ioctl = msm_isp_v4l2_fops_ioctl }; static int vfe_probe(struct platform_device *pdev) { struct vfe_parent_device *vfe_parent_dev; int rc = 0; struct device_node *node; struct platform_device *new_dev = NULL; const struct device_node *dt_node = pdev->dev.of_node; vfe_parent_dev = kzalloc(sizeof(struct vfe_parent_device), GFP_KERNEL); if (!vfe_parent_dev) { rc = -ENOMEM; goto end; } vfe_parent_dev->common_sd = kzalloc( sizeof(struct msm_vfe_common_subdev), GFP_KERNEL); if (!vfe_parent_dev->common_sd) { rc = -ENOMEM; goto probe_fail1; } vfe_parent_dev->common_sd->common_data = &vfe_common_data; memset(&vfe_common_data, 0, sizeof(vfe_common_data)); spin_lock_init(&vfe_common_data.common_dev_data_lock); for_each_available_child_of_node(dt_node, node) { new_dev = of_platform_device_create(node, NULL, &pdev->dev); if (!new_dev) { pr_err("Failed to create device %s\n", node->name); goto probe_fail2; } vfe_parent_dev->child_list[vfe_parent_dev->num_hw_sd++] = new_dev; new_dev->dev.platform_data = (void *)vfe_parent_dev->common_sd->common_data; pr_debug("%s: device creation done\n", __func__); } vfe_parent_dev->num_sd = vfe_parent_dev->num_hw_sd; vfe_parent_dev->pdev = pdev; return rc; probe_fail2: kfree(vfe_parent_dev->common_sd); probe_fail1: kfree(vfe_parent_dev); end: return rc; } int vfe_hw_probe(struct platform_device *pdev) { struct vfe_device *vfe_dev; /*struct msm_cam_subdev_info sd_info;*/ Loading @@ -456,10 +512,16 @@ static int vfe_probe(struct platform_device *pdev) rc = -ENOMEM; goto probe_fail2; } vfe_dev->common_data = (struct msm_vfe_common_dev_data *) pdev->dev.platform_data; if (pdev->dev.of_node) { of_property_read_u32((&pdev->dev)->of_node, of_property_read_u32(pdev->dev.of_node, "cell-index", &pdev->id); match_dev = of_match_device(msm_vfe_dt_match, &pdev->dev); match_dev = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); if (!match_dev) { pr_err("%s: No vfe hardware info\n", __func__); rc = -EINVAL; Loading Loading @@ -498,9 +560,9 @@ static int vfe_probe(struct platform_device *pdev) tasklet_init(&vfe_dev->vfe_tasklet, msm_isp_do_tasklet, (unsigned long)vfe_dev); v4l2_subdev_init(&vfe_dev->subdev.sd, vfe_dev->hw_info->subdev_ops); v4l2_subdev_init(&vfe_dev->subdev.sd, &msm_vfe_v4l2_subdev_ops); vfe_dev->subdev.sd.internal_ops = vfe_dev->hw_info->subdev_internal_ops; &msm_vfe_subdev_internal_ops; snprintf(vfe_dev->subdev.sd.name, ARRAY_SIZE(vfe_dev->subdev.sd.name), "vfe"); Loading @@ -526,12 +588,12 @@ static int vfe_probe(struct platform_device *pdev) goto probe_fail3; } msm_isp_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner; msm_isp_v4l2_subdev_fops.open = v4l2_subdev_fops.open; msm_isp_v4l2_subdev_fops.release = v4l2_subdev_fops.release; msm_isp_v4l2_subdev_fops.poll = v4l2_subdev_fops.poll; msm_isp_v4l2_fops.owner = v4l2_subdev_fops.owner; msm_isp_v4l2_fops.open = v4l2_subdev_fops.open; msm_isp_v4l2_fops.release = v4l2_subdev_fops.release; msm_isp_v4l2_fops.poll = v4l2_subdev_fops.poll; vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_subdev_fops; vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_fops; vfe_dev->buf_mgr = &vfe_buf_mgr; v4l2_subdev_notify(&vfe_dev->subdev.sd, Loading Loading @@ -568,7 +630,6 @@ static struct platform_driver vfe_driver = { .owner = THIS_MODULE, .of_match_table = msm_vfe_dt_match, }, .id_table = msm_vfe_dev_id, }; static int __init msm_vfe_init_module(void) Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.h +54 −3 Original line number Diff line number Diff line Loading @@ -65,6 +65,20 @@ struct vfe_device; struct msm_vfe_axi_stream; struct msm_vfe_stats_stream; #define VFE_SD_HW_MAX VFE_SD_COMMON struct msm_vfe_sof_info { uint32_t timestamp_ms; uint32_t mono_timestamp_ms; uint32_t frame_id; }; struct msm_vfe_dual_hw_ms_info { enum msm_vfe_dual_hw_ms_type dual_hw_ms_type; struct msm_vfe_sof_info *sof_info; uint8_t slave_id; }; struct vfe_subscribe_info { struct v4l2_fh *vfh; uint32_t active; Loading Loading @@ -259,8 +273,6 @@ struct msm_vfe_hardware_info { struct msm_vfe_ops vfe_ops; struct msm_vfe_axi_hardware_info *axi_hw_info; struct msm_vfe_stats_hardware_info *stats_hw_info; struct v4l2_subdev_internal_ops *subdev_internal_ops; struct v4l2_subdev_ops *subdev_ops; uint32_t dmi_reg_offset; }; Loading Loading @@ -388,6 +400,8 @@ struct msm_vfe_src_info { uint32_t last_updt_frm_id; uint32_t sof_counter_step; struct timeval time_stamp; enum msm_vfe_dual_hw_type dual_hw_type; struct msm_vfe_dual_hw_ms_info dual_hw_ms_info; }; struct msm_vfe_fetch_engine_info { Loading Loading @@ -495,7 +509,7 @@ struct msm_vfe_error_info { uint32_t error_mask1; uint32_t violation_status; uint32_t camif_status; uint8_t stream_framedrop_count[MAX_NUM_STREAM]; uint8_t stream_framedrop_count[VFE_AXI_SRC_MAX]; uint8_t stats_framedrop_count[MSM_ISP_STATS_MAX]; uint32_t info_dump_frame_count; uint32_t error_count; Loading Loading @@ -584,8 +598,35 @@ struct dual_vfe_resource { uint32_t wm_reload_mask[MAX_VFE]; }; struct msm_vfe_common_dev_data { spinlock_t common_dev_data_lock; enum msm_vfe_dual_hw_type dual_hw_type; struct msm_vfe_sof_info master_sof_info; uint8_t master_active; uint32_t sof_delta_threshold; /* Updated by Master */ uint32_t num_slave; uint32_t reserved_slave_mask; uint32_t slave_active_mask; struct msm_vfe_sof_info slave_sof_info[MS_NUM_SLAVE_MAX]; }; struct msm_vfe_common_subdev { /* parent reference */ struct vfe_parent_device *parent; /* Media Subdevice */ struct msm_sd_subdev *subdev; /* Buf Mgr */ struct msm_isp_buf_mgr *buf_mgr; /* Common Data */ struct msm_vfe_common_dev_data *common_data; }; struct vfe_device { struct platform_device *pdev; struct msm_vfe_common_dev_data *common_data; struct msm_sd_subdev subdev; struct resource *vfe_irq; struct resource *vfe_mem; Loading Loading @@ -657,4 +698,14 @@ struct vfe_device { unsigned long page_fault_addr; }; struct vfe_parent_device { struct platform_device *pdev; uint32_t num_sd; uint32_t num_hw_sd; struct platform_device *child_list[VFE_SD_HW_MAX]; struct msm_vfe_common_subdev *common_sd; }; int vfe_hw_probe(struct platform_device *pdev); #endif
drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +41 −17 Original line number Diff line number Diff line Loading @@ -21,6 +21,11 @@ #include "msm.h" #include "msm_camera_io_util.h" static const struct platform_device_id msm_vfe32_dev_id[] = { {"msm_vfe32", (kernel_ulong_t) &vfe32_hw_info}, {} }; #define VFE32_BURST_LEN 2 #define VFE32_UB_SIZE 1024 #define VFE32_UB_SIZE_32KB 2048 Loading Loading @@ -1459,21 +1464,6 @@ static struct msm_vfe_stats_hardware_info msm_vfe32_stats_hw_info = { .num_stats_comp_mask = 0, }; static struct v4l2_subdev_core_ops msm_vfe32_subdev_core_ops = { .ioctl = msm_isp_ioctl, .subscribe_event = msm_isp_subscribe_event, .unsubscribe_event = msm_isp_unsubscribe_event, }; static struct v4l2_subdev_ops msm_vfe32_subdev_ops = { .core = &msm_vfe32_subdev_core_ops, }; static struct v4l2_subdev_internal_ops msm_vfe32_internal_ops = { .open = msm_isp_open_node, .close = msm_isp_close_node, }; struct msm_vfe_hardware_info vfe32_hw_info = { .num_iommu_ctx = 2, .num_iommu_secure_ctx = 0, Loading Loading @@ -1550,7 +1540,41 @@ struct msm_vfe_hardware_info vfe32_hw_info = { .dmi_reg_offset = 0x5A0, .axi_hw_info = &msm_vfe32_axi_hw_info, .stats_hw_info = &msm_vfe32_stats_hw_info, .subdev_ops = &msm_vfe32_subdev_ops, .subdev_internal_ops = &msm_vfe32_internal_ops, }; EXPORT_SYMBOL(vfe32_hw_info); static const struct of_device_id msm_vfe32_dt_match[] = { { .compatible = "qcom,vfe32", .data = &vfe32_hw_info, }, {} }; MODULE_DEVICE_TABLE(of, msm_vfe32_dt_match); static struct platform_driver vfe32_driver = { .probe = vfe_hw_probe, .driver = { .name = "msm_vfe32", .owner = THIS_MODULE, .of_match_table = msm_vfe32_dt_match, }, .id_table = msm_vfe32_dev_id, }; static int __init msm_vfe32_init_module(void) { return platform_driver_register(&vfe32_driver); } static void __exit msm_vfe32_exit_module(void) { platform_driver_unregister(&vfe32_driver); } module_init(msm_vfe32_init_module); module_exit(msm_vfe32_exit_module); MODULE_DESCRIPTION("MSM VFE32 driver"); MODULE_LICENSE("GPL v2");