summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h21
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c438
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c120
-rw-r--r--include/uapi/media/msmb_isp.h14
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)