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

Commit 643c7c3e authored by Karthik Anantha Ram's avatar Karthik Anantha Ram Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Obtain timestamp as part of frame header



In use-cases that involve custom HW retrieve the timestamp
for shutter from frame header as opposed to csid registers.

CRs-Fixed: 2524308
Change-Id: I5de789cf939546affbfe6d537d8090982f39189d
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
parent 1c478e75
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_HW_MGR_INTF_H_
@@ -101,6 +101,8 @@ struct cam_hw_done_event_data {
 * @num_acq:               Total number of acquire in the payload
 * @acquire_info:          Acquired resource array pointer
 * @ctxt_to_hw_map:        HW context (returned)
 * @custom_enabled:        ctx has custom enabled
 * @use_frame_header_ts:   Use frame header for qtimer ts
 * @acquired_hw_id:        Acquired hardware mask
 * @acquired_hw_path:      Acquired path mask for an input
 *                         if input splits into multiple paths,
@@ -115,6 +117,8 @@ struct cam_hw_acquire_args {
	uint32_t                     acquire_info_size;
	uintptr_t                    acquire_info;
	void                        *ctxt_to_hw_map;
	bool                         custom_enabled;
	bool                         use_frame_header_ts;

	uint32_t    acquired_hw_id[CAM_MAX_ACQ_RES];
	uint32_t    acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT];
+83 −15
Original line number Diff line number Diff line
@@ -251,6 +251,7 @@ static int __cam_isp_ctx_enqueue_init_request(
	struct cam_ctx_request                *req_old;
	struct cam_isp_ctx_req                *req_isp_old;
	struct cam_isp_ctx_req                *req_isp_new;
	struct cam_isp_prepare_hw_update_data *hw_update_data;

	spin_lock_bh(&ctx->lock);
	if (list_empty(&ctx->pending_req_list)) {
@@ -302,6 +303,13 @@ static int __cam_isp_ctx_enqueue_init_request(
			memcpy(&req_old->pf_data, &req->pf_data,
				sizeof(struct cam_hw_mgr_dump_pf_data));

			/* Update frame header params for EPCR */
			hw_update_data = &req_isp_new->hw_update_data;
			req_isp_old->hw_update_data.frame_header_res_id =
				req_isp_new->hw_update_data.frame_header_res_id;
			req_isp_old->hw_update_data.frame_header_cpu_addr =
				hw_update_data->frame_header_cpu_addr;

			req_old->request_id = req->request_id;

			list_add_tail(&req->list, &ctx->free_req_list);
@@ -428,9 +436,9 @@ static void __cam_isp_ctx_send_sof_boot_timestamp(
	req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta;

	CAM_DBG(CAM_ISP,
		"request id:%lld frame number:%lld boot time stamp:0x%llx",
		"request id:%lld frame number:%lld boot time stamp:0x%llx status:%u",
		 request_id, ctx_isp->frame_id,
		 ctx_isp->boot_timestamp);
		 ctx_isp->boot_timestamp, sof_event_status);

	if (cam_req_mgr_notify_message(&req_msg,
		V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS,
@@ -440,6 +448,41 @@ static void __cam_isp_ctx_send_sof_boot_timestamp(
			request_id);
}

static void __cam_isp_ctx_send_sof_timestamp_frame_header(
	struct cam_isp_context *ctx_isp, uint32_t *frame_header_cpu_addr,
	uint64_t request_id, uint32_t sof_event_status)
{
	uint32_t *time32 = NULL;
	uint64_t timestamp = 0;
	struct cam_req_mgr_message   req_msg;

	time32 = frame_header_cpu_addr;
	timestamp = (uint64_t) time32[1];
	timestamp = timestamp << 24;
	timestamp |= (uint64_t)(time32[0] >> 8);
	timestamp = mul_u64_u32_div(timestamp,
			CAM_IFE_QTIMER_MUL_FACTOR,
			CAM_IFE_QTIMER_DIV_FACTOR);

	ctx_isp->sof_timestamp_val = timestamp;
	req_msg.session_hdl = ctx_isp->base->session_hdl;
	req_msg.u.frame_msg.frame_id = ctx_isp->frame_id;
	req_msg.u.frame_msg.request_id = request_id;
	req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val;
	req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
	req_msg.u.frame_msg.sof_status = sof_event_status;

	CAM_DBG(CAM_ISP,
		"request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u",
		 request_id, ctx_isp->frame_id,
		ctx_isp->sof_timestamp_val, sof_event_status);

	if (cam_req_mgr_notify_message(&req_msg,
		V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT))
		CAM_ERR(CAM_ISP,
			"Error in notifying the sof time for req id:%lld",
			request_id);
}

static void __cam_isp_ctx_send_sof_timestamp(
	struct cam_isp_context *ctx_isp, uint64_t request_id,
@@ -447,6 +490,10 @@ static void __cam_isp_ctx_send_sof_timestamp(
{
	struct cam_req_mgr_message   req_msg;

	if ((ctx_isp->use_frame_header_ts) && (request_id) &&
		(sof_event_status == CAM_REQ_MGR_SOF_EVENT_SUCCESS))
		goto end;

	req_msg.session_hdl = ctx_isp->base->session_hdl;
	req_msg.u.frame_msg.frame_id = ctx_isp->frame_id;
	req_msg.u.frame_msg.request_id = request_id;
@@ -456,10 +503,9 @@ static void __cam_isp_ctx_send_sof_timestamp(
	req_msg.u.frame_msg.frame_id_meta = ctx_isp->frame_id_meta;

	CAM_DBG(CAM_ISP,
		"request id:%lld frame number:%lld SOF time stamp:0x%llx",
		"request id:%lld frame number:%lld SOF time stamp:0x%llx status:%u",
		 request_id, ctx_isp->frame_id,
		ctx_isp->sof_timestamp_val);
	CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status);
		ctx_isp->sof_timestamp_val, sof_event_status);

	if (cam_req_mgr_notify_message(&req_msg,
		V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT))
@@ -467,9 +513,9 @@ static void __cam_isp_ctx_send_sof_timestamp(
			"Error in notifying the sof time for req id:%lld",
			request_id);

end:
	__cam_isp_ctx_send_sof_boot_timestamp(ctx_isp,
		request_id, sof_event_status);

}

static void __cam_isp_ctx_handle_buf_done_fail_log(
@@ -605,6 +651,14 @@ static int __cam_isp_ctx_handle_buf_done_for_request(
			req_isp->num_acked++;
			req_isp->fence_map_out[j].sync_id = -1;
		}

		if ((ctx_isp->use_frame_header_ts) &&
			(req_isp->hw_update_data.frame_header_res_id ==
			req_isp->fence_map_out[j].resource_handle))
			__cam_isp_ctx_send_sof_timestamp_frame_header(
				ctx_isp,
				req_isp->hw_update_data.frame_header_cpu_addr,
				req->request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS);
	}

	if (req_isp->num_acked > req_isp->num_fence_map_out) {
@@ -648,10 +702,14 @@ static int __cam_isp_ctx_handle_buf_done_for_request(
				ctx->ctx_id);
		}
	} else {

		if (!ctx_isp->use_frame_header_ts) {
			if (ctx_isp->reported_req_id < buf_done_req_id) {
				ctx_isp->reported_req_id = buf_done_req_id;
				__cam_isp_ctx_send_sof_timestamp(ctx_isp,
				buf_done_req_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS);
					buf_done_req_id,
					CAM_REQ_MGR_SOF_EVENT_SUCCESS);
			}
		}
		list_del_init(&req->list);
		list_add_tail(&req->list, &ctx->free_req_list);
@@ -2906,6 +2964,8 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
	}

	ctx->last_flush_req = 0;
	ctx_isp->custom_enabled = false;
	ctx_isp->use_frame_header_ts = false;
	ctx_isp->frame_id = 0;
	ctx_isp->active_req_cnt = 0;
	ctx_isp->reported_req_id = 0;
@@ -3550,6 +3610,12 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
		goto free_res;
	}

	/* Set custom flag if applicable
	 * custom hw is supported only on v2
	 */
	ctx_isp->custom_enabled = param.custom_enabled;
	ctx_isp->use_frame_header_ts = param.use_frame_header_ts;

	/* Query the context has rdi only resource */
	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
	hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
@@ -4444,6 +4510,8 @@ int cam_isp_context_init(struct cam_isp_context *ctx,

	ctx->base = ctx_base;
	ctx->frame_id = 0;
	ctx->custom_enabled = false;
	ctx->use_frame_header_ts = false;
	ctx->active_req_cnt = 0;
	ctx->reported_req_id = 0;
	ctx->req_info.last_bufdone_req_id = 0;
+8 −0
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@
#include "cam_context.h"
#include "cam_isp_hw_mgr_intf.h"


#define CAM_IFE_QTIMER_MUL_FACTOR        10000
#define CAM_IFE_QTIMER_DIV_FACTOR        192

/*
 * Maximum hw resource - This number is based on the maximum
 * output port resource. The current maximum resource number
@@ -191,6 +195,8 @@ struct cam_isp_context_req_id_info {
 * @hw_acquired:               Indicate whether HW resources are acquired
 * @init_received:             Indicate whether init config packet is received
 * @split_acquire:             Indicate whether a separate acquire is expected
 * @custom_enabled:            Custom HW enabled for this ctx
 * @use_frame_header_ts:       Use frame header for qtimer ts
 * @init_timestamp:            Timestamp at which this context is initialized
 *
 */
@@ -223,6 +229,8 @@ struct cam_isp_context {
	bool                                  hw_acquired;
	bool                                  init_received;
	bool                                  split_acquire;
	bool                                  custom_enabled;
	bool                                  use_frame_header_ts;
	unsigned int                          init_timestamp;
};

+104 −3
Original line number Diff line number Diff line
@@ -2741,6 +2741,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
		goto err;
	}

	ife_ctx->custom_enabled = false;
	ife_ctx->common.cb_priv = acquire_args->context_data;
	for (i = 0; i < CAM_ISP_HW_EVENT_MAX; i++)
		ife_ctx->common.event_cb[i] = acquire_args->event_cb;
@@ -2793,6 +2794,12 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
		}
		CAM_DBG(CAM_ISP, "in_res_type %x", in_port->res_type);

		if ((in_port->cust_node) && (!ife_ctx->custom_enabled)) {
			ife_ctx->custom_enabled = true;
			/* This can be obtained from uapi */
			ife_ctx->use_frame_header_ts = true;
		}

		rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
			&num_pix_port_per_in, &num_rdi_port_per_in,
			&acquire_args->acquired_hw_id[i],
@@ -2827,6 +2834,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
	}

	acquire_args->ctxt_to_hw_map = ife_ctx;
	acquire_args->custom_enabled = ife_ctx->custom_enabled;
	acquire_args->use_frame_header_ts = ife_ctx->use_frame_header_ts;
	ife_ctx->ctx_in_use = 1;

	acquire_args->valid_acquired_hw =
@@ -4239,6 +4248,8 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
	ctx->is_rdi_only_context = 0;
	ctx->cdm_handle = 0;
	ctx->cdm_ops = NULL;
	ctx->custom_enabled = false;
	ctx->use_frame_header_ts = false;
	atomic_set(&ctx->overflow_pending, 0);
	for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
		ctx->sof_cnt[i] = 0;
@@ -5546,6 +5557,58 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
	return rc;
}

static int cam_ife_mgr_util_insert_frame_header(
	struct cam_kmd_buf_info *kmd_buf,
	struct cam_isp_prepare_hw_update_data *prepare_hw_data)
{
	int mmu_hdl = -1, rc = 0;
	dma_addr_t iova_addr;
	uint32_t frame_header_iova, padded_bytes = 0;
	size_t len;
	struct cam_ife_hw_mgr *hw_mgr = &g_ife_hw_mgr;

	mmu_hdl = cam_mem_is_secure_buf(
			kmd_buf->handle) ?
			hw_mgr->mgr_common.img_iommu_hdl_secure :
			hw_mgr->mgr_common.img_iommu_hdl;

	rc = cam_mem_get_io_buf(kmd_buf->handle, mmu_hdl,
		&iova_addr, &len);
	if (rc) {
		CAM_ERR(CAM_ISP,
			"Failed to get io addr for handle = %d for mmu_hdl = %u",
			kmd_buf->handle, mmu_hdl);
		return rc;
	}

	frame_header_iova = (uint32_t)iova_addr;
	frame_header_iova += kmd_buf->offset;

	/* frame header address needs to be 16 byte aligned */
	if (frame_header_iova % 16) {
		padded_bytes = (uint32_t)(16 - (frame_header_iova % 16));
		iova_addr += padded_bytes;
	}

	prepare_hw_data->frame_header_iova = frame_header_iova;

	/* update the padding if any for the cpu addr as well */
	prepare_hw_data->frame_header_cpu_addr = kmd_buf->cpu_addr +
			(padded_bytes / 4);

	CAM_DBG(CAM_ISP,
		"Frame Header iova_addr: %pK cpu_addr: %pK padded_bytes: %llu",
		prepare_hw_data->frame_header_iova,
		prepare_hw_data->frame_header_cpu_addr,
		padded_bytes);

	/* Reserve memory for frame header */
	kmd_buf->used_bytes += 128;
	kmd_buf->offset += kmd_buf->used_bytes;

	return rc;
}

static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	void *prepare_hw_update_args)
{
@@ -5557,7 +5620,9 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	struct cam_kmd_buf_info                  kmd_buf;
	uint32_t                                 i;
	bool                                     fill_fence = true;
	bool                                     frame_header_enable = false;
	struct cam_isp_prepare_hw_update_data   *prepare_hw_data;
	struct cam_isp_frame_header_info         frame_header_info;

	if (!hw_mgr_priv || !prepare_hw_update_args) {
		CAM_ERR(CAM_ISP, "Invalid args");
@@ -5584,6 +5649,15 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	if (rc)
		return rc;

	if (ctx->use_frame_header_ts) {
		rc = cam_ife_mgr_util_insert_frame_header(&kmd_buf,
			prepare_hw_data);
		if (rc)
			return rc;

		frame_header_enable = true;
	}

	rc = cam_packet_util_process_patches(prepare->packet,
		hw_mgr->mgr_common.cmd_iommu_hdl,
		hw_mgr->mgr_common.cmd_iommu_hdl_secure);
@@ -5632,13 +5706,23 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
			}
		}

		memset(&frame_header_info, 0,
			sizeof(struct cam_isp_frame_header_info));
		if (frame_header_enable) {
			frame_header_info.frame_header_enable = true;
			frame_header_info.frame_header_iova_addr =
				prepare_hw_data->frame_header_iova;
		}

		/* get IO buffers */
		rc = cam_isp_add_io_buffers(hw_mgr->mgr_common.img_iommu_hdl,
		rc = cam_isp_add_io_buffers(
			hw_mgr->mgr_common.img_iommu_hdl,
			hw_mgr->mgr_common.img_iommu_hdl_secure,
			prepare, ctx->base[i].idx,
			&kmd_buf, ctx->res_list_ife_out,
			&ctx->res_list_ife_in_rd,
			CAM_IFE_HW_OUT_RES_MAX, fill_fence);
			CAM_IFE_HW_OUT_RES_MAX, fill_fence,
			&frame_header_info);

		if (rc) {
			CAM_ERR(CAM_ISP,
@@ -5650,6 +5734,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
		/* fence map table entries need to fill only once in the loop */
		if (fill_fence)
			fill_fence = false;

		if (frame_header_info.frame_header_res_id &&
			frame_header_enable) {
			frame_header_enable = false;
			prepare_hw_data->frame_header_res_id =
				frame_header_info.frame_header_res_id;

			CAM_DBG(CAM_ISP,
				"Frame header enabled for res_id 0x%x cpu_addr %pK",
				prepare_hw_data->frame_header_res_id,
				prepare_hw_data->frame_header_cpu_addr);
		}
	}

	/*
@@ -6484,10 +6580,15 @@ static int cam_ife_hw_mgr_handle_hw_sof(
		rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx,
			CAM_ISP_HW_EVENT_SOF);
		if (!rc) {
			cam_ife_mgr_cmd_get_sof_timestamp(ife_hw_mgr_ctx,
			cam_ife_mgr_cmd_get_sof_timestamp(
				ife_hw_mgr_ctx,
				&sof_done_event_data.timestamp,
				&sof_done_event_data.boot_time);

			/* if frame header is enabled reset qtimer ts */
			if (ife_hw_mgr_ctx->use_frame_header_ts)
				sof_done_event_data.timestamp = 0x0;

			if (atomic_read(&ife_hw_mgr_ctx->overflow_pending))
				break;

+5 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_IFE_HW_MGR_H_
@@ -139,6 +139,8 @@ struct cam_ife_hw_mgr_debug {
 * @init_done               indicate whether init hw is done
 * @is_fe_enable            indicate whether fetch engine\read path is enabled
 * @is_dual                 indicate whether context is in dual VFE mode
 * @custom_enabled          update the flag if context is connected to custom HW
 * @use_frame_header_ts     obtain qtimer ts using frame header
 * @ts                      captured timestamp when the ctx is acquired
 */
struct cam_ife_hw_mgr_ctx {
@@ -186,6 +188,8 @@ struct cam_ife_hw_mgr_ctx {
	bool                            init_done;
	bool                            is_fe_enable;
	bool                            is_dual;
	bool                            custom_enabled;
	bool                            use_frame_header_ts;
	struct timespec64               ts;
};

Loading