Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a048a234 authored by Konstantin Motov's avatar Konstantin Motov
Browse files

msm: camera: Add support for more than one buffer per HW stream



Add support to use more than one buffer queue per HW stream. This
functionality could be use only for controllable outputs. Using
frame request iocltl user specified from which queue buffer will
be got.

Change-Id: Ic1b9c2379bd9c96584c9ad27b41f77042f6bceb9
Signed-off-by: default avatarKonstantin Motov <kmotov@codeaurora.org>
parent c5353f99
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;
+244 −230
Original line number Diff line number Diff line
@@ -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;
}

@@ -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)
@@ -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;
}
@@ -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) {
@@ -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]++;
@@ -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;
@@ -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,
@@ -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);
@@ -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,
@@ -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__);
@@ -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__);
@@ -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);
@@ -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;
			}

@@ -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)
@@ -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)
@@ -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: {
@@ -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;
@@ -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);
@@ -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)) {
@@ -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);
+9 −1
Original line number Diff line number Diff line
@@ -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 {
@@ -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];
};