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

Commit b9861f1c authored by Sreesudhan Ramakrish Ramkumar's avatar Sreesudhan Ramakrish Ramkumar
Browse files

msm: camera: isp: Fix composite stats irq handling



If more than one stats irq are composite together, callback for both
stats should be sent only after composite stats irq is received.
Currently there is a bug due to which stats callback was called
even if one of the stats irq that is part of composite is received.
Fix bug by handling composite and non composite irq separately.

Change-Id: I8cd0c857ff6c8271e450ee3ecc2eaa3cf2866508
Signed-off-by: default avatarSreesudhan Ramakrish Ramkumar <srramku@codeaurora.org>
parent 18c43109
Loading
Loading
Loading
Loading
+119 −78
Original line number Original line Diff line number Diff line
@@ -67,78 +67,31 @@ buf_error:
	return rc;
	return rc;
}
}


void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
	uint32_t irq_status0, uint32_t irq_status1,
	struct msm_isp_buffer *done_buf, struct msm_isp_timestamp *ts,
	struct msm_isp_timestamp *ts)
	struct msm_isp_event_data *buf_event,
	struct msm_vfe_stats_stream *stream_info,
	uint32_t *comp_stats_type_mask)
{
{
	int i, j, rc;
	int32_t rc = 0;
	struct msm_isp_event_data buf_event;
	struct msm_isp_stats_event *stats_event = NULL;
	struct msm_isp_stats_event *stats_event = &buf_event.u.stats;

	struct msm_isp_buffer *done_buf;
	if (!vfe_dev || !done_buf || !ts || !buf_event || !stream_info ||
	struct msm_vfe_stats_stream *stream_info = NULL;
		!comp_stats_type_mask) {
	uint32_t pingpong_status;
		pr_err("%s:%d failed: invalid params %p %p %p %p %p %p\n",
	uint32_t comp_stats_type_mask = 0, atomic_stats_mask = 0;
			__func__, __LINE__, vfe_dev, done_buf, ts, buf_event,
	uint32_t stats_comp_mask = 0, stats_irq_mask = 0;
			stream_info, comp_stats_type_mask);
	uint32_t num_stats_comp_mask =
		return -EINVAL;
		vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask;
	stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
		get_comp_mask(irq_status0, irq_status1);
	stats_irq_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
		get_wm_mask(irq_status0, irq_status1);
	if (!(stats_comp_mask || stats_irq_mask))
		return;
	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);

	/*
	 * If any of composite mask is set, clear irq bits from mask,
	 * they will be restored by comp mask
	 */
	if (stats_comp_mask) {
		for (j = 0; j < num_stats_comp_mask; j++) {
			stats_irq_mask &= ~atomic_read(
				&vfe_dev->stats_data.stats_comp_mask[j]);
		}
	}

	for (j = 0; j < num_stats_comp_mask; j++) {
		atomic_stats_mask = atomic_read(
			&vfe_dev->stats_data.stats_comp_mask[j]);
		if (!stats_comp_mask) {
			stats_irq_mask &= ~atomic_stats_mask;
		} else {
			/* restore irq bits from composite mask */
			if (stats_comp_mask & (1 << j))
				stats_irq_mask |= atomic_stats_mask;
	}
	}
		/* if no irq bits set from this composite mask continue*/
		if (!stats_irq_mask)
			continue;
		memset(&buf_event, 0, sizeof(struct msm_isp_event_data));
		buf_event.timestamp = ts->event_time;
		buf_event.frame_id =
			vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
		buf_event.input_intf = VFE_PIX_0;
		pingpong_status = vfe_dev->hw_info->
			vfe_ops.stats_ops.get_pingpong_status(vfe_dev);

		for (i = 0; i < vfe_dev->hw_info->stats_hw_info->num_stats_type;
			i++) {
			if (!(stats_irq_mask & (1 << i)))
				continue;


			stats_irq_mask &= ~(1 << i);
	stats_event = &buf_event->u.stats;
			stream_info = &vfe_dev->stats_data.stream_info[i];
			done_buf = NULL;
			msm_isp_stats_cfg_ping_pong_address(vfe_dev,
				stream_info, pingpong_status, &done_buf);
			if (done_buf) {
	rc = vfe_dev->buf_mgr->ops->buf_divert(
	rc = vfe_dev->buf_mgr->ops->buf_divert(
		vfe_dev->buf_mgr, done_buf->bufq_handle,
		vfe_dev->buf_mgr, done_buf->bufq_handle,
		done_buf->buf_idx, &ts->buf_time,
		done_buf->buf_idx, &ts->buf_time,
		vfe_dev->axi_data.
		vfe_dev->axi_data.
		src_info[VFE_PIX_0].frame_id);
		src_info[VFE_PIX_0].frame_id);
	if (rc != 0)
	if (rc != 0)
					continue;
		return rc;


	stats_event->stats_buf_idxs
	stats_event->stats_buf_idxs
		[stream_info->stats_type] =
		[stream_info->stats_type] =
@@ -147,16 +100,53 @@ void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
		stats_event->stats_mask =
		stats_event->stats_mask =
			1 << stream_info->stats_type;
			1 << stream_info->stats_type;
		ISP_DBG("%s: stats frameid: 0x%x %d\n",
		ISP_DBG("%s: stats frameid: 0x%x %d\n",
						__func__, buf_event.frame_id,
			__func__, buf_event->frame_id,
			stream_info->stats_type);
			stream_info->stats_type);
		msm_isp_send_event(vfe_dev,
		msm_isp_send_event(vfe_dev,
			ISP_EVENT_STATS_NOTIFY +
			ISP_EVENT_STATS_NOTIFY +
			stream_info->stats_type,
			stream_info->stats_type,
						&buf_event);
			buf_event);
	} else {
	} else {
					comp_stats_type_mask |=
		*comp_stats_type_mask |=
			1 << stream_info->stats_type;
			1 << stream_info->stats_type;
	}
	}

	return 0;
}

static int32_t msm_isp_stats_configure(struct vfe_device *vfe_dev,
	uint32_t stats_irq_mask, struct msm_isp_timestamp *ts)
{
	int i, rc = 0;
	struct msm_isp_event_data buf_event;
	struct msm_isp_stats_event *stats_event = &buf_event.u.stats;
	struct msm_isp_buffer *done_buf;
	struct msm_vfe_stats_stream *stream_info = NULL;
	uint32_t pingpong_status;
	uint32_t comp_stats_type_mask = 0;

	memset(&buf_event, 0, sizeof(struct msm_isp_event_data));
	buf_event.timestamp = ts->event_time;
	buf_event.frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
	buf_event.input_intf = VFE_PIX_0;
	pingpong_status = vfe_dev->hw_info->
		vfe_ops.stats_ops.get_pingpong_status(vfe_dev);

	for (i = 0; i < vfe_dev->hw_info->stats_hw_info->num_stats_type; i++) {
		if (!(stats_irq_mask & (1 << i)))
			continue;

		stream_info = &vfe_dev->stats_data.stream_info[i];
		done_buf = NULL;
		msm_isp_stats_cfg_ping_pong_address(vfe_dev,
			stream_info, pingpong_status, &done_buf);
		if (done_buf) {
			rc = msm_isp_stats_buf_divert(vfe_dev, done_buf, ts,
				&buf_event, stream_info, &comp_stats_type_mask);
			if (rc < 0) {
				pr_err("%s:%d failed: stats buf divert rc %d\n",
					__func__, __LINE__, rc);
			}
		}
		}
	}
	}


@@ -169,6 +159,57 @@ void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
			ISP_EVENT_COMP_STATS_NOTIFY, &buf_event);
			ISP_EVENT_COMP_STATS_NOTIFY, &buf_event);
		comp_stats_type_mask = 0;
		comp_stats_type_mask = 0;
	}
	}
	return rc;
}

void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
	uint32_t irq_status0, uint32_t irq_status1,
	struct msm_isp_timestamp *ts)
{
	int j, rc;
	uint32_t atomic_stats_mask = 0;
	uint32_t stats_comp_mask = 0, stats_irq_mask = 0;
	uint32_t num_stats_comp_mask =
		vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask;
	stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
		get_comp_mask(irq_status0, irq_status1);
	stats_irq_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
		get_wm_mask(irq_status0, irq_status1);
	if (!(stats_comp_mask || stats_irq_mask))
		return;
	ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);

	/* Clear composite mask irq bits, they will be restored by comp mask */
	for (j = 0; j < num_stats_comp_mask; j++) {
		stats_irq_mask &= ~atomic_read(
			&vfe_dev->stats_data.stats_comp_mask[j]);
	}

	/* Process non-composite irq */
	if (stats_irq_mask) {
		rc = msm_isp_stats_configure(vfe_dev, stats_irq_mask, ts);
		if (rc < 0) {
			pr_err("%s:%d failed individual stats rc %d\n",
				__func__, __LINE__, rc);
		}
	}

	/* Process composite irq */
	if (stats_comp_mask) {
		for (j = 0; j < num_stats_comp_mask; j++) {
			if (!(stats_comp_mask & (1 << j)))
				continue;

			atomic_stats_mask = atomic_read(
				&vfe_dev->stats_data.stats_comp_mask[j]);

			rc = msm_isp_stats_configure(vfe_dev, atomic_stats_mask,
				ts);
			if (rc < 0) {
				pr_err("%s:%d failed comp stats %d rc %d\n",
					__func__, __LINE__, j, rc);
			}
		}
	}
	}
}
}