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

Commit 9a3869ce authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm:camera: Add support for AV time stamp for VT call"

parents 2484b664 4a8052a6
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/avtimer.h>
#include <media/v4l2-subdev.h>
#include <media/msmb_isp.h>
#include <mach/msm_bus.h>
@@ -35,6 +36,10 @@
#define MAX_INIT_FRAME_DROP 31
#define ISP_Q2 (1 << 2)

#define AVTIMER_MSW_PHY_ADDR 0xFE05300C
#define AVTIMER_LSW_PHY_ADDR 0xFE053008
#define AVTIMER_ITERATION_CTR 16

#define VFE_PING_FLAG 0xFFFFFFFF
#define VFE_PONG_FLAG 0x0

@@ -69,6 +74,8 @@ enum msm_isp_camif_update_state {
struct msm_isp_timestamp {
	/*Monotonic clock for v4l2 buffer*/
	struct timeval buf_time;
	/*Monotonic clock for VT */
	struct timeval vt_time;
	/*Wall clock for userspace event*/
	struct timeval event_time;
};
@@ -264,7 +271,7 @@ struct msm_vfe_axi_stream {
	uint32_t stream_handle;
	uint8_t buf_divert;
	enum msm_vfe_axi_stream_type stream_type;

	uint32_t vt_enable;
	uint32_t frame_based;
	uint32_t framedrop_period;
	uint32_t framedrop_pattern;
@@ -437,6 +444,9 @@ struct vfe_device {
	int dump_reg;
	int vfe_clk_idx;
	uint32_t vfe_open_cnt;
	uint8_t vt_enable;
	void __iomem *p_avtimer_msw;
	void __iomem *p_avtimer_lsw;
};

#endif
+29 −4
Original line number Diff line number Diff line
@@ -485,6 +485,19 @@ void msm_isp_calculate_bandwidth(
	}
}

#ifdef CONFIG_MSM_AVTIMER
void msm_isp_start_avtimer(void)
{
	avcs_core_open();
	avcs_core_disable_power_collapse(1);
}
#else
void msm_isp_start_avtimer(void)
{
	pr_err("AV Timer is not supported\n");
}
#endif

int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
{
	int rc = 0, i;
@@ -528,7 +541,13 @@ int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
	}

	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);

	stream_info->vt_enable = stream_cfg_cmd->vt_enable;
	if (stream_info->vt_enable) {
		vfe_dev->vt_enable = stream_info->vt_enable;
		msm_isp_start_avtimer();
		vfe_dev->p_avtimer_lsw = ioremap(AVTIMER_LSW_PHY_ADDR, 4);
		vfe_dev->p_avtimer_msw = ioremap(AVTIMER_MSW_PHY_ADDR, 4);
	}
	if (stream_info->num_planes > 1) {
		msm_isp_axi_reserve_comp_mask(
			&vfe_dev->axi_data, stream_info);
@@ -787,16 +806,22 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
{
	int rc;
	struct msm_isp_event_data buf_event;
	struct timeval *time_stamp;
	uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
	uint32_t frame_id = vfe_dev->axi_data.
		src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id;
	memset(&buf_event, 0, sizeof(buf_event));

	if (buf && ts) {
		if (vfe_dev->vt_enable) {
			time_stamp = &ts->vt_time;
		} else {
			time_stamp = &ts->buf_time;
		}
		if (stream_info->buf_divert) {
			rc = vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
				buf->bufq_handle, buf->buf_idx,
				&ts->buf_time, frame_id);
				time_stamp, frame_id);
			/* Buf divert return value represent whether the buf
			 * can be diverted. A positive return value means
			 * other ISP hardware is still processing the frame.
@@ -805,7 +830,7 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
				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.timestamp = *time_stamp;
				buf_event.u.buf_done.session_id =
					stream_info->session_id;
				buf_event.u.buf_done.stream_id =
@@ -834,7 +859,7 @@ static void msm_isp_process_done_buf(struct vfe_device *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,
				&ts->buf_time, frame_id,
				time_stamp, frame_id,
				stream_info->runtime_output_format);
		}
	}
+47 −0
Original line number Diff line number Diff line
@@ -193,6 +193,30 @@ static inline void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp)
	do_gettimeofday(&(time_stamp->event_time));
}

static inline void msm_isp_get_vt_tstamp(struct vfe_device *vfe_dev,
	struct msm_isp_timestamp *time_stamp)
{
	uint32_t avtimer_msw_1st = 0, avtimer_lsw = 0;
	uint32_t avtimer_msw_2nd = 0;
	uint8_t iter = 0;
	if (!vfe_dev->p_avtimer_msw || !vfe_dev->p_avtimer_lsw) {
		pr_err("%s: ioremap failed\n", __func__);
		return;
	}
	do {
		avtimer_msw_1st = msm_camera_io_r(vfe_dev->p_avtimer_msw);
		avtimer_lsw = msm_camera_io_r(vfe_dev->p_avtimer_lsw);
		avtimer_msw_2nd = msm_camera_io_r(vfe_dev->p_avtimer_msw);
	} while ((avtimer_msw_1st != avtimer_msw_2nd)
		&& (iter++ < AVTIMER_ITERATION_CTR));
	if (iter >= AVTIMER_ITERATION_CTR) {
		pr_err("%s: AVTimer MSW TS did not converge !!!\n", __func__);
		return;
	}
	time_stamp->vt_time.tv_sec = avtimer_msw_1st;
	time_stamp->vt_time.tv_usec = avtimer_lsw;
}

int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
	struct v4l2_event_subscription *sub)
{
@@ -885,6 +909,8 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data)
	queue_cmd->vfeInterruptStatus0 = irq_status0;
	queue_cmd->vfeInterruptStatus1 = irq_status1;
	msm_isp_get_timestamp(&queue_cmd->ts);
	if (vfe_dev->vt_enable)
		msm_isp_get_vt_tstamp(vfe_dev, &queue_cmd->ts);
	queue_cmd->cmd_used = 1;
	vfe_dev->taskletq_idx =
		(vfe_dev->taskletq_idx + 1) % MSM_VFE_TASKLETQ_SIZE;
@@ -998,11 +1024,26 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
	vfe_dev->vfe_open_cnt++;
	vfe_dev->taskletq_idx = 0;
	vfe_dev->vt_enable = 0;
	vfe_dev->p_avtimer_lsw = NULL;
	vfe_dev->p_avtimer_msw = NULL;
	mutex_unlock(&vfe_dev->core_mutex);
	mutex_unlock(&vfe_dev->realtime_mutex);
	return 0;
}

#ifdef CONFIG_MSM_AVTIMER
void msm_isp_end_avtimer(void)
{
	avcs_core_disable_power_collapse(0);
}
#else
void msm_isp_end_avtimer(void)
{
	pr_err("AV Timer is not supported\n");
}
#endif

int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
	long rc;
@@ -1024,6 +1065,12 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
	vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
	vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
	vfe_dev->vfe_open_cnt--;
	if (vfe_dev->vt_enable) {
		iounmap(vfe_dev->p_avtimer_lsw);
		iounmap(vfe_dev->p_avtimer_msw);
		msm_isp_end_avtimer();
		vfe_dev->vt_enable = 0;
	}
	mutex_unlock(&vfe_dev->core_mutex);
	mutex_unlock(&vfe_dev->realtime_mutex);
	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ struct msm_vfe_axi_plane_cfg {
struct msm_vfe_axi_stream_request_cmd {
	uint32_t session_id;
	uint32_t stream_id;
	uint32_t vt_enable;
	uint32_t output_format;/*Planar/RAW/Misc*/
	enum msm_vfe_axi_stream_src stream_src; /*CAMIF/IDEAL/RDIs*/
	struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM];