Loading drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -98,6 +98,8 @@ struct msm_isp_buffer { struct timeval *tv; /* Indicates whether buffer is used as ping ot pong buffer */ uint32_t pingpong_bit; /* Indicates buffer is reconfig due to drop frame */ uint32_t is_drop_reconfig; /*Native buffer*/ struct list_head list; Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.c +69 −1 Original line number Diff line number Diff line Loading @@ -453,11 +453,69 @@ static long msm_isp_v4l2_fops_ioctl(struct file *file, unsigned int cmd, return video_usercopy(file, cmd, arg, msm_isp_subdev_do_ioctl); } static void isp_vma_open(struct vm_area_struct *vma) { pr_debug("%s: open called\n", __func__); } static void isp_vma_close(struct vm_area_struct *vma) { pr_debug("%s: close called\n", __func__); } static int isp_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct page *page; struct vfe_device *vfe_dev = vma->vm_private_data; struct isp_proc *isp_page = NULL; isp_page = vfe_dev->isp_page; pr_debug("%s: vfeid:%d u_virt_addr:0x%lx k_virt_addr:%pK\n", __func__, vfe_dev->pdev->id, vma->vm_start, (void *)isp_page); if (isp_page != NULL) { page = virt_to_page(isp_page); get_page(page); vmf->page = page; isp_page->kernel_sofid = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id; isp_page->vfeid = vfe_dev->pdev->id; } return 0; } static const struct vm_operations_struct isp_vm_ops = { .open = isp_vma_open, .close = isp_vma_close, .fault = isp_vma_fault, }; static int msm_isp_v4l2_fops_mmap(struct file *filep, struct vm_area_struct *vma) { int ret = -EINVAL; struct video_device *vdev = video_devdata(filep); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); vma->vm_ops = &isp_vm_ops; vma->vm_flags |= (unsigned long)(VM_DONTEXPAND | VM_DONTDUMP); vma->vm_private_data = vfe_dev; isp_vma_open(vma); ret = 0; pr_debug("%s: isp mmap is called vm_start: 0x%lx\n", __func__, vma->vm_start); return ret; } static struct v4l2_file_operations msm_isp_v4l2_fops = { #ifdef CONFIG_COMPAT .compat_ioctl32 = msm_isp_v4l2_fops_ioctl, #endif .unlocked_ioctl = msm_isp_v4l2_fops_ioctl .unlocked_ioctl = msm_isp_v4l2_fops_ioctl, .mmap = msm_isp_v4l2_fops_mmap }; static int vfe_set_common_data(struct platform_device *pdev) Loading Loading @@ -671,6 +729,8 @@ int vfe_hw_probe(struct platform_device *pdev) msm_isp_v4l2_fops.compat_ioctl32 = msm_isp_v4l2_fops_ioctl; #endif msm_isp_v4l2_fops.mmap = msm_isp_v4l2_fops_mmap; vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_fops; vfe_dev->buf_mgr = &vfe_buf_mgr; Loading @@ -687,6 +747,14 @@ int vfe_hw_probe(struct platform_device *pdev) msm_isp_enable_debugfs(vfe_dev, msm_isp_bw_request_history); vfe_dev->buf_mgr->init_done = 1; vfe_dev->vfe_open_cnt = 0; /*Allocate a page in kernel and map it to camera user process*/ vfe_dev->isp_page = (struct isp_proc *)get_zeroed_page(GFP_KERNEL); if (vfe_dev->isp_page == NULL) { pr_err("%s: no enough memory\n", __func__); rc = -ENOMEM; goto probe_fail3; } vfe_dev->isp_page->vfeid = vfe_dev->pdev->id; return rc; probe_fail3: Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.h +6 −0 Original line number Diff line number Diff line Loading @@ -759,6 +759,11 @@ struct msm_vfe_common_subdev { struct msm_vfe_common_dev_data *common_data; }; struct isp_proc { uint32_t kernel_sofid; uint32_t vfeid; }; struct vfe_device { /* Driver private data */ struct platform_device *pdev; Loading Loading @@ -842,6 +847,7 @@ struct vfe_device { uint32_t recovery_irq1_mask; /* total bandwidth per vfe */ uint64_t total_bandwidth; struct isp_proc *isp_page; }; struct vfe_parent_device { Loading drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +104 −34 Original line number Diff line number Diff line Loading @@ -719,13 +719,7 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, sof_info->stream_get_buf_fail_mask = 0; axi_data = &vfe_dev->axi_data; /* report that registers are not updated and return empty buffer for * controllable outputs */ if (!vfe_dev->reg_updated) { sof_info->regs_not_updated = vfe_dev->reg_update_requested; } for (i = 0; i < RDI_INTF_0; i++) { stream_info = msm_isp_get_stream_common_data(vfe_dev, i); Loading @@ -747,6 +741,12 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, if (stream_info->controllable_output && !vfe_dev->reg_updated) { if (stream_info->undelivered_request_cnt) { /*report that registers are not updated * and return empty buffer for controllable * outputs */ sof_info->regs_not_updated = !vfe_dev->reg_updated; pr_err("Drop frame no reg update\n"); if (msm_isp_drop_frame(vfe_dev, stream_info, ts, sof_info)) { Loading Loading @@ -933,6 +933,8 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, } if (frame_src == VFE_PIX_0) { vfe_dev->isp_page->kernel_sofid = vfe_dev->axi_data.src_info[frame_src].frame_id; if (!src_info->frame_id && !src_info->reg_update_frame_id && ((src_info->frame_id - Loading Loading @@ -1646,22 +1648,29 @@ static void msm_isp_reload_ping_pong_offset( } static int msm_isp_update_deliver_count(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_bit) struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_bit, struct msm_isp_buffer *done_buf) { int rc = 0; if (!stream_info->controllable_output) goto done; if (!stream_info->undelivered_request_cnt) { if (!stream_info->undelivered_request_cnt || (done_buf == NULL)) { pr_err_ratelimited("%s:%d error undelivered_request_cnt 0\n", __func__, __LINE__); rc = -EINVAL; goto done; } else { if ((done_buf->is_drop_reconfig == 1) && (stream_info->sw_ping_pong_bit == -1)) { goto done; } /*After wm reload, we get bufdone for ping buffer*/ if (stream_info->sw_ping_pong_bit == -1) stream_info->sw_ping_pong_bit = 0; if (done_buf->is_drop_reconfig != 1) stream_info->undelivered_request_cnt--; if (pingpong_bit != stream_info->sw_ping_pong_bit) { pr_err("%s:%d ping pong bit actual %d sw %d\n", Loading Loading @@ -1908,7 +1917,8 @@ int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev, } static int msm_isp_cfg_ping_pong_address( struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status) struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, struct msm_isp_buffer *buf) { int i; int j; Loading @@ -1917,7 +1927,6 @@ static int msm_isp_cfg_ping_pong_address( uint32_t buffer_size_byte = 0; int32_t word_per_line = 0; dma_addr_t paddr; struct msm_isp_buffer *buf = NULL; /* Isolate pingpong_bit from pingpong_status */ Loading @@ -1928,9 +1937,10 @@ static int msm_isp_cfg_ping_pong_address( if (stream_info->buf[!pingpong_bit]) { pr_err("stream %x buffer already set for pingpong %d\n", stream_info->stream_src, !pingpong_bit); return 0; return 1; } if (buf == NULL) buf = msm_isp_get_stream_buffer(vfe_dev, stream_info); if (!buf) { Loading Loading @@ -2165,6 +2175,7 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, struct msm_isp_bufq *bufq = NULL; uint32_t pingpong_bit; int vfe_idx; int rc = -1; if (!vfe_dev || !stream_info || !ts || !sof_info) { pr_err("%s %d vfe_dev %pK stream_info %pK ts %pK op_info %pK\n", Loading @@ -2181,18 +2192,43 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, pingpong_bit = (~(pingpong_status >> stream_info->wm[vfe_idx][0]) & 0x1); done_buf = stream_info->buf[pingpong_bit]; if (done_buf) { bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr, if (done_buf && (stream_info->composite_irq[MSM_ISP_COMP_IRQ_EPOCH] == 0)) { if ((stream_info->sw_ping_pong_bit != -1) && !vfe_dev->reg_updated) { rc = msm_isp_cfg_ping_pong_address( stream_info, ~pingpong_status, done_buf); if (rc < 0) { ISP_DBG("%s: Error configuring ping_pong\n", __func__); bufq = vfe_dev->buf_mgr->ops->get_bufq( vfe_dev->buf_mgr, done_buf->bufq_handle); if (!bufq) { spin_unlock_irqrestore(&stream_info->lock, flags); spin_unlock_irqrestore( &stream_info->lock, flags); pr_err("%s: Invalid bufq buf_handle %x\n", __func__, done_buf->bufq_handle); __func__, done_buf->bufq_handle); return -EINVAL; } sof_info->reg_update_fail_mask_ext |= (bufq->bufq_handle & 0xFF); } } /*Avoid Drop Frame and re-issue pingpong cfg*/ /*this notify is per ping and pong buffer*/ done_buf->is_drop_reconfig = 1; stream_info->current_framedrop_period = 1; /*Avoid Multiple request frames for single SOF*/ vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = false; if (stream_info->current_framedrop_period != stream_info->requested_framedrop_period) { msm_isp_cfg_framedrop_reg(stream_info); } } spin_unlock_irqrestore(&stream_info->lock, flags); /* if buf done will not come, we need to process it ourself */ Loading @@ -2201,6 +2237,8 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, /* no buf done come */ msm_isp_process_axi_irq_stream(vfe_dev, stream_info, pingpong_status, ts); if (done_buf) done_buf->is_drop_reconfig = 0; } return 0; } Loading Loading @@ -2505,7 +2543,7 @@ static int msm_isp_init_stream_ping_pong_reg( /* Set address for both PING & PO NG register */ rc = msm_isp_cfg_ping_pong_address( stream_info, VFE_PING_FLAG); stream_info, VFE_PING_FLAG, NULL); /* No buffer available on start is not error */ if (rc == -ENOMEM && stream_info->stream_type != BURST_STREAM) return 0; Loading @@ -2517,7 +2555,7 @@ static int msm_isp_init_stream_ping_pong_reg( if (stream_info->stream_type != BURST_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( stream_info, VFE_PONG_FLAG); stream_info, VFE_PONG_FLAG, NULL); /* No buffer available on start is not error */ if (rc == -ENOMEM) return 0; Loading Loading @@ -3516,7 +3554,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, if (stream_info->undelivered_request_cnt == 1) { rc = msm_isp_cfg_ping_pong_address(stream_info, VFE_PING_FLAG); VFE_PING_FLAG, NULL); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); stream_info->undelivered_request_cnt--; Loading Loading @@ -3549,10 +3587,10 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, * now. */ rc = msm_isp_cfg_ping_pong_address(stream_info, VFE_PONG_FLAG); VFE_PONG_FLAG, NULL); } else { rc = msm_isp_cfg_ping_pong_address( stream_info, pingpong_status); stream_info, pingpong_status, NULL); } if (rc) { stream_info->undelivered_request_cnt--; Loading @@ -3574,6 +3612,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, if (0 == rc) msm_isp_reset_framedrop(vfe_dev, stream_info); /*Avoid Multiple request frames for single SOF*/ vfe_dev->axi_data.src_info[frame_src].accept_frame = false; spin_unlock_irqrestore(&stream_info->lock, flags); return rc; Loading Loading @@ -4057,6 +4098,10 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, done_buf = stream_info->buf[pingpong_bit]; if (vfe_dev->buf_mgr->frameId_mismatch_recovery == 1) { if (done_buf) { if (done_buf->is_drop_reconfig == 1) done_buf->is_drop_reconfig = 0; } pr_err_ratelimited("%s: Mismatch Recovery in progress, drop frame!\n", __func__); spin_unlock_irqrestore(&stream_info->lock, flags); Loading @@ -4076,14 +4121,26 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, stream_info->frame_id++; stream_info->buf[pingpong_bit] = NULL; if (stream_info->controllable_output && (done_buf != NULL) && (stream_info->sw_ping_pong_bit == -1) && (done_buf->is_drop_reconfig == 1)) { /*When wm reloaded and corresponding reg_update fail * then buffer is reconfig as PING buffer. so, avoid * NULL assignment to PING buffer and eventually * next AXI_DONE or buf_done can be successful */ stream_info->buf[pingpong_bit] = done_buf; } if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( stream_info, pingpong_status); stream_info, pingpong_status, NULL); if (rc < 0) ISP_DBG("%s: Error configuring ping_pong\n", __func__); } else if (done_buf) { } else if (done_buf && (done_buf->is_drop_reconfig != 1)) { msm_isp_cfg_stream_scratch(stream_info, pingpong_status); } Loading @@ -4107,8 +4164,10 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, } rc = msm_isp_update_deliver_count(vfe_dev, stream_info, pingpong_bit); pingpong_bit, done_buf); if (rc) { if (done_buf->is_drop_reconfig == 1) done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); pr_err_ratelimited("%s:VFE%d get done buf fail\n", __func__, vfe_dev->pdev->id); Loading @@ -4117,18 +4176,29 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, return; } spin_unlock_irqrestore(&stream_info->lock, flags); if ((done_buf->frame_id != frame_id) && vfe_dev->axi_data.enable_frameid_recovery) { if (done_buf->is_drop_reconfig == 1) done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); msm_isp_handle_done_buf_frame_id_mismatch(vfe_dev, stream_info, done_buf, time_stamp, frame_id); return; } if (done_buf->is_drop_reconfig == 1) { /*When ping/pong buf is already reconfigured * then dont issue buf-done for current buffer */ done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); } else { spin_unlock_irqrestore(&stream_info->lock, flags); msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, time_stamp, frame_id); } } void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, Loading Loading
drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h +3 −1 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -98,6 +98,8 @@ struct msm_isp_buffer { struct timeval *tv; /* Indicates whether buffer is used as ping ot pong buffer */ uint32_t pingpong_bit; /* Indicates buffer is reconfig due to drop frame */ uint32_t is_drop_reconfig; /*Native buffer*/ struct list_head list; Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.c +69 −1 Original line number Diff line number Diff line Loading @@ -453,11 +453,69 @@ static long msm_isp_v4l2_fops_ioctl(struct file *file, unsigned int cmd, return video_usercopy(file, cmd, arg, msm_isp_subdev_do_ioctl); } static void isp_vma_open(struct vm_area_struct *vma) { pr_debug("%s: open called\n", __func__); } static void isp_vma_close(struct vm_area_struct *vma) { pr_debug("%s: close called\n", __func__); } static int isp_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct page *page; struct vfe_device *vfe_dev = vma->vm_private_data; struct isp_proc *isp_page = NULL; isp_page = vfe_dev->isp_page; pr_debug("%s: vfeid:%d u_virt_addr:0x%lx k_virt_addr:%pK\n", __func__, vfe_dev->pdev->id, vma->vm_start, (void *)isp_page); if (isp_page != NULL) { page = virt_to_page(isp_page); get_page(page); vmf->page = page; isp_page->kernel_sofid = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id; isp_page->vfeid = vfe_dev->pdev->id; } return 0; } static const struct vm_operations_struct isp_vm_ops = { .open = isp_vma_open, .close = isp_vma_close, .fault = isp_vma_fault, }; static int msm_isp_v4l2_fops_mmap(struct file *filep, struct vm_area_struct *vma) { int ret = -EINVAL; struct video_device *vdev = video_devdata(filep); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); vma->vm_ops = &isp_vm_ops; vma->vm_flags |= (unsigned long)(VM_DONTEXPAND | VM_DONTDUMP); vma->vm_private_data = vfe_dev; isp_vma_open(vma); ret = 0; pr_debug("%s: isp mmap is called vm_start: 0x%lx\n", __func__, vma->vm_start); return ret; } static struct v4l2_file_operations msm_isp_v4l2_fops = { #ifdef CONFIG_COMPAT .compat_ioctl32 = msm_isp_v4l2_fops_ioctl, #endif .unlocked_ioctl = msm_isp_v4l2_fops_ioctl .unlocked_ioctl = msm_isp_v4l2_fops_ioctl, .mmap = msm_isp_v4l2_fops_mmap }; static int vfe_set_common_data(struct platform_device *pdev) Loading Loading @@ -671,6 +729,8 @@ int vfe_hw_probe(struct platform_device *pdev) msm_isp_v4l2_fops.compat_ioctl32 = msm_isp_v4l2_fops_ioctl; #endif msm_isp_v4l2_fops.mmap = msm_isp_v4l2_fops_mmap; vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_fops; vfe_dev->buf_mgr = &vfe_buf_mgr; Loading @@ -687,6 +747,14 @@ int vfe_hw_probe(struct platform_device *pdev) msm_isp_enable_debugfs(vfe_dev, msm_isp_bw_request_history); vfe_dev->buf_mgr->init_done = 1; vfe_dev->vfe_open_cnt = 0; /*Allocate a page in kernel and map it to camera user process*/ vfe_dev->isp_page = (struct isp_proc *)get_zeroed_page(GFP_KERNEL); if (vfe_dev->isp_page == NULL) { pr_err("%s: no enough memory\n", __func__); rc = -ENOMEM; goto probe_fail3; } vfe_dev->isp_page->vfeid = vfe_dev->pdev->id; return rc; probe_fail3: Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.h +6 −0 Original line number Diff line number Diff line Loading @@ -759,6 +759,11 @@ struct msm_vfe_common_subdev { struct msm_vfe_common_dev_data *common_data; }; struct isp_proc { uint32_t kernel_sofid; uint32_t vfeid; }; struct vfe_device { /* Driver private data */ struct platform_device *pdev; Loading Loading @@ -842,6 +847,7 @@ struct vfe_device { uint32_t recovery_irq1_mask; /* total bandwidth per vfe */ uint64_t total_bandwidth; struct isp_proc *isp_page; }; struct vfe_parent_device { Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +104 −34 Original line number Diff line number Diff line Loading @@ -719,13 +719,7 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, sof_info->stream_get_buf_fail_mask = 0; axi_data = &vfe_dev->axi_data; /* report that registers are not updated and return empty buffer for * controllable outputs */ if (!vfe_dev->reg_updated) { sof_info->regs_not_updated = vfe_dev->reg_update_requested; } for (i = 0; i < RDI_INTF_0; i++) { stream_info = msm_isp_get_stream_common_data(vfe_dev, i); Loading @@ -747,6 +741,12 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, if (stream_info->controllable_output && !vfe_dev->reg_updated) { if (stream_info->undelivered_request_cnt) { /*report that registers are not updated * and return empty buffer for controllable * outputs */ sof_info->regs_not_updated = !vfe_dev->reg_updated; pr_err("Drop frame no reg update\n"); if (msm_isp_drop_frame(vfe_dev, stream_info, ts, sof_info)) { Loading Loading @@ -933,6 +933,8 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, } if (frame_src == VFE_PIX_0) { vfe_dev->isp_page->kernel_sofid = vfe_dev->axi_data.src_info[frame_src].frame_id; if (!src_info->frame_id && !src_info->reg_update_frame_id && ((src_info->frame_id - Loading Loading @@ -1646,22 +1648,29 @@ static void msm_isp_reload_ping_pong_offset( } static int msm_isp_update_deliver_count(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_bit) struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_bit, struct msm_isp_buffer *done_buf) { int rc = 0; if (!stream_info->controllable_output) goto done; if (!stream_info->undelivered_request_cnt) { if (!stream_info->undelivered_request_cnt || (done_buf == NULL)) { pr_err_ratelimited("%s:%d error undelivered_request_cnt 0\n", __func__, __LINE__); rc = -EINVAL; goto done; } else { if ((done_buf->is_drop_reconfig == 1) && (stream_info->sw_ping_pong_bit == -1)) { goto done; } /*After wm reload, we get bufdone for ping buffer*/ if (stream_info->sw_ping_pong_bit == -1) stream_info->sw_ping_pong_bit = 0; if (done_buf->is_drop_reconfig != 1) stream_info->undelivered_request_cnt--; if (pingpong_bit != stream_info->sw_ping_pong_bit) { pr_err("%s:%d ping pong bit actual %d sw %d\n", Loading Loading @@ -1908,7 +1917,8 @@ int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev, } static int msm_isp_cfg_ping_pong_address( struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status) struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, struct msm_isp_buffer *buf) { int i; int j; Loading @@ -1917,7 +1927,6 @@ static int msm_isp_cfg_ping_pong_address( uint32_t buffer_size_byte = 0; int32_t word_per_line = 0; dma_addr_t paddr; struct msm_isp_buffer *buf = NULL; /* Isolate pingpong_bit from pingpong_status */ Loading @@ -1928,9 +1937,10 @@ static int msm_isp_cfg_ping_pong_address( if (stream_info->buf[!pingpong_bit]) { pr_err("stream %x buffer already set for pingpong %d\n", stream_info->stream_src, !pingpong_bit); return 0; return 1; } if (buf == NULL) buf = msm_isp_get_stream_buffer(vfe_dev, stream_info); if (!buf) { Loading Loading @@ -2165,6 +2175,7 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, struct msm_isp_bufq *bufq = NULL; uint32_t pingpong_bit; int vfe_idx; int rc = -1; if (!vfe_dev || !stream_info || !ts || !sof_info) { pr_err("%s %d vfe_dev %pK stream_info %pK ts %pK op_info %pK\n", Loading @@ -2181,18 +2192,43 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, pingpong_bit = (~(pingpong_status >> stream_info->wm[vfe_idx][0]) & 0x1); done_buf = stream_info->buf[pingpong_bit]; if (done_buf) { bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr, if (done_buf && (stream_info->composite_irq[MSM_ISP_COMP_IRQ_EPOCH] == 0)) { if ((stream_info->sw_ping_pong_bit != -1) && !vfe_dev->reg_updated) { rc = msm_isp_cfg_ping_pong_address( stream_info, ~pingpong_status, done_buf); if (rc < 0) { ISP_DBG("%s: Error configuring ping_pong\n", __func__); bufq = vfe_dev->buf_mgr->ops->get_bufq( vfe_dev->buf_mgr, done_buf->bufq_handle); if (!bufq) { spin_unlock_irqrestore(&stream_info->lock, flags); spin_unlock_irqrestore( &stream_info->lock, flags); pr_err("%s: Invalid bufq buf_handle %x\n", __func__, done_buf->bufq_handle); __func__, done_buf->bufq_handle); return -EINVAL; } sof_info->reg_update_fail_mask_ext |= (bufq->bufq_handle & 0xFF); } } /*Avoid Drop Frame and re-issue pingpong cfg*/ /*this notify is per ping and pong buffer*/ done_buf->is_drop_reconfig = 1; stream_info->current_framedrop_period = 1; /*Avoid Multiple request frames for single SOF*/ vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = false; if (stream_info->current_framedrop_period != stream_info->requested_framedrop_period) { msm_isp_cfg_framedrop_reg(stream_info); } } spin_unlock_irqrestore(&stream_info->lock, flags); /* if buf done will not come, we need to process it ourself */ Loading @@ -2201,6 +2237,8 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, /* no buf done come */ msm_isp_process_axi_irq_stream(vfe_dev, stream_info, pingpong_status, ts); if (done_buf) done_buf->is_drop_reconfig = 0; } return 0; } Loading Loading @@ -2505,7 +2543,7 @@ static int msm_isp_init_stream_ping_pong_reg( /* Set address for both PING & PO NG register */ rc = msm_isp_cfg_ping_pong_address( stream_info, VFE_PING_FLAG); stream_info, VFE_PING_FLAG, NULL); /* No buffer available on start is not error */ if (rc == -ENOMEM && stream_info->stream_type != BURST_STREAM) return 0; Loading @@ -2517,7 +2555,7 @@ static int msm_isp_init_stream_ping_pong_reg( if (stream_info->stream_type != BURST_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( stream_info, VFE_PONG_FLAG); stream_info, VFE_PONG_FLAG, NULL); /* No buffer available on start is not error */ if (rc == -ENOMEM) return 0; Loading Loading @@ -3516,7 +3554,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, if (stream_info->undelivered_request_cnt == 1) { rc = msm_isp_cfg_ping_pong_address(stream_info, VFE_PING_FLAG); VFE_PING_FLAG, NULL); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); stream_info->undelivered_request_cnt--; Loading Loading @@ -3549,10 +3587,10 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, * now. */ rc = msm_isp_cfg_ping_pong_address(stream_info, VFE_PONG_FLAG); VFE_PONG_FLAG, NULL); } else { rc = msm_isp_cfg_ping_pong_address( stream_info, pingpong_status); stream_info, pingpong_status, NULL); } if (rc) { stream_info->undelivered_request_cnt--; Loading @@ -3574,6 +3612,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, if (0 == rc) msm_isp_reset_framedrop(vfe_dev, stream_info); /*Avoid Multiple request frames for single SOF*/ vfe_dev->axi_data.src_info[frame_src].accept_frame = false; spin_unlock_irqrestore(&stream_info->lock, flags); return rc; Loading Loading @@ -4057,6 +4098,10 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, done_buf = stream_info->buf[pingpong_bit]; if (vfe_dev->buf_mgr->frameId_mismatch_recovery == 1) { if (done_buf) { if (done_buf->is_drop_reconfig == 1) done_buf->is_drop_reconfig = 0; } pr_err_ratelimited("%s: Mismatch Recovery in progress, drop frame!\n", __func__); spin_unlock_irqrestore(&stream_info->lock, flags); Loading @@ -4076,14 +4121,26 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, stream_info->frame_id++; stream_info->buf[pingpong_bit] = NULL; if (stream_info->controllable_output && (done_buf != NULL) && (stream_info->sw_ping_pong_bit == -1) && (done_buf->is_drop_reconfig == 1)) { /*When wm reloaded and corresponding reg_update fail * then buffer is reconfig as PING buffer. so, avoid * NULL assignment to PING buffer and eventually * next AXI_DONE or buf_done can be successful */ stream_info->buf[pingpong_bit] = done_buf; } if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( stream_info, pingpong_status); stream_info, pingpong_status, NULL); if (rc < 0) ISP_DBG("%s: Error configuring ping_pong\n", __func__); } else if (done_buf) { } else if (done_buf && (done_buf->is_drop_reconfig != 1)) { msm_isp_cfg_stream_scratch(stream_info, pingpong_status); } Loading @@ -4107,8 +4164,10 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, } rc = msm_isp_update_deliver_count(vfe_dev, stream_info, pingpong_bit); pingpong_bit, done_buf); if (rc) { if (done_buf->is_drop_reconfig == 1) done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); pr_err_ratelimited("%s:VFE%d get done buf fail\n", __func__, vfe_dev->pdev->id); Loading @@ -4117,18 +4176,29 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, return; } spin_unlock_irqrestore(&stream_info->lock, flags); if ((done_buf->frame_id != frame_id) && vfe_dev->axi_data.enable_frameid_recovery) { if (done_buf->is_drop_reconfig == 1) done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); msm_isp_handle_done_buf_frame_id_mismatch(vfe_dev, stream_info, done_buf, time_stamp, frame_id); return; } if (done_buf->is_drop_reconfig == 1) { /*When ping/pong buf is already reconfigured * then dont issue buf-done for current buffer */ done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); } else { spin_unlock_irqrestore(&stream_info->lock, flags); msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, time_stamp, frame_id); } } void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, Loading