Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.h +16 −4 Original line number Diff line number Diff line Loading @@ -286,6 +286,14 @@ enum msm_vfe_axi_stream_type { BURST_STREAM, }; struct msm_vfe_frame_request_queue { struct list_head list; enum msm_vfe_buff_queue_id buff_queue_id; uint8_t cmd_used; }; #define MSM_VFE_REQUESTQ_SIZE 8 struct msm_vfe_axi_stream { uint32_t frame_id; enum msm_vfe_axi_state state; Loading @@ -298,11 +306,15 @@ struct msm_vfe_axi_stream { struct msm_isp_buffer *buf[2]; uint32_t session_id; uint32_t stream_id; uint32_t bufq_handle; uint32_t bufq_scratch_handle; uint32_t controllable_output; uint32_t bufq_handle[VFE_BUF_QUEUE_MAX]; uint8_t controllable_output; uint8_t undelivered_request_cnt; uint8_t request_q_idx; uint32_t request_q_cnt; struct list_head request_q; struct msm_vfe_frame_request_queue request_queue_cmd[MSM_VFE_REQUESTQ_SIZE]; uint32_t stream_handle; uint32_t request_frm_num; uint8_t buf_divert; enum msm_vfe_axi_stream_type stream_type; uint32_t vt_enable; Loading drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +244 −230 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ int msm_isp_axi_create_stream( stream_cfg_cmd->controllable_output; if (stream_cfg_cmd->controllable_output) stream_cfg_cmd->frame_skip_pattern = SKIP_ALL; INIT_LIST_HEAD(&axi_data->stream_info[i].request_q); return 0; } Loading Loading @@ -348,49 +349,6 @@ void msm_isp_axi_free_comp_mask(struct msm_vfe_axi_shared_data *axi_data, axi_data->num_used_composite_mask--; } int msm_isp_axi_get_bufq_handles( struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info) { int rc = 0; if (stream_info->stream_id & ISP_SCRATCH_BUF_BIT) { stream_info->bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( vfe_dev->buf_mgr, stream_info->session_id, stream_info->stream_id & ~ISP_SCRATCH_BUF_BIT); if (stream_info->bufq_handle == 0) { pr_err("%s: Stream 0x%x has no valid buffer queue\n", __func__, (unsigned int)stream_info->stream_id); rc = -EINVAL; return rc; } stream_info->bufq_scratch_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( vfe_dev->buf_mgr, stream_info->session_id, stream_info->stream_id); if (stream_info->bufq_scratch_handle == 0) { pr_err("%s: Stream 0x%x has no valid buffer queue\n", __func__, (unsigned int)stream_info->stream_id); rc = -EINVAL; return rc; } } else { stream_info->bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( vfe_dev->buf_mgr, stream_info->session_id, stream_info->stream_id); if (stream_info->bufq_handle == 0) { pr_err("%s: Stream 0x%x has no valid buffer queue\n", __func__, (unsigned int)stream_info->stream_id); rc = -EINVAL; return rc; } } return rc; } int msm_isp_axi_check_stream_state( struct vfe_device *vfe_dev, struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd) Loading Loading @@ -431,12 +389,6 @@ int msm_isp_axi_check_stream_state( } } spin_unlock_irqrestore(&stream_info->lock, flags); if (stream_cfg_cmd->cmd == START_STREAM) { rc = msm_isp_axi_get_bufq_handles(vfe_dev, stream_info); if (rc) break; } } return rc; } Loading Loading @@ -950,17 +902,18 @@ static void msm_isp_get_done_buf(struct vfe_device *vfe_dev, if (stream_info->controllable_output) { stream_info->buf[pingpong_bit] = NULL; stream_info->request_frm_num--; stream_info->undelivered_request_cnt--; } } static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, uint32_t pingpong_bit) struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status) { int i, rc = -1; struct msm_isp_buffer *buf = NULL; uint32_t bufq_handle = 0; struct msm_vfe_frame_request_queue *queue_req; uint32_t pingpong_bit; uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle); if (stream_idx >= MAX_NUM_STREAM) { Loading @@ -968,17 +921,29 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, return rc; } if (stream_info->controllable_output && !stream_info->request_frm_num) if (!stream_info->controllable_output) { bufq_handle = stream_info->bufq_handle[VFE_BUF_QUEUE_DEFAULT]; } else { queue_req = list_first_entry_or_null(&stream_info->request_q, struct msm_vfe_frame_request_queue, list); if (!queue_req) return 0; bufq_handle = stream_info->bufq_handle; if (SRC_TO_INTF(stream_info->stream_src) < VFE_SRC_MAX) queue_req->cmd_used = 0; bufq_handle = stream_info-> bufq_handle[queue_req->buff_queue_id]; list_del(&queue_req->list); stream_info->request_q_cnt--; if (!bufq_handle) { pr_err("%s: Drop request. Shared stream is stopped.\n", __func__); return -EINVAL; } } rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr, vfe_dev->pdev->id, bufq_handle, &buf); else { pr_err("%s: Invalid stream index\n", __func__); rc = -1; } if (rc < 0) { vfe_dev->error_info.stream_framedrop_count[stream_idx]++; Loading @@ -997,6 +962,7 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, pingpong_status, buf->mapped_info[i].paddr + stream_info->plane_cfg[i].plane_addr_offset); pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); stream_info->buf[pingpong_bit] = buf; return 0; Loading @@ -1018,10 +984,7 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, uint32_t buf_src; memset(&buf_event, 0, sizeof(buf_event)); if (SRC_TO_INTF(stream_info->stream_src) < VFE_SRC_MAX) frame_id = vfe_dev->axi_data. src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id; else { if (SRC_TO_INTF(stream_info->stream_src) >= VFE_SRC_MAX) { pr_err("%s: Invalid stream index, put buf back to vb2 queue\n", __func__); vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr, Loading @@ -1029,13 +992,18 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, return; } if (buf && ts) { if (!buf || !ts) return; frame_id = vfe_dev->axi_data. src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id; if (vfe_dev->vt_enable) { msm_isp_get_avtimer_ts(ts); time_stamp = &ts->vt_time; } else } else { time_stamp = &ts->buf_time; } rc = vfe_dev->buf_mgr->ops->get_buf_src(vfe_dev->buf_mgr, buf->bufq_handle, &buf_src); Loading @@ -1048,44 +1016,34 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, * can be diverted. A positive return value means * other ISP hardware is still processing the frame. */ if (rc == 0) { buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); if (rc) return; buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); buf_event.frame_id = frame_id; buf_event.timestamp = *time_stamp; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.handle = stream_info->bufq_handle; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.handle = buf->bufq_handle; buf_event.u.buf_done.buf_idx = buf->buf_idx; buf_event.u.buf_done.output_format = stream_info->runtime_output_format; msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DIVERT + stream_idx, msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DIVERT + stream_idx, &buf_event); } } else { buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); buf_event.frame_id = frame_id; buf_event.timestamp = ts->buf_time; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.output_format = stream_info->runtime_output_format; msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DONE, &buf_event); msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DONE, &buf_event); vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr, buf->bufq_handle, buf->buf_idx, time_stamp, frame_id, buf->bufq_handle, buf->buf_idx, time_stamp, frame_id, stream_info->runtime_output_format); } } } static enum msm_isp_camif_update_state msm_isp_get_camif_update_state(struct vfe_device *vfe_dev, Loading Loading @@ -1229,7 +1187,7 @@ static int msm_isp_init_stream_ping_pong_reg( int rc = 0; /*Set address for both PING & PONG register */ rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PING_FLAG, 0); stream_info, VFE_PING_FLAG); if (rc < 0) { pr_err("%s: No free buffer for ping\n", __func__); Loading @@ -1245,7 +1203,7 @@ static int msm_isp_init_stream_ping_pong_reg( msm_isp_cfg_pong_address(vfe_dev, stream_info); } else { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PONG_FLAG, 1); stream_info, VFE_PONG_FLAG); if (rc < 0) { pr_err("%s: No free buffer for pong\n", __func__); Loading Loading @@ -1312,6 +1270,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info; struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; struct msm_isp_bufq *bufq = NULL; uint32_t bufq_handle = 0, bufq_id = 0; if (!reset_cmd) { pr_err("%s: NULL pointer reset cmd %p\n", __func__, reset_cmd); Loading @@ -1336,11 +1295,16 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, continue; } for (bufq_id = 0; bufq_id < VFE_BUF_QUEUE_MAX; bufq_id++) { bufq_handle = stream_info->bufq_handle[bufq_id]; if (!bufq_handle) continue; bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr, stream_info->bufq_handle); bufq_handle); if (!bufq) { pr_err("%s: bufq null %p by handle %x\n", __func__, bufq, stream_info->bufq_handle); pr_err("%s: bufq null %p by handle %x\n", __func__, bufq, bufq_handle); continue; } Loading @@ -1348,13 +1312,15 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, msm_isp_deinit_stream_ping_pong_reg(vfe_dev, stream_info); } else { vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr, stream_info->bufq_handle, vfe_dev->buf_mgr->ops->flush_buf( vfe_dev->buf_mgr, bufq_handle, MSM_ISP_BUFFER_FLUSH_ALL); } axi_data->src_info[SRC_TO_INTF(stream_info->stream_src)]. frame_id = reset_cmd->frame_id; msm_isp_reset_burst_count_and_frame_drop(vfe_dev, stream_info); axi_data->src_info[SRC_TO_INTF(stream_info-> stream_src)]. frame_id = reset_cmd->frame_id; msm_isp_reset_burst_count_and_frame_drop(vfe_dev, stream_info); } } if (rc < 0) Loading Loading @@ -1633,81 +1599,122 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg) } static int msm_isp_request_frame(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t request_frm_num) struct msm_vfe_axi_stream *stream_info, uint32_t user_stream_id) { struct msm_vfe_axi_stream_request_cmd stream_cfg_cmd; struct msm_vfe_frame_request_queue *queue_req; uint32_t pingpong_status, wm_reload_mask = 0x0; unsigned long flags; int rc = 0; uint32_t pingpong_status, pingpong_bit, wm_reload_mask = 0x0; if (!stream_info->controllable_output) return 0; if (!request_frm_num) { pr_err("%s: Invalid frame request.\n", __func__); spin_lock_irqsave(&stream_info->lock, flags); queue_req = &stream_info->request_queue_cmd[stream_info->request_q_idx]; if (queue_req->cmd_used) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err_ratelimited("%s: Request queue overflow.\n", __func__); return -EINVAL; } stream_info->request_frm_num += request_frm_num; if (user_stream_id == stream_info->stream_id) queue_req->buff_queue_id = VFE_BUF_QUEUE_DEFAULT; else queue_req->buff_queue_id = VFE_BUF_QUEUE_SHARED; if (!stream_info->bufq_handle[queue_req->buff_queue_id]) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err("%s:%d stream is stoped\n", __func__, __LINE__); return 0; } queue_req->cmd_used = 1; stream_info->request_q_idx = (stream_info->request_q_idx + 1) % MSM_VFE_REQUESTQ_SIZE; list_add_tail(&queue_req->list, &stream_info->request_q); stream_info->request_q_cnt++; stream_info->undelivered_request_cnt++; stream_cfg_cmd.axi_stream_handle = stream_info->stream_handle; stream_cfg_cmd.frame_skip_pattern = NO_SKIP; stream_cfg_cmd.init_frame_drop = 0; stream_cfg_cmd.burst_count = stream_info->request_frm_num; stream_cfg_cmd.burst_count = stream_info->request_q_cnt; msm_isp_calculate_framedrop(&vfe_dev->axi_data, &stream_cfg_cmd); msm_isp_reset_framedrop(vfe_dev, stream_info); if (stream_info->request_frm_num != request_frm_num) { pingpong_status = vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status( vfe_dev); pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); if (!stream_info->buf[pingpong_bit]) { if (stream_info->undelivered_request_cnt == 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, pingpong_status, pingpong_bit); VFE_PING_FLAG); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); return rc; } } if (!stream_info->buf[!pingpong_bit] && request_frm_num > 1) { msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask); vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask); } else if (stream_info->undelivered_request_cnt == 2) { pingpong_status = vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status( vfe_dev); rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, ~pingpong_status, !pingpong_bit); pingpong_status); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); return rc; } } } else { if (!stream_info->buf[0]) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PING_FLAG, 0); if (rc) { pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); spin_unlock_irqrestore(&stream_info->lock, flags); return rc; } static int msm_isp_add_buf_queue(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t stream_id) { int rc = 0; uint32_t bufq_id = 0; if (stream_id == stream_info->stream_id) bufq_id = VFE_BUF_QUEUE_DEFAULT; else bufq_id = VFE_BUF_QUEUE_SHARED; stream_info->bufq_handle[bufq_id] = vfe_dev->buf_mgr->ops->get_bufq_handle(vfe_dev->buf_mgr, stream_info->session_id, stream_id); if (stream_info->bufq_handle[bufq_id] == 0) { pr_err("%s: failed: No valid buffer queue for stream: 0x%x\n", __func__, stream_id); rc = -EINVAL; } if (!stream_info->buf[1] && request_frm_num > 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PONG_FLAG, 1); if (rc) { pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); return rc; } } msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask); vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask); } static void msm_isp_remove_buf_queue(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t stream_id) { uint32_t bufq_id = 0; unsigned long flags; if (stream_id == stream_info->stream_id) bufq_id = VFE_BUF_QUEUE_DEFAULT; else bufq_id = VFE_BUF_QUEUE_SHARED; spin_lock_irqsave(&stream_info->lock, flags); stream_info->bufq_handle[bufq_id] = 0; spin_unlock_irqrestore(&stream_info->lock, flags); return rc; } int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) Loading Loading @@ -1756,7 +1763,7 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) case DISABLE_STREAM_BUF_DIVERT: stream_info->buf_divert = 0; vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr, stream_info->bufq_handle, stream_info->bufq_handle[VFE_BUF_QUEUE_DEFAULT], MSM_ISP_BUFFER_FLUSH_DIVERTED); break; case UPDATE_STREAM_FRAMEDROP_PATTERN: { Loading Loading @@ -1801,12 +1808,29 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) } case UPDATE_STREAM_REQUEST_FRAMES: { rc = msm_isp_request_frame(vfe_dev, stream_info, update_info->request_frm_num); update_info->user_stream_id); if (rc) pr_err("%s failed to request frame!\n", __func__); break; } case UPDATE_STREAM_ADD_BUFQ: { rc = msm_isp_add_buf_queue(vfe_dev, stream_info, update_info->user_stream_id); if (rc) pr_err("%s failed to add bufq!\n", __func__); break; } case UPDATE_STREAM_REMOVE_BUFQ: { msm_isp_remove_buf_queue(vfe_dev, stream_info, update_info->user_stream_id); rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, NO_UPDATE); if (rc < 0) pr_err("%s: wait for config done failed\n", __func__); break; } default: pr_err("%s: Invalid update type\n", __func__); return -EINVAL; Loading @@ -1826,7 +1850,7 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info; struct msm_vfe_axi_composite_info *comp_info; struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; uint32_t pingpong_bit = 0; unsigned long flags; comp_mask = vfe_dev->hw_info->vfe_ops.axi_ops. get_comp_mask(irq_status0, irq_status1); Loading @@ -1842,45 +1866,37 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) { rc = 0; comp_info = &axi_data->composite_info[i]; wm_mask &= ~(comp_info->stream_composite_mask); if (comp_mask & (1 << i)) { if (!comp_info->stream_handle) { pr_err("%s: Invalid handle for composite irq\n", __func__); } else { stream_idx = HANDLE_TO_IDX(comp_info->stream_handle); stream_info = &axi_data->stream_info[stream_idx]; ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, stream_info->stream_id, stream_info->frame_id); continue; } stream_idx = HANDLE_TO_IDX(comp_info->stream_handle); stream_info = &axi_data->stream_info[stream_idx]; ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, stream_info->stream_id, stream_info->frame_id); stream_info->frame_id++; pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); if (stream_info->stream_type == BURST_STREAM) stream_info-> runtime_num_burst_capture--; stream_info->runtime_num_burst_capture--; spin_lock_irqsave(&stream_info->lock, flags); msm_isp_get_done_buf(vfe_dev, stream_info, pingpong_status, &done_buf); if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info-> runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( vfe_dev, stream_info, pingpong_status, pingpong_bit); if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, pingpong_status); } spin_unlock_irqrestore(&stream_info->lock, flags); if (done_buf && !rc) msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, ts); msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, ts); } } wm_mask &= ~(comp_info->stream_composite_mask); } for (i = 0; i < axi_data->hw_info->num_wm; i++) { if (wm_mask & (1 << i)) { Loading @@ -1891,25 +1907,23 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, } stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]); stream_info = &axi_data->stream_info[stream_idx]; ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, stream_info->stream_id, stream_info->frame_id); stream_info->frame_id++; pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); if (stream_info->stream_type == BURST_STREAM) stream_info->runtime_num_burst_capture--; spin_lock_irqsave(&stream_info->lock, flags); msm_isp_get_done_buf(vfe_dev, stream_info, pingpong_status, &done_buf); if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, pingpong_status, pingpong_bit); stream_info, pingpong_status); } spin_unlock_irqrestore(&stream_info->lock, flags); if (done_buf && !rc) msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, ts); Loading include/media/msmb_isp.h +9 −1 Original line number Diff line number Diff line Loading @@ -221,6 +221,8 @@ enum msm_vfe_axi_stream_update_type { UPDATE_STREAM_STATS_FRAMEDROP_PATTERN, UPDATE_STREAM_AXI_CONFIG, UPDATE_STREAM_REQUEST_FRAMES, UPDATE_STREAM_ADD_BUFQ, UPDATE_STREAM_REMOVE_BUFQ, }; enum msm_vfe_iommu_type { Loading @@ -228,10 +230,16 @@ enum msm_vfe_iommu_type { IOMMU_DETACH, }; enum msm_vfe_buff_queue_id { VFE_BUF_QUEUE_DEFAULT, VFE_BUF_QUEUE_SHARED, VFE_BUF_QUEUE_MAX, }; struct msm_vfe_axi_stream_cfg_update_info { uint32_t stream_handle; uint32_t output_format; uint32_t request_frm_num; uint32_t user_stream_id; enum msm_vfe_frame_skip_pattern skip_pattern; struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM]; }; Loading Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.h +16 −4 Original line number Diff line number Diff line Loading @@ -286,6 +286,14 @@ enum msm_vfe_axi_stream_type { BURST_STREAM, }; struct msm_vfe_frame_request_queue { struct list_head list; enum msm_vfe_buff_queue_id buff_queue_id; uint8_t cmd_used; }; #define MSM_VFE_REQUESTQ_SIZE 8 struct msm_vfe_axi_stream { uint32_t frame_id; enum msm_vfe_axi_state state; Loading @@ -298,11 +306,15 @@ struct msm_vfe_axi_stream { struct msm_isp_buffer *buf[2]; uint32_t session_id; uint32_t stream_id; uint32_t bufq_handle; uint32_t bufq_scratch_handle; uint32_t controllable_output; uint32_t bufq_handle[VFE_BUF_QUEUE_MAX]; uint8_t controllable_output; uint8_t undelivered_request_cnt; uint8_t request_q_idx; uint32_t request_q_cnt; struct list_head request_q; struct msm_vfe_frame_request_queue request_queue_cmd[MSM_VFE_REQUESTQ_SIZE]; uint32_t stream_handle; uint32_t request_frm_num; uint8_t buf_divert; enum msm_vfe_axi_stream_type stream_type; uint32_t vt_enable; Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +244 −230 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ int msm_isp_axi_create_stream( stream_cfg_cmd->controllable_output; if (stream_cfg_cmd->controllable_output) stream_cfg_cmd->frame_skip_pattern = SKIP_ALL; INIT_LIST_HEAD(&axi_data->stream_info[i].request_q); return 0; } Loading Loading @@ -348,49 +349,6 @@ void msm_isp_axi_free_comp_mask(struct msm_vfe_axi_shared_data *axi_data, axi_data->num_used_composite_mask--; } int msm_isp_axi_get_bufq_handles( struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info) { int rc = 0; if (stream_info->stream_id & ISP_SCRATCH_BUF_BIT) { stream_info->bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( vfe_dev->buf_mgr, stream_info->session_id, stream_info->stream_id & ~ISP_SCRATCH_BUF_BIT); if (stream_info->bufq_handle == 0) { pr_err("%s: Stream 0x%x has no valid buffer queue\n", __func__, (unsigned int)stream_info->stream_id); rc = -EINVAL; return rc; } stream_info->bufq_scratch_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( vfe_dev->buf_mgr, stream_info->session_id, stream_info->stream_id); if (stream_info->bufq_scratch_handle == 0) { pr_err("%s: Stream 0x%x has no valid buffer queue\n", __func__, (unsigned int)stream_info->stream_id); rc = -EINVAL; return rc; } } else { stream_info->bufq_handle = vfe_dev->buf_mgr->ops->get_bufq_handle( vfe_dev->buf_mgr, stream_info->session_id, stream_info->stream_id); if (stream_info->bufq_handle == 0) { pr_err("%s: Stream 0x%x has no valid buffer queue\n", __func__, (unsigned int)stream_info->stream_id); rc = -EINVAL; return rc; } } return rc; } int msm_isp_axi_check_stream_state( struct vfe_device *vfe_dev, struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd) Loading Loading @@ -431,12 +389,6 @@ int msm_isp_axi_check_stream_state( } } spin_unlock_irqrestore(&stream_info->lock, flags); if (stream_cfg_cmd->cmd == START_STREAM) { rc = msm_isp_axi_get_bufq_handles(vfe_dev, stream_info); if (rc) break; } } return rc; } Loading Loading @@ -950,17 +902,18 @@ static void msm_isp_get_done_buf(struct vfe_device *vfe_dev, if (stream_info->controllable_output) { stream_info->buf[pingpong_bit] = NULL; stream_info->request_frm_num--; stream_info->undelivered_request_cnt--; } } static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, uint32_t pingpong_bit) struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status) { int i, rc = -1; struct msm_isp_buffer *buf = NULL; uint32_t bufq_handle = 0; struct msm_vfe_frame_request_queue *queue_req; uint32_t pingpong_bit; uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle); if (stream_idx >= MAX_NUM_STREAM) { Loading @@ -968,17 +921,29 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, return rc; } if (stream_info->controllable_output && !stream_info->request_frm_num) if (!stream_info->controllable_output) { bufq_handle = stream_info->bufq_handle[VFE_BUF_QUEUE_DEFAULT]; } else { queue_req = list_first_entry_or_null(&stream_info->request_q, struct msm_vfe_frame_request_queue, list); if (!queue_req) return 0; bufq_handle = stream_info->bufq_handle; if (SRC_TO_INTF(stream_info->stream_src) < VFE_SRC_MAX) queue_req->cmd_used = 0; bufq_handle = stream_info-> bufq_handle[queue_req->buff_queue_id]; list_del(&queue_req->list); stream_info->request_q_cnt--; if (!bufq_handle) { pr_err("%s: Drop request. Shared stream is stopped.\n", __func__); return -EINVAL; } } rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr, vfe_dev->pdev->id, bufq_handle, &buf); else { pr_err("%s: Invalid stream index\n", __func__); rc = -1; } if (rc < 0) { vfe_dev->error_info.stream_framedrop_count[stream_idx]++; Loading @@ -997,6 +962,7 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev, pingpong_status, buf->mapped_info[i].paddr + stream_info->plane_cfg[i].plane_addr_offset); pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); stream_info->buf[pingpong_bit] = buf; return 0; Loading @@ -1018,10 +984,7 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, uint32_t buf_src; memset(&buf_event, 0, sizeof(buf_event)); if (SRC_TO_INTF(stream_info->stream_src) < VFE_SRC_MAX) frame_id = vfe_dev->axi_data. src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id; else { if (SRC_TO_INTF(stream_info->stream_src) >= VFE_SRC_MAX) { pr_err("%s: Invalid stream index, put buf back to vb2 queue\n", __func__); vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr, Loading @@ -1029,13 +992,18 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, return; } if (buf && ts) { if (!buf || !ts) return; frame_id = vfe_dev->axi_data. src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id; if (vfe_dev->vt_enable) { msm_isp_get_avtimer_ts(ts); time_stamp = &ts->vt_time; } else } else { time_stamp = &ts->buf_time; } rc = vfe_dev->buf_mgr->ops->get_buf_src(vfe_dev->buf_mgr, buf->bufq_handle, &buf_src); Loading @@ -1048,44 +1016,34 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, * can be diverted. A positive return value means * other ISP hardware is still processing the frame. */ if (rc == 0) { buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); if (rc) return; buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); buf_event.frame_id = frame_id; buf_event.timestamp = *time_stamp; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.handle = stream_info->bufq_handle; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.handle = buf->bufq_handle; buf_event.u.buf_done.buf_idx = buf->buf_idx; buf_event.u.buf_done.output_format = stream_info->runtime_output_format; msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DIVERT + stream_idx, msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DIVERT + stream_idx, &buf_event); } } else { buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); buf_event.input_intf = SRC_TO_INTF(stream_info->stream_src); buf_event.frame_id = frame_id; buf_event.timestamp = ts->buf_time; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.session_id = stream_info->session_id; buf_event.u.buf_done.stream_id = stream_info->stream_id; buf_event.u.buf_done.output_format = stream_info->runtime_output_format; msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DONE, &buf_event); msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DONE, &buf_event); vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr, buf->bufq_handle, buf->buf_idx, time_stamp, frame_id, buf->bufq_handle, buf->buf_idx, time_stamp, frame_id, stream_info->runtime_output_format); } } } static enum msm_isp_camif_update_state msm_isp_get_camif_update_state(struct vfe_device *vfe_dev, Loading Loading @@ -1229,7 +1187,7 @@ static int msm_isp_init_stream_ping_pong_reg( int rc = 0; /*Set address for both PING & PONG register */ rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PING_FLAG, 0); stream_info, VFE_PING_FLAG); if (rc < 0) { pr_err("%s: No free buffer for ping\n", __func__); Loading @@ -1245,7 +1203,7 @@ static int msm_isp_init_stream_ping_pong_reg( msm_isp_cfg_pong_address(vfe_dev, stream_info); } else { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PONG_FLAG, 1); stream_info, VFE_PONG_FLAG); if (rc < 0) { pr_err("%s: No free buffer for pong\n", __func__); Loading Loading @@ -1312,6 +1270,7 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info; struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; struct msm_isp_bufq *bufq = NULL; uint32_t bufq_handle = 0, bufq_id = 0; if (!reset_cmd) { pr_err("%s: NULL pointer reset cmd %p\n", __func__, reset_cmd); Loading @@ -1336,11 +1295,16 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, continue; } for (bufq_id = 0; bufq_id < VFE_BUF_QUEUE_MAX; bufq_id++) { bufq_handle = stream_info->bufq_handle[bufq_id]; if (!bufq_handle) continue; bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr, stream_info->bufq_handle); bufq_handle); if (!bufq) { pr_err("%s: bufq null %p by handle %x\n", __func__, bufq, stream_info->bufq_handle); pr_err("%s: bufq null %p by handle %x\n", __func__, bufq, bufq_handle); continue; } Loading @@ -1348,13 +1312,15 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev, msm_isp_deinit_stream_ping_pong_reg(vfe_dev, stream_info); } else { vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr, stream_info->bufq_handle, vfe_dev->buf_mgr->ops->flush_buf( vfe_dev->buf_mgr, bufq_handle, MSM_ISP_BUFFER_FLUSH_ALL); } axi_data->src_info[SRC_TO_INTF(stream_info->stream_src)]. frame_id = reset_cmd->frame_id; msm_isp_reset_burst_count_and_frame_drop(vfe_dev, stream_info); axi_data->src_info[SRC_TO_INTF(stream_info-> stream_src)]. frame_id = reset_cmd->frame_id; msm_isp_reset_burst_count_and_frame_drop(vfe_dev, stream_info); } } if (rc < 0) Loading Loading @@ -1633,81 +1599,122 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg) } static int msm_isp_request_frame(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t request_frm_num) struct msm_vfe_axi_stream *stream_info, uint32_t user_stream_id) { struct msm_vfe_axi_stream_request_cmd stream_cfg_cmd; struct msm_vfe_frame_request_queue *queue_req; uint32_t pingpong_status, wm_reload_mask = 0x0; unsigned long flags; int rc = 0; uint32_t pingpong_status, pingpong_bit, wm_reload_mask = 0x0; if (!stream_info->controllable_output) return 0; if (!request_frm_num) { pr_err("%s: Invalid frame request.\n", __func__); spin_lock_irqsave(&stream_info->lock, flags); queue_req = &stream_info->request_queue_cmd[stream_info->request_q_idx]; if (queue_req->cmd_used) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err_ratelimited("%s: Request queue overflow.\n", __func__); return -EINVAL; } stream_info->request_frm_num += request_frm_num; if (user_stream_id == stream_info->stream_id) queue_req->buff_queue_id = VFE_BUF_QUEUE_DEFAULT; else queue_req->buff_queue_id = VFE_BUF_QUEUE_SHARED; if (!stream_info->bufq_handle[queue_req->buff_queue_id]) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err("%s:%d stream is stoped\n", __func__, __LINE__); return 0; } queue_req->cmd_used = 1; stream_info->request_q_idx = (stream_info->request_q_idx + 1) % MSM_VFE_REQUESTQ_SIZE; list_add_tail(&queue_req->list, &stream_info->request_q); stream_info->request_q_cnt++; stream_info->undelivered_request_cnt++; stream_cfg_cmd.axi_stream_handle = stream_info->stream_handle; stream_cfg_cmd.frame_skip_pattern = NO_SKIP; stream_cfg_cmd.init_frame_drop = 0; stream_cfg_cmd.burst_count = stream_info->request_frm_num; stream_cfg_cmd.burst_count = stream_info->request_q_cnt; msm_isp_calculate_framedrop(&vfe_dev->axi_data, &stream_cfg_cmd); msm_isp_reset_framedrop(vfe_dev, stream_info); if (stream_info->request_frm_num != request_frm_num) { pingpong_status = vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status( vfe_dev); pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); if (!stream_info->buf[pingpong_bit]) { if (stream_info->undelivered_request_cnt == 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, pingpong_status, pingpong_bit); VFE_PING_FLAG); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); return rc; } } if (!stream_info->buf[!pingpong_bit] && request_frm_num > 1) { msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask); vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask); } else if (stream_info->undelivered_request_cnt == 2) { pingpong_status = vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status( vfe_dev); rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, ~pingpong_status, !pingpong_bit); pingpong_status); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); return rc; } } } else { if (!stream_info->buf[0]) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PING_FLAG, 0); if (rc) { pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); spin_unlock_irqrestore(&stream_info->lock, flags); return rc; } static int msm_isp_add_buf_queue(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t stream_id) { int rc = 0; uint32_t bufq_id = 0; if (stream_id == stream_info->stream_id) bufq_id = VFE_BUF_QUEUE_DEFAULT; else bufq_id = VFE_BUF_QUEUE_SHARED; stream_info->bufq_handle[bufq_id] = vfe_dev->buf_mgr->ops->get_bufq_handle(vfe_dev->buf_mgr, stream_info->session_id, stream_id); if (stream_info->bufq_handle[bufq_id] == 0) { pr_err("%s: failed: No valid buffer queue for stream: 0x%x\n", __func__, stream_id); rc = -EINVAL; } if (!stream_info->buf[1] && request_frm_num > 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, VFE_PONG_FLAG, 1); if (rc) { pr_err("%s:%d fail to set ping pong address\n", __func__, __LINE__); return rc; } } msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask); vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask); } static void msm_isp_remove_buf_queue(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info, uint32_t stream_id) { uint32_t bufq_id = 0; unsigned long flags; if (stream_id == stream_info->stream_id) bufq_id = VFE_BUF_QUEUE_DEFAULT; else bufq_id = VFE_BUF_QUEUE_SHARED; spin_lock_irqsave(&stream_info->lock, flags); stream_info->bufq_handle[bufq_id] = 0; spin_unlock_irqrestore(&stream_info->lock, flags); return rc; } int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) Loading Loading @@ -1756,7 +1763,7 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) case DISABLE_STREAM_BUF_DIVERT: stream_info->buf_divert = 0; vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr, stream_info->bufq_handle, stream_info->bufq_handle[VFE_BUF_QUEUE_DEFAULT], MSM_ISP_BUFFER_FLUSH_DIVERTED); break; case UPDATE_STREAM_FRAMEDROP_PATTERN: { Loading Loading @@ -1801,12 +1808,29 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) } case UPDATE_STREAM_REQUEST_FRAMES: { rc = msm_isp_request_frame(vfe_dev, stream_info, update_info->request_frm_num); update_info->user_stream_id); if (rc) pr_err("%s failed to request frame!\n", __func__); break; } case UPDATE_STREAM_ADD_BUFQ: { rc = msm_isp_add_buf_queue(vfe_dev, stream_info, update_info->user_stream_id); if (rc) pr_err("%s failed to add bufq!\n", __func__); break; } case UPDATE_STREAM_REMOVE_BUFQ: { msm_isp_remove_buf_queue(vfe_dev, stream_info, update_info->user_stream_id); rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, NO_UPDATE); if (rc < 0) pr_err("%s: wait for config done failed\n", __func__); break; } default: pr_err("%s: Invalid update type\n", __func__); return -EINVAL; Loading @@ -1826,7 +1850,7 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream *stream_info; struct msm_vfe_axi_composite_info *comp_info; struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; uint32_t pingpong_bit = 0; unsigned long flags; comp_mask = vfe_dev->hw_info->vfe_ops.axi_ops. get_comp_mask(irq_status0, irq_status1); Loading @@ -1842,45 +1866,37 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) { rc = 0; comp_info = &axi_data->composite_info[i]; wm_mask &= ~(comp_info->stream_composite_mask); if (comp_mask & (1 << i)) { if (!comp_info->stream_handle) { pr_err("%s: Invalid handle for composite irq\n", __func__); } else { stream_idx = HANDLE_TO_IDX(comp_info->stream_handle); stream_info = &axi_data->stream_info[stream_idx]; ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, stream_info->stream_id, stream_info->frame_id); continue; } stream_idx = HANDLE_TO_IDX(comp_info->stream_handle); stream_info = &axi_data->stream_info[stream_idx]; ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, stream_info->stream_id, stream_info->frame_id); stream_info->frame_id++; pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); if (stream_info->stream_type == BURST_STREAM) stream_info-> runtime_num_burst_capture--; stream_info->runtime_num_burst_capture--; spin_lock_irqsave(&stream_info->lock, flags); msm_isp_get_done_buf(vfe_dev, stream_info, pingpong_status, &done_buf); if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info-> runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( vfe_dev, stream_info, pingpong_status, pingpong_bit); if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, pingpong_status); } spin_unlock_irqrestore(&stream_info->lock, flags); if (done_buf && !rc) msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, ts); msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, ts); } } wm_mask &= ~(comp_info->stream_composite_mask); } for (i = 0; i < axi_data->hw_info->num_wm; i++) { if (wm_mask & (1 << i)) { Loading @@ -1891,25 +1907,23 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, } stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]); stream_info = &axi_data->stream_info[stream_idx]; ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, stream_info->stream_id, stream_info->frame_id); stream_info->frame_id++; pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1); if (stream_info->stream_type == BURST_STREAM) stream_info->runtime_num_burst_capture--; spin_lock_irqsave(&stream_info->lock, flags); msm_isp_get_done_buf(vfe_dev, stream_info, pingpong_status, &done_buf); if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info, pingpong_status, pingpong_bit); stream_info, pingpong_status); } spin_unlock_irqrestore(&stream_info->lock, flags); if (done_buf && !rc) msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, ts); Loading
include/media/msmb_isp.h +9 −1 Original line number Diff line number Diff line Loading @@ -221,6 +221,8 @@ enum msm_vfe_axi_stream_update_type { UPDATE_STREAM_STATS_FRAMEDROP_PATTERN, UPDATE_STREAM_AXI_CONFIG, UPDATE_STREAM_REQUEST_FRAMES, UPDATE_STREAM_ADD_BUFQ, UPDATE_STREAM_REMOVE_BUFQ, }; enum msm_vfe_iommu_type { Loading @@ -228,10 +230,16 @@ enum msm_vfe_iommu_type { IOMMU_DETACH, }; enum msm_vfe_buff_queue_id { VFE_BUF_QUEUE_DEFAULT, VFE_BUF_QUEUE_SHARED, VFE_BUF_QUEUE_MAX, }; struct msm_vfe_axi_stream_cfg_update_info { uint32_t stream_handle; uint32_t output_format; uint32_t request_frm_num; uint32_t user_stream_id; enum msm_vfe_frame_skip_pattern skip_pattern; struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM]; }; Loading