diff options
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/isp/msm_isp.h | 21 | ||||
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 438 | ||||
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 120 | ||||
| -rw-r--r-- | include/uapi/media/msmb_isp.h | 14 |
4 files changed, 269 insertions, 324 deletions
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index bf0d90f506df..15bbf5b7747f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -95,11 +95,9 @@ struct msm_vfe_sof_info { struct msm_vfe_dual_hw_ms_info { /* type is Master/Slave */ enum msm_vfe_dual_hw_ms_type dual_hw_ms_type; - /* sof_info is resource from common_data. If NULL, then this INTF - * sof does not need to be saved */ - struct msm_vfe_sof_info *sof_info; - /* slave_id is index in common_data sof_info array for slaves */ - uint8_t slave_id; + enum msm_vfe_dual_cam_sync_mode sync_state; + struct msm_vfe_sof_info sof_info; + int index; }; struct vfe_subscribe_info { @@ -680,13 +678,14 @@ struct dual_vfe_resource { struct master_slave_resource_info { 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]; + uint32_t active_src_mask; + uint32_t src_sof_mask; + int master_index; + int primary_slv_idx; + struct msm_vfe_src_info *src_info[MAX_VFE * VFE_SRC_MAX]; + uint32_t num_src; + enum msm_vfe_dual_cam_sync_mode dual_sync_mode; }; struct msm_vfe_common_dev_data { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index ea33d3eab401..ac42144212bf 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -19,10 +19,6 @@ #define HANDLE_TO_IDX(handle) (handle & 0xFF) #define ISP_SOF_DEBUG_COUNT 0 -static int msm_isp_update_dual_HW_ms_info_at_start( - struct vfe_device *vfe_dev, - enum msm_vfe_input_src stream_src); - static void msm_isp_reload_ping_pong_offset( struct msm_vfe_axi_stream *stream_info); @@ -761,6 +757,71 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, } } +static void msm_isp_sync_dual_cam_frame_id( + struct vfe_device *vfe_dev, + struct master_slave_resource_info *ms_res, + enum msm_vfe_input_src frame_src, + struct msm_isp_timestamp *ts) +{ + struct msm_vfe_src_info *src_info = + &vfe_dev->axi_data.src_info[frame_src]; + int i; + uint32_t frame_id = src_info->frame_id; + uint32_t master_time = 0, current_time; + + if (src_info->dual_hw_ms_info.sync_state == + ms_res->dual_sync_mode) { + (frame_src == VFE_PIX_0) ? src_info->frame_id += + vfe_dev->axi_data.src_info[frame_src]. + sof_counter_step : + src_info->frame_id++; + return; + } + + WARN_ON(ms_res->dual_sync_mode == MSM_ISP_DUAL_CAM_ASYNC); + /* find highest frame id */ + for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { + if (ms_res->src_info[i] == NULL) + continue; + if (src_info == ms_res->src_info[i] || + ms_res->src_info[i]->active == 0) + continue; + if (frame_id >= ms_res->src_info[i]->frame_id) + continue; + frame_id = ms_res->src_info[i]->frame_id; + master_time = ms_res->src_info[i]-> + dual_hw_ms_info.sof_info.mono_timestamp_ms; + } + /* copy highest frame id to the intf based on sof delta */ + current_time = ts->buf_time.tv_sec * 1000 + + ts->buf_time.tv_usec / 1000; + + if (current_time > master_time && + (current_time - master_time) > ms_res->sof_delta_threshold) { + if (frame_src == VFE_PIX_0) + frame_id += vfe_dev->axi_data.src_info[frame_src]. + sof_counter_step; + else + frame_id += 1; + } else { + for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { + if (ms_res->src_info[i] == NULL) + continue; + if (src_info == ms_res->src_info[i] || + ((1 << ms_res->src_info[i]-> + dual_hw_ms_info.index) & + ms_res->active_src_mask) == 0) + continue; + if (ms_res->src_info[i]->frame_id == frame_id) + ms_res->src_sof_mask |= (1 << + ms_res->src_info[i]->dual_hw_ms_info.index); + } + } + ms_res->active_src_mask |= (1 << src_info->dual_hw_ms_info.index); + src_info->frame_id = frame_id; + src_info->dual_hw_ms_info.sync_state = MSM_ISP_DUAL_CAM_SYNC; +} + void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, enum msm_vfe_input_src frame_src, struct msm_isp_timestamp *ts) { @@ -768,13 +829,9 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, struct msm_vfe_sof_info *sof_info = NULL; enum msm_vfe_dual_hw_type dual_hw_type; enum msm_vfe_dual_hw_ms_type ms_type; - struct msm_vfe_sof_info *master_sof_info = NULL; - int32_t time, master_time, delta; - uint32_t sof_incr = 0; unsigned long flags; - - if (vfe_dev->axi_data.src_info[frame_src].frame_id == 0) - msm_isp_update_dual_HW_ms_info_at_start(vfe_dev, frame_src); + struct master_slave_resource_info *ms_res = + &vfe_dev->common_data->ms_resource; spin_lock_irqsave(&vfe_dev->common_data->common_dev_data_lock, flags); dual_hw_type = @@ -782,43 +839,41 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, ms_type = vfe_dev->axi_data.src_info[frame_src]. dual_hw_ms_info.dual_hw_ms_type; - /* - * Increment frame_id if - * 1. Not Master Slave - * 2. Master - * 3. Slave and Master is Inactive - * - * OR - * (in other words) - * If SLAVE and Master active, don't increment slave frame_id. - * Instead use Master frame_id for Slave. - */ - if ((dual_hw_type == DUAL_HW_MASTER_SLAVE) && - (ms_type == MS_TYPE_SLAVE) && - (vfe_dev->common_data->ms_resource.master_active == 1)) { - /* DUAL_HW_MS_SLAVE && MASTER active */ - time = ts->buf_time.tv_sec * 1000 + - ts->buf_time.tv_usec / 1000; - master_sof_info = &vfe_dev->common_data->ms_resource. - master_sof_info; - master_time = master_sof_info->mono_timestamp_ms; - delta = vfe_dev->common_data->ms_resource.sof_delta_threshold; - ISP_DBG("%s: vfe %d frame_src %d frame %d Slave time %d Master time %d delta %d\n", - __func__, vfe_dev->pdev->id, frame_src, - vfe_dev->axi_data.src_info[frame_src].frame_id, - time, master_time, time - master_time); - - if (time - master_time > delta) - sof_incr = 1; - /* - * If delta < 5ms, slave frame_id = master frame_id - * If delta > 5ms, slave frame_id = master frame_id + 1 - * CANNOT support Batch Mode with this logic currently. - */ - vfe_dev->axi_data.src_info[frame_src].frame_id = - master_sof_info->frame_id + sof_incr; + src_info = &vfe_dev->axi_data.src_info[frame_src]; + if (dual_hw_type == DUAL_HW_MASTER_SLAVE) { + msm_isp_sync_dual_cam_frame_id(vfe_dev, ms_res, frame_src, ts); + if (src_info->dual_hw_ms_info.sync_state == + MSM_ISP_DUAL_CAM_SYNC) { + /* + * for dual hw check that we recv sof from all + * linked intf + */ + if (ms_res->src_sof_mask & (1 << + src_info->dual_hw_ms_info.index)) { + pr_err("Frame out of sync on vfe %d\n", + vfe_dev->pdev->id); + msm_isp_halt_send_error(vfe_dev, + ISP_EVENT_BUF_FATAL_ERROR); + } + ms_res->src_sof_mask |= (1 << + src_info->dual_hw_ms_info.index); + if (ms_res->active_src_mask == ms_res->src_sof_mask) + ms_res->src_sof_mask = 0; + } + sof_info = &vfe_dev->axi_data.src_info[frame_src]. + dual_hw_ms_info.sof_info; + sof_info->frame_id = vfe_dev->axi_data.src_info[frame_src]. + frame_id; + sof_info->timestamp_ms = ts->event_time.tv_sec * 1000 + + ts->event_time.tv_usec / 1000; + sof_info->mono_timestamp_ms = ts->buf_time.tv_sec * 1000 + + ts->buf_time.tv_usec / 1000; + spin_unlock_irqrestore(&vfe_dev->common_data-> + common_dev_data_lock, flags); } else { + spin_unlock_irqrestore(&vfe_dev->common_data-> + common_dev_data_lock, flags); if (frame_src == VFE_PIX_0) { vfe_dev->axi_data.src_info[frame_src].frame_id += vfe_dev->axi_data.src_info[frame_src]. @@ -827,40 +882,27 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, vfe_dev->pdev->id, vfe_dev->axi_data.src_info[frame_src]. sof_counter_step); - src_info = &vfe_dev->axi_data.src_info[frame_src]; - - if (!src_info->frame_id && - !src_info->reg_update_frame_id && - ((src_info->frame_id - - src_info->reg_update_frame_id) > - (MAX_REG_UPDATE_THRESHOLD * - src_info->sof_counter_step))) { - pr_err("%s:%d reg_update not received for %d frames\n", - __func__, __LINE__, - src_info->frame_id - - src_info->reg_update_frame_id); - - msm_isp_halt_send_error(vfe_dev, - ISP_EVENT_REG_UPDATE_MISSING); - } - - } else + } else { vfe_dev->axi_data.src_info[frame_src].frame_id++; + } } - sof_info = vfe_dev->axi_data.src_info[frame_src]. - dual_hw_ms_info.sof_info; - if (dual_hw_type == DUAL_HW_MASTER_SLAVE && - sof_info != NULL) { - sof_info->frame_id = vfe_dev->axi_data.src_info[frame_src]. - frame_id; - sof_info->timestamp_ms = ts->event_time.tv_sec * 1000 + - ts->event_time.tv_usec / 1000; - sof_info->mono_timestamp_ms = ts->buf_time.tv_sec * 1000 + - ts->buf_time.tv_usec / 1000; + if (frame_src == VFE_PIX_0) { + if (!src_info->frame_id && + !src_info->reg_update_frame_id && + ((src_info->frame_id - + src_info->reg_update_frame_id) > + (MAX_REG_UPDATE_THRESHOLD * + src_info->sof_counter_step))) { + pr_err("%s:%d reg_update not received for %d frames\n", + __func__, __LINE__, + src_info->frame_id - + src_info->reg_update_frame_id); + + msm_isp_halt_send_error(vfe_dev, + ISP_EVENT_REG_UPDATE_MISSING); + } } - spin_unlock_irqrestore(&vfe_dev->common_data->common_dev_data_lock, - flags); } void msm_isp_notify(struct vfe_device *vfe_dev, uint32_t event_type, @@ -869,7 +911,6 @@ void msm_isp_notify(struct vfe_device *vfe_dev, uint32_t event_type, struct msm_isp_event_data event_data; struct msm_vfe_sof_info *sof_info = NULL, *self_sof = NULL; enum msm_vfe_dual_hw_ms_type ms_type; - int i, j; unsigned long flags; memset(&event_data, 0, sizeof(event_data)); @@ -907,51 +948,43 @@ void msm_isp_notify(struct vfe_device *vfe_dev, uint32_t event_type, * If need to support framedrop as well, move delta calculation * to userspace */ - if (vfe_dev->axi_data.src_info[frame_src].dual_hw_type == + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, + flags); + if (vfe_dev->common_data->ms_resource.dual_sync_mode == + MSM_ISP_DUAL_CAM_SYNC && + vfe_dev->axi_data.src_info[frame_src].dual_hw_type == DUAL_HW_MASTER_SLAVE) { - spin_lock_irqsave( - &vfe_dev->common_data->common_dev_data_lock, - flags); - self_sof = vfe_dev->axi_data.src_info[frame_src]. + struct master_slave_resource_info *ms_res = + &vfe_dev->common_data->ms_resource; + self_sof = &vfe_dev->axi_data.src_info[frame_src]. dual_hw_ms_info.sof_info; - if (!self_sof) { - spin_unlock_irqrestore(&vfe_dev->common_data-> - common_dev_data_lock, flags); - break; - } ms_type = vfe_dev->axi_data.src_info[frame_src]. dual_hw_ms_info.dual_hw_ms_type; - if (ms_type == MS_TYPE_MASTER) { - for (i = 0, j = 0; i < MS_NUM_SLAVE_MAX; i++) { - if (!(vfe_dev->common_data-> - ms_resource.slave_active_mask - & (1 << i))) - continue; - sof_info = &vfe_dev->common_data-> - ms_resource.slave_sof_info[i]; - event_data.u.sof_info.ms_delta_info. - delta[j] = - self_sof->mono_timestamp_ms - - sof_info->mono_timestamp_ms; - j++; - if (j == vfe_dev->common_data-> - ms_resource.num_slave) - break; - } - event_data.u.sof_info.ms_delta_info. - num_delta_info = j; - } else { - sof_info = &vfe_dev->common_data->ms_resource. - master_sof_info; + /* only send back time delta for primatry intf */ + if (ms_res->primary_slv_idx > 0 && + ms_type == MS_TYPE_MASTER) + sof_info = &ms_res->src_info[ + ms_res->primary_slv_idx]-> + dual_hw_ms_info.sof_info; + if (ms_type != MS_TYPE_MASTER && + ms_res->master_index > 0) + sof_info = &ms_res->src_info[ + ms_res->master_index]-> + dual_hw_ms_info.sof_info; + if (sof_info) { event_data.u.sof_info.ms_delta_info. - num_delta_info = 1; - event_data.u.sof_info.ms_delta_info.delta[0] = + delta[0] = self_sof->mono_timestamp_ms - sof_info->mono_timestamp_ms; + event_data.u.sof_info.ms_delta_info. + num_delta_info = 1; } spin_unlock_irqrestore(&vfe_dev->common_data-> common_dev_data_lock, flags); } else { + spin_unlock_irqrestore(&vfe_dev->common_data-> + common_dev_data_lock, flags); if (frame_src <= VFE_RAW_2) { msm_isp_check_for_output_error(vfe_dev, ts, &event_data.u.sof_info); @@ -2089,6 +2122,7 @@ static void msm_isp_input_disable(struct vfe_device *vfe_dev) int stream_count; int total_stream_count = 0; int i; + struct msm_vfe_src_info *src_info; for (i = 0; i < VFE_SRC_MAX; i++) total_stream_count += axi_data->src_info[i].stream_count + @@ -2103,6 +2137,37 @@ static void msm_isp_input_disable(struct vfe_device *vfe_dev) continue; /* deactivate the input line */ axi_data->src_info[i].active = 0; + src_info = &axi_data->src_info[i]; + + if (src_info->dual_hw_type == DUAL_HW_MASTER_SLAVE) { + struct master_slave_resource_info *ms_res = + &vfe_dev->common_data->ms_resource; + unsigned long flags; + + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, + flags); + if (src_info->dual_hw_ms_info.index == + ms_res->master_index) + ms_res->master_index = -1; + if (src_info->dual_hw_ms_info.index == + ms_res->primary_slv_idx) + ms_res->primary_slv_idx = -1; + ms_res->active_src_mask &= ~(1 << + src_info->dual_hw_ms_info.index); + ms_res->src_sof_mask &= ~(1 << + src_info->dual_hw_ms_info.index); + ms_res->src_info[src_info->dual_hw_ms_info.index] = + NULL; + ms_res->num_src--; + src_info->dual_hw_ms_info.sync_state = + MSM_ISP_DUAL_CAM_ASYNC; + src_info->dual_hw_type = DUAL_NONE; + src_info->dual_hw_ms_info.index = -1; + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, + flags); + } if (i != VFE_PIX_0 || ext_read) continue; @@ -2520,152 +2585,6 @@ static int msm_isp_axi_update_cgc_override(struct vfe_device *vfe_dev_ioctl, return 0; } -static int msm_isp_update_dual_HW_ms_info_at_start( - struct vfe_device *vfe_dev, - enum msm_vfe_input_src stream_src) -{ - int rc = 0; - uint32_t j, k, max_sof = 0; - uint8_t slave_id; - struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; - struct msm_vfe_src_info *src_info = NULL; - uint32_t vfe_id = 0; - unsigned long flags; - - if (stream_src >= VFE_SRC_MAX) { - pr_err("%s: Error! Invalid src %u\n", __func__, stream_src); - return -EINVAL; - } - - src_info = &axi_data->src_info[stream_src]; - if (src_info->dual_hw_type != DUAL_HW_MASTER_SLAVE) - return rc; - - spin_lock_irqsave(&vfe_dev->common_data->common_dev_data_lock, flags); - if (src_info->dual_hw_ms_info.dual_hw_ms_type == - MS_TYPE_MASTER) { - if (vfe_dev->common_data->ms_resource.master_active == 1) { - spin_unlock_irqrestore(&vfe_dev->common_data-> - common_dev_data_lock, flags); - return rc; - } - - vfe_dev->common_data->ms_resource.master_active = 1; - - /* - * If any slaves are active, then find the max slave - * frame_id and set it to Master, so master will start - * higher and then the slave can copy master frame_id - * without repeating. - */ - if (!vfe_dev->common_data->ms_resource.slave_active_mask) { - spin_unlock_irqrestore(&vfe_dev->common_data-> - common_dev_data_lock, flags); - return rc; - } - - for (j = 0, k = 0; k < MS_NUM_SLAVE_MAX; k++) { - if (!(vfe_dev->common_data->ms_resource. - reserved_slave_mask & (1 << k))) - continue; - - if (vfe_dev->common_data->ms_resource.slave_active_mask - & (1 << k) && - (vfe_dev->common_data->ms_resource. - slave_sof_info[k].frame_id > max_sof)) { - max_sof = vfe_dev->common_data->ms_resource. - slave_sof_info[k].frame_id; - } - j++; - if (j == vfe_dev->common_data->ms_resource.num_slave) - break; - } - vfe_dev->axi_data.src_info[stream_src].frame_id = - max_sof + 1; - if (vfe_dev->is_split) { - vfe_id = vfe_dev->pdev->id; - vfe_id = (vfe_id == 0) ? 1 : 0; - vfe_dev->common_data->dual_vfe_res->axi_data[vfe_id]-> - src_info[stream_src].frame_id = max_sof + 1; - } - - ISP_DBG("%s: Setting Master frame_id to %u\n", __func__, - max_sof + 1); - } else { - if (src_info->dual_hw_ms_info.sof_info != NULL) { - slave_id = src_info->dual_hw_ms_info.slave_id; - vfe_dev->common_data->ms_resource.slave_active_mask |= - (1 << slave_id); - } - } - spin_unlock_irqrestore(&vfe_dev->common_data->common_dev_data_lock, - flags); - - return rc; -} - -static int msm_isp_update_dual_HW_ms_info_at_stop( - struct vfe_device *vfe_dev, - struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd) -{ - int i, rc = 0; - uint8_t slave_id; - struct msm_vfe_axi_stream *stream_info = NULL; - struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; - enum msm_vfe_input_src stream_src = VFE_SRC_MAX; - struct msm_vfe_src_info *src_info = NULL; - unsigned long flags; - - if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM || - stream_cfg_cmd->num_streams == 0) - return -EINVAL; - - for (i = 0; i < stream_cfg_cmd->num_streams; i++) { - if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= - VFE_AXI_SRC_MAX) { - return -EINVAL; - } - stream_info = msm_isp_get_stream_common_data(vfe_dev, - HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])); - stream_src = SRC_TO_INTF(stream_info->stream_src); - - /* Remove PIX if DISABLE CAMIF */ - if (stream_src == VFE_PIX_0 && - axi_data->src_info[VFE_PIX_0].active) - continue; - - src_info = &axi_data->src_info[stream_src]; - if (src_info->dual_hw_type != DUAL_HW_MASTER_SLAVE) - continue; - - spin_lock_irqsave( - &vfe_dev->common_data->common_dev_data_lock, - flags); - if (src_info->dual_hw_ms_info.dual_hw_ms_type == - MS_TYPE_MASTER) { - /* - * Once Master is inactive, slave will increment - * its own frame_id - */ - vfe_dev->common_data->ms_resource.master_active = 0; - } else { - slave_id = src_info->dual_hw_ms_info.slave_id; - vfe_dev->common_data->ms_resource.reserved_slave_mask &= - ~(1 << slave_id); - vfe_dev->common_data->ms_resource.slave_active_mask &= - ~(1 << slave_id); - vfe_dev->common_data->ms_resource.num_slave--; - } - src_info->dual_hw_ms_info.sof_info = NULL; - spin_unlock_irqrestore( - &vfe_dev->common_data->common_dev_data_lock, - flags); - vfe_dev->vfe_ub_policy = 0; - } - - return rc; -} - /** * msm_isp_axi_wait_for_stream_cfg_done() - Wait for a stream completion * @stream_info: The stream to wait on @@ -3126,7 +3045,7 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev_ioctl, int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg) { - int rc = 0, ret; + int rc = 0; struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg; uint32_t stream_idx[MAX_NUM_STREAM]; int i; @@ -3175,11 +3094,6 @@ int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg) * Use different ret value to not overwrite the error from * msm_isp_stop_axi_stream */ - ret = msm_isp_update_dual_HW_ms_info_at_stop( - vfe_dev, stream_cfg_cmd); - if (ret < 0) - pr_warn("%s: Warning! Update dual_cam failed\n", - __func__); if (vfe_dev->axi_data.num_active_stream == 0) vfe_dev->hvx_cmd = HVX_DISABLE; if (vfe_dev->is_split) { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 61b54dcd850d..59b875d6e464 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -202,17 +202,17 @@ void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp, struct vfe_device *vfe_dev) { struct timespec ts; + do_gettimeofday(&(time_stamp->event_time)); if (vfe_dev->vt_enable) { msm_isp_get_avtimer_ts(time_stamp); time_stamp->buf_time.tv_sec = time_stamp->vt_time.tv_sec; time_stamp->buf_time.tv_usec = time_stamp->vt_time.tv_usec; - } else { + } else { get_monotonic_boottime(&ts); time_stamp->buf_time.tv_sec = ts.tv_sec; time_stamp->buf_time.tv_usec = ts.tv_nsec/1000; } - } static inline u32 msm_isp_evt_mask_to_isp_event(u32 evt_mask) @@ -548,18 +548,53 @@ int msm_isp_cfg_input(struct vfe_device *vfe_dev, void *arg) return rc; } +static int msm_isp_dual_hw_master_slave_sync(struct vfe_device *vfe_dev, + void *arg) +{ + int rc = 0; + + struct msm_isp_dual_hw_master_slave_sync *link = arg; + unsigned long flags; + struct master_slave_resource_info *ms_res = + &vfe_dev->common_data->ms_resource; + int i; + struct msm_vfe_src_info *src_info = NULL; + + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, + flags); + ms_res->dual_sync_mode = link->sync_mode; + if (ms_res->dual_sync_mode == MSM_ISP_DUAL_CAM_ASYNC) { + for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { + if (ms_res->src_info[i] == NULL) + continue; + src_info = ms_res->src_info[i]; + if (src_info->dual_hw_ms_info.sync_state == + MSM_ISP_DUAL_CAM_ASYNC) + continue; + ms_res->active_src_mask &= ~(1 << + src_info->dual_hw_ms_info.index); + ms_res->src_sof_mask &= ~(1 << + src_info->dual_hw_ms_info.index); + src_info->dual_hw_ms_info.sync_state = + MSM_ISP_DUAL_CAM_ASYNC; + } + } + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, + flags); + return rc; +} + static int msm_isp_set_dual_HW_master_slave_mode( struct vfe_device *vfe_dev, void *arg) { - /* - * This method assumes no 2 processes are accessing it simultaneously. - * Currently this is guaranteed by mutex lock in ioctl. - * If that changes, need to revisit this - */ - int rc = 0, i, j; + int rc = 0, i; struct msm_isp_set_dual_hw_ms_cmd *dual_hw_ms_cmd = NULL; struct msm_vfe_src_info *src_info = NULL; unsigned long flags; + struct master_slave_resource_info *ms_res = + &vfe_dev->common_data->ms_resource; if (!vfe_dev || !arg) { pr_err("%s: Error! Invalid input vfe_dev %pK arg %pK\n", @@ -567,6 +602,7 @@ static int msm_isp_set_dual_HW_master_slave_mode( return -EINVAL; } + spin_lock_irqsave(&vfe_dev->common_data->common_dev_data_lock, flags); dual_hw_ms_cmd = (struct msm_isp_set_dual_hw_ms_cmd *)arg; vfe_dev->common_data->ms_resource.dual_hw_type = DUAL_HW_MASTER_SLAVE; vfe_dev->vfe_ub_policy = MSM_WM_UB_EQUAL_SLICING; @@ -575,50 +611,20 @@ static int msm_isp_set_dual_HW_master_slave_mode( vfe_dev->pdev->id, dual_hw_ms_cmd->primary_intf); src_info = &vfe_dev->axi_data. src_info[dual_hw_ms_cmd->primary_intf]; + src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE; src_info->dual_hw_ms_info.dual_hw_ms_type = dual_hw_ms_cmd->dual_hw_ms_type; - } - - /* No lock needed here since ioctl lock protects 2 session from race */ - if (src_info != NULL && - dual_hw_ms_cmd->dual_hw_ms_type == MS_TYPE_MASTER) { - src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE; - ISP_DBG("%s: vfe %d Master\n", __func__, vfe_dev->pdev->id); - - src_info->dual_hw_ms_info.sof_info = - &vfe_dev->common_data->ms_resource.master_sof_info; - vfe_dev->common_data->ms_resource.sof_delta_threshold = - dual_hw_ms_cmd->sof_delta_threshold; - } else if (src_info != NULL) { - spin_lock_irqsave( - &vfe_dev->common_data->common_dev_data_lock, - flags); - src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE; - ISP_DBG("%s: vfe %d Slave\n", __func__, vfe_dev->pdev->id); - - for (j = 0; j < MS_NUM_SLAVE_MAX; j++) { - if (vfe_dev->common_data->ms_resource. - reserved_slave_mask & (1 << j)) - continue; - - vfe_dev->common_data->ms_resource.reserved_slave_mask |= - (1 << j); - vfe_dev->common_data->ms_resource.num_slave++; - src_info->dual_hw_ms_info.sof_info = - &vfe_dev->common_data->ms_resource. - slave_sof_info[j]; - src_info->dual_hw_ms_info.slave_id = j; - ISP_DBG("%s: Slave id %d\n", __func__, j); - break; - } - spin_unlock_irqrestore( - &vfe_dev->common_data->common_dev_data_lock, - flags); - - if (j == MS_NUM_SLAVE_MAX) { - pr_err("%s: Error! Cannot find free aux resource\n", - __func__); - return -EBUSY; + src_info->dual_hw_ms_info.index = dual_hw_ms_cmd-> + primary_intf + VFE_SRC_MAX * vfe_dev->pdev->id; + ms_res->src_info[src_info->dual_hw_ms_info.index] = src_info; + ms_res->num_src++; + if (dual_hw_ms_cmd->dual_hw_ms_type == MS_TYPE_MASTER) { + ms_res->master_index = src_info->dual_hw_ms_info.index; + ms_res->sof_delta_threshold = + dual_hw_ms_cmd->sof_delta_threshold; + } else { + ms_res->primary_slv_idx = + src_info->dual_hw_ms_info.index; } } ISP_DBG("%s: vfe %d num_src %d\n", __func__, vfe_dev->pdev->id, @@ -630,6 +636,8 @@ static int msm_isp_set_dual_HW_master_slave_mode( if (dual_hw_ms_cmd->input_src[i] >= VFE_SRC_MAX) { pr_err("%s: Error! Invalid SRC param %d\n", __func__, dual_hw_ms_cmd->input_src[i]); + spin_unlock_irqrestore(&vfe_dev->common_data-> + common_dev_data_lock, flags); return -EINVAL; } ISP_DBG("%s: vfe %d src %d type %d\n", __func__, @@ -640,8 +648,13 @@ static int msm_isp_set_dual_HW_master_slave_mode( src_info->dual_hw_type = DUAL_HW_MASTER_SLAVE; src_info->dual_hw_ms_info.dual_hw_ms_type = dual_hw_ms_cmd->dual_hw_ms_type; + src_info->dual_hw_ms_info.index = dual_hw_ms_cmd-> + input_src[i] + VFE_SRC_MAX * vfe_dev->pdev->id; + ms_res->src_info[src_info->dual_hw_ms_info.index] = src_info; + ms_res->num_src++; } - + spin_unlock_irqrestore(&vfe_dev->common_data->common_dev_data_lock, + flags); return rc; } @@ -909,6 +922,11 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, rc = msm_isp_set_dual_HW_master_slave_mode(vfe_dev, arg); mutex_unlock(&vfe_dev->core_mutex); break; + case VIDIOC_MSM_ISP_DUAL_HW_MASTER_SLAVE_SYNC: + mutex_lock(&vfe_dev->core_mutex); + rc = msm_isp_dual_hw_master_slave_sync(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); + break; case VIDIOC_MSM_ISP_FETCH_ENG_START: case VIDIOC_MSM_ISP_MAP_BUF_START_FE: mutex_lock(&vfe_dev->core_mutex); diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h index e4d41d4072c5..9399f6e84004 100644 --- a/include/uapi/media/msmb_isp.h +++ b/include/uapi/media/msmb_isp.h @@ -819,6 +819,16 @@ struct msm_isp_ahb_clk_cfg { uint32_t reserved[2]; }; +enum msm_vfe_dual_cam_sync_mode { + MSM_ISP_DUAL_CAM_ASYNC, + MSM_ISP_DUAL_CAM_SYNC, +}; + +struct msm_isp_dual_hw_master_slave_sync { + uint32_t sync_mode; + uint32_t reserved[2]; +}; + #define V4L2_PIX_FMT_QBGGR8 v4l2_fourcc('Q', 'B', 'G', '8') #define V4L2_PIX_FMT_QGBRG8 v4l2_fourcc('Q', 'G', 'B', '8') #define V4L2_PIX_FMT_QGRBG8 v4l2_fourcc('Q', 'G', 'R', '8') @@ -981,6 +991,10 @@ enum msm_isp_ioctl_cmd_code { #define VIDIOC_MSM_ISP_AHB_CLK_CFG \ _IOWR('V', BASE_VIDIOC_PRIVATE+25, struct msm_isp_ahb_clk_cfg) +#define VIDIOC_MSM_ISP_DUAL_HW_MASTER_SLAVE_SYNC \ + _IOWR('V', BASE_VIDIOC_PRIVATE+26, \ + struct msm_isp_dual_hw_master_slave_sync) + #define VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START \ _IOWR('V', MSM_ISP_FETCH_ENG_MULTI_PASS_START, \ struct msm_vfe_fetch_eng_multi_pass_start) |
