summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-07-13 15:44:52 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-07-13 15:44:52 -0700
commitafc9724015d6860fdf7272914e6f1dcd366d8bcd (patch)
tree2af6ed24bb01e56e3d2e6823513cd0902f1527fb
parent8013c761da8536c29b2cab571fd2e816a9e591d5 (diff)
parent36edcc0d58a8c96659901dbf539e45f018a43906 (diff)
Merge "msm: camera: isp: Fix RDI stream streamoff issue"
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c3
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c159
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c9
4 files changed, 129 insertions, 44 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 95465fb24feb..763b6a575326 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -40,6 +40,7 @@
#define VFE40_8952_VERSION 0x10060000
#define VFE40_8976_VERSION 0x10050000
#define VFE40_8937_VERSION 0x10080000
+#define VFE40_8917_VERSION 0x10080001
#define VFE40_8953_VERSION 0x10090000
#define VFE32_8909_VERSION 0x30600
@@ -652,6 +653,7 @@ struct dual_vfe_resource {
struct msm_vfe_stats_shared_data *stats_data[MAX_VFE];
struct msm_vfe_axi_shared_data *axi_data[MAX_VFE];
uint32_t wm_reload_mask[MAX_VFE];
+ uint32_t epoch_sync_mask;
};
struct master_slave_resource_info {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index d4f0453d72ff..a76ccc06c9e1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -326,6 +326,7 @@ static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
break;
case VFE40_8937_VERSION:
case VFE40_8953_VERSION:
+ case VFE40_8917_VERSION:
default:
ISP_DBG("%s: No special QOS\n", __func__);
}
@@ -1475,6 +1476,7 @@ static void msm_vfe40_axi_cfg_wm_reg(
wm_bit_shift = VFE40_WM_BIT_SHIFT;
} else if (vfe_dev->vfe_hw_version == VFE40_8976_VERSION ||
vfe_dev->vfe_hw_version == VFE40_8937_VERSION ||
+ vfe_dev->vfe_hw_version == VFE40_8917_VERSION ||
vfe_dev->vfe_hw_version == VFE40_8953_VERSION) {
burst_len = VFE40_BURST_LEN_8952_VERSION;
wm_bit_shift = VFE40_WM_BIT_SHIFT_8976_VERSION;
@@ -1986,6 +1988,7 @@ static void msm_vfe40_stats_cfg_ub(struct vfe_device *vfe_dev)
if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION ||
vfe_dev->vfe_hw_version == VFE40_8939_VERSION ||
vfe_dev->vfe_hw_version == VFE40_8937_VERSION ||
+ vfe_dev->vfe_hw_version == VFE40_8917_VERSION ||
vfe_dev->vfe_hw_version == VFE40_8953_VERSION) {
stats_burst_len = VFE40_STATS_BURST_LEN_8916_VERSION;
ub_offset = VFE40_UB_SIZE_8916;
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 fbac6d81ded0..3dd55e02826d 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
@@ -540,6 +540,89 @@ static void msm_isp_cfg_framedrop_reg(struct vfe_device *vfe_dev,
}
/**
+ * msm_isp_check_epoch_status() - check the epock signal for framedrop
+ *
+ * @vfe_dev: The h/w on which the epoch signel is reveived
+ * @frame_src: The source of the epoch signal for this frame
+ *
+ * For dual vfe case and pixel stream, if both vfe's epoch signal is
+ * received, this function will return success.
+ * It will also return the vfe1 for further process
+ * For none dual VFE stream or none pixl source, this
+ * funciton will just return success.
+ *
+ * Returns 1 - epoch received is complete.
+ * 0 - epoch reveived is not complete.
+ */
+static int msm_isp_check_epoch_status(struct vfe_device **vfe_dev,
+ enum msm_vfe_input_src frame_src)
+{
+ struct vfe_device *vfe_dev_cur = *vfe_dev;
+ struct vfe_device *vfe_dev_other = NULL;
+ uint32_t vfe_id_other = 0;
+ uint32_t vfe_id_cur = 0;
+ uint32_t epoch_mask = 0;
+ unsigned long flags;
+ int completed = 0;
+
+ spin_lock_irqsave(
+ &vfe_dev_cur->common_data->common_dev_data_lock, flags);
+
+ if (vfe_dev_cur->is_split &&
+ frame_src == VFE_PIX_0) {
+ if (vfe_dev_cur->pdev->id == ISP_VFE0) {
+ vfe_id_cur = ISP_VFE0;
+ vfe_id_other = ISP_VFE1;
+ } else {
+ vfe_id_cur = ISP_VFE1;
+ vfe_id_other = ISP_VFE0;
+ }
+ vfe_dev_other = vfe_dev_cur->common_data->dual_vfe_res->
+ vfe_dev[vfe_id_other];
+
+ if (vfe_dev_cur->common_data->dual_vfe_res->
+ epoch_sync_mask & (1 << vfe_id_cur)) {
+ /* serious scheduling delay */
+ pr_err("Missing epoch: vfe %d, epoch mask 0x%x\n",
+ vfe_dev_cur->pdev->id,
+ vfe_dev_cur->common_data->dual_vfe_res->
+ epoch_sync_mask);
+ goto fatal;
+ }
+
+ vfe_dev_cur->common_data->dual_vfe_res->
+ epoch_sync_mask |= (1 << vfe_id_cur);
+
+ epoch_mask = (1 << vfe_id_cur) | (1 << vfe_id_other);
+ if ((vfe_dev_cur->common_data->dual_vfe_res->
+ epoch_sync_mask & epoch_mask) == epoch_mask) {
+
+ if (vfe_id_other == ISP_VFE0)
+ *vfe_dev = vfe_dev_cur;
+ else
+ *vfe_dev = vfe_dev_other;
+
+ vfe_dev_cur->common_data->dual_vfe_res->
+ epoch_sync_mask &= ~epoch_mask;
+ completed = 1;
+ }
+ } else
+ completed = 1;
+
+ spin_unlock_irqrestore(
+ &vfe_dev_cur->common_data->common_dev_data_lock, flags);
+
+ return completed;
+fatal:
+ spin_unlock_irqrestore(
+ &vfe_dev_cur->common_data->common_dev_data_lock, flags);
+ /* new error event code will be added later */
+ msm_isp_halt_send_error(vfe_dev_cur, ISP_EVENT_PING_PONG_MISMATCH);
+ return 0;
+}
+
+
+/**
* msm_isp_update_framedrop_reg() - Update frame period pattern on h/w
* @vfe_dev: The h/w on which the perion pattern is updated.
* @frame_src: Input source.
@@ -554,10 +637,15 @@ void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev,
enum msm_vfe_input_src frame_src)
{
int i;
- struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+ struct msm_vfe_axi_shared_data *axi_data = NULL;
struct msm_vfe_axi_stream *stream_info;
unsigned long flags;
+ if (msm_isp_check_epoch_status(&vfe_dev, frame_src) != 1)
+ return;
+
+ axi_data = &vfe_dev->axi_data;
+
for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
if (SRC_TO_INTF(axi_data->stream_info[i].stream_src) !=
frame_src) {
@@ -1937,6 +2025,13 @@ static void msm_isp_get_camif_update_state_and_halt(
pix_stream_cnt++;
}
+ if (vfe_dev->axi_data.num_active_stream == stream_cfg_cmd->num_streams
+ && (stream_cfg_cmd->cmd == STOP_STREAM ||
+ stream_cfg_cmd->cmd == STOP_IMMEDIATELY))
+ *halt = 1;
+ else
+ *halt = 0;
+
if ((pix_stream_cnt) &&
(axi_data->src_info[VFE_PIX_0].input_mux != EXTERNAL_READ)) {
if (cur_pix_stream_cnt == 0 && pix_stream_cnt &&
@@ -1944,24 +2039,17 @@ static void msm_isp_get_camif_update_state_and_halt(
*camif_update = ENABLE_CAMIF;
else if (cur_pix_stream_cnt &&
(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
- stream_cfg_cmd->cmd == STOP_STREAM)
- *camif_update = DISABLE_CAMIF;
- else if (cur_pix_stream_cnt &&
- (cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
- stream_cfg_cmd->cmd == STOP_IMMEDIATELY)
- *camif_update = DISABLE_CAMIF_IMMEDIATELY;
+ (stream_cfg_cmd->cmd == STOP_STREAM ||
+ stream_cfg_cmd->cmd == STOP_IMMEDIATELY)) {
+ if (*halt)
+ *camif_update = DISABLE_CAMIF_IMMEDIATELY;
+ else
+ *camif_update = DISABLE_CAMIF;
+ }
else
*camif_update = NO_UPDATE;
} else
*camif_update = NO_UPDATE;
-
- if (vfe_dev->axi_data.num_active_stream == stream_cfg_cmd->num_streams
- && (stream_cfg_cmd->cmd == STOP_STREAM ||
- stream_cfg_cmd->cmd == STOP_IMMEDIATELY))
- *halt = 1;
- else
- *halt = 0;
-
}
static void msm_isp_update_camif_output_count(
@@ -2584,6 +2672,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
vfe_dev->hw_info->vfe_ops.core_ops.
update_camif_state(vfe_dev, camif_update);
vfe_dev->axi_data.camif_state = CAMIF_ENABLE;
+ vfe_dev->common_data->dual_vfe_res->epoch_sync_mask = 0;
}
if (wait_for_complete) {
@@ -2645,34 +2734,20 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
wait_for_complete_for_this_stream = 0;
stream_info->state = STOP_PENDING;
- ISP_DBG("Stop axi Stream 0x%x\n", stream_info->stream_id);
- if (stream_info->stream_src == CAMIF_RAW ||
- stream_info->stream_src == IDEAL_RAW) {
- /* We dont get reg update IRQ for raw snapshot
- * so frame skip cant be ocnfigured
- */
- if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) &&
- (!ext_read))
- wait_for_complete_for_this_stream = 1;
-
- } else if (stream_info->stream_type == BURST_STREAM &&
- stream_info->runtime_num_burst_capture == 0) {
- /* Configure AXI writemasters to stop immediately
- * since for burst case, write masters already skip
- * all frames.
- */
- if (stream_info->stream_src == RDI_INTF_0 ||
- stream_info->stream_src == RDI_INTF_1 ||
- stream_info->stream_src == RDI_INTF_2)
- wait_for_complete_for_this_stream = 1;
- } else {
- if ((camif_update != DISABLE_CAMIF_IMMEDIATELY) &&
- !halt && (!ext_read))
- wait_for_complete_for_this_stream = 1;
- }
- ISP_DBG("%s: vfe_dev %d camif_update %d halt %d wait %d\n",
- __func__, vfe_dev->pdev->id, camif_update, halt,
+
+ if (!halt && !ext_read &&
+ !(stream_info->stream_type == BURST_STREAM &&
+ stream_info->runtime_num_burst_capture == 0))
+ wait_for_complete_for_this_stream = 1;
+
+ ISP_DBG("%s: stream 0x%x, vfe %d camif %d halt %d wait %d\n",
+ __func__,
+ stream_info->stream_id,
+ vfe_dev->pdev->id,
+ camif_update,
+ halt,
wait_for_complete_for_this_stream);
+
intf = SRC_TO_INTF(stream_info->stream_src);
if (!wait_for_complete_for_this_stream ||
stream_info->state == INACTIVE ||
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 460746089c53..5b12c1239bf4 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
@@ -1917,11 +1917,16 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
ISP_DBG("%s open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
- if (vfe_dev->common_data == NULL) {
- pr_err("%s: Error in probe. No common_data\n", __func__);
+ if (vfe_dev->common_data == NULL ||
+ vfe_dev->common_data->dual_vfe_res == NULL) {
+ pr_err("%s: Error in probe. No common_data or dual vfe res\n",
+ __func__);
return -EINVAL;
}
+ if (vfe_dev->pdev->id == ISP_VFE0)
+ vfe_dev->common_data->dual_vfe_res->epoch_sync_mask = 0;
+
mutex_lock(&vfe_dev->realtime_mutex);
mutex_lock(&vfe_dev->core_mutex);