diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 1e2c1f7a70..422a47bf35 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -1,6 +1,6 @@ /* 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]; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 3f991dc7b1..02f51ff13c 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -425,6 +425,7 @@ static int __cam_isp_ctx_enqueue_init_request( struct cam_isp_ctx_req *req_isp_new; struct cam_isp_prepare_hw_update_data *req_update_old; struct cam_isp_prepare_hw_update_data *req_update_new; + struct cam_isp_prepare_hw_update_data *hw_update_data; spin_lock_bh(&ctx->lock); if (list_empty(&ctx->pending_req_list)) { @@ -487,6 +488,13 @@ static int __cam_isp_ctx_enqueue_init_request( req_update_new->num_reg_dump_buf; } + /* 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); @@ -645,9 +653,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, @@ -657,6 +665,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, @@ -664,6 +707,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; @@ -673,10 +720,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)) @@ -684,9 +730,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( @@ -738,7 +784,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request( { int rc = 0; int i, j; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp; struct cam_context *ctx = ctx_isp->base; uint64_t buf_done_req_id; const char *handle_type; @@ -840,6 +886,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) { @@ -883,10 +937,14 @@ static int __cam_isp_ctx_handle_buf_done_for_request( ctx->ctx_id); } } else { - 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); + + 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); + } } list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); @@ -3375,6 +3433,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; @@ -4030,6 +4090,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; @@ -4935,6 +5001,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; diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 78e2db92f0..94c61af5e0 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -15,6 +15,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 @@ -246,6 +250,8 @@ struct cam_isp_context_event_record { * @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 * @isp_device_type ISP device type * @@ -283,6 +289,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; uint32_t isp_device_type; }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index af626cbbfb..e2a2cecf72 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2695,6 +2695,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; @@ -2748,6 +2749,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], @@ -2782,6 +2789,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; ife_ctx->num_reg_dump_buf = 0; @@ -4193,6 +4202,8 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->cdm_handle = 0; ctx->cdm_ops = NULL; ctx->num_reg_dump_buf = 0; + 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; @@ -5555,6 +5566,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) { @@ -5566,7 +5629,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"); @@ -5593,6 +5658,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); @@ -5641,13 +5715,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, @@ -5659,6 +5743,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); + } } /* @@ -6643,10 +6739,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; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 7d68b180e5..79033e3458 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -82,6 +82,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 { @@ -129,6 +131,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; }; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 1eaa695d36..a3e946e802 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -3809,6 +3809,7 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, uint32_t i; bool fill_fence = true; 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"); @@ -3886,13 +3887,18 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, } } + memset(&frame_header_info, 0, + sizeof(struct cam_isp_frame_header_info)); + frame_header_info.frame_header_enable = false; + /* get IO buffers */ 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_tfe_out, NULL, - CAM_TFE_HW_OUT_RES_MAX, fill_fence); + CAM_TFE_HW_OUT_RES_MAX, fill_fence, + &frame_header_info); if (rc) { CAM_ERR(CAM_ISP, diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index ce3f895f4b..b6027db649 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -463,7 +463,8 @@ int cam_isp_add_io_buffers( struct cam_isp_hw_mgr_res *res_list_isp_out, struct list_head *res_list_ife_in_rd, uint32_t size_isp_out, - bool fill_fence) + bool fill_fence, + struct cam_isp_frame_header_info *frame_header_info) { int rc = 0; dma_addr_t io_addr[CAM_PACKET_MAX_PLANES]; @@ -480,6 +481,7 @@ int cam_isp_add_io_buffers( uint32_t i, j, num_out_buf, num_in_buf; uint32_t res_id_out, res_id_in, plane_id; uint32_t io_cfg_used_bytes, num_ent; + uint64_t iova_addr; size_t size; int32_t hdl; int mmu_hdl; @@ -693,6 +695,21 @@ int cam_isp_add_io_buffers( wm_update.image_buf = io_addr; wm_update.num_buf = plane_id; wm_update.io_cfg = &io_cfg[i]; + wm_update.frame_header = 0; + iova_addr = frame_header_info->frame_header_iova_addr; + if ((frame_header_info->frame_header_enable) && + !(frame_header_info->frame_header_res_id)) { + wm_update.frame_header = iova_addr; + frame_header_info->frame_header_res_id = + res->res_id; + wm_update.local_id = + prepare->packet->header.request_id; + CAM_DBG(CAM_ISP, + "Frame header enabled for res: 0x%x iova: %pK", + frame_header_info->frame_header_res_id, + wm_update.frame_header); + } + update_buf.cmd.size = kmd_buf_remain_size; update_buf.wm_update = &wm_update; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index 8948b2a416..ca56b155e9 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -34,6 +34,19 @@ struct cam_isp_generic_blob_info { struct cam_kmd_buf_info *kmd_buf_info; }; +/* + * struct cam_isp_frame_header_info + * + * @frame_header_enable: Enable frame header + * @frame_header_iova_addr: frame header iova + * @frame_header_res_id: res id for which frame header is enabled + */ +struct cam_isp_frame_header_info { + bool frame_header_enable; + uint64_t frame_header_iova_addr; + uint32_t frame_header_res_id; +}; + /* * cam_isp_add_change_base() * @@ -127,7 +140,7 @@ int cam_isp_add_command_buffers( * @res_list_ife_in_rd: IFE /VFE in rd resource list * @size_isp_out: Size of the res_list_isp_out array * @fill_fence: If true, Fence map table will be filled - * + * @frame_header_info: Frame header related params * @return: 0 for success * -EINVAL for Fail */ @@ -140,7 +153,8 @@ int cam_isp_add_io_buffers( struct cam_isp_hw_mgr_res *res_list_isp_out, struct list_head *res_list_ife_in_rd, uint32_t size_isp_out, - bool fill_fence); + bool fill_fence, + struct cam_isp_frame_header_info *frame_header_info); /* * cam_isp_add_reg_update() diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 86b47da0b3..f68a6ec3a8 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -121,6 +121,9 @@ struct cam_isp_bw_config_internal { * @packet_opcode_type: Packet header opcode in the packet header * this opcode defines, packet is init packet or * update packet + * @frame_header_cpu_addr: Frame header cpu addr + * @frame_header_iova: Frame header iova + * @frame_header_res_id: Out port res_id corresponding to frame header * @bw_config_version: BW config version indicator * @bw_config: BW config information * @bw_config_v2: BW config info for AXI bw voting v2 @@ -133,10 +136,13 @@ struct cam_isp_bw_config_internal { struct cam_isp_prepare_hw_update_data { void *isp_mgr_ctx; uint32_t packet_opcode_type; + uint32_t *frame_header_cpu_addr; + uint64_t frame_header_iova; + uint32_t frame_header_res_id; uint32_t bw_config_version; struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; struct cam_isp_bw_config_internal_v2 bw_config_v2[CAM_IFE_HW_NUM_MAX]; - bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; + bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; struct cam_cmd_buf_desc reg_dump_buf_desc[ CAM_REG_DUMP_MAX_BUF_ENTRIES]; uint32_t num_reg_dump_buf; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index b7f2692b61..c242bdaa17 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -1,6 +1,6 @@ /* 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_CSID_HW_INTF_H_ @@ -187,9 +187,9 @@ struct cam_csid_reset_cfg_args { /** * struct cam_csid_get_time_stamp_args- time stamp capture arguments - * @res_node : resource to get the time stamp - * @time_stamp_val : captured time stamp - * @boot_timestamp : boot time stamp + * @node_res : resource to get the time stamp + * @time_stamp_val : captured time stamp + * @boot_timestamp : boot time stamp */ struct cam_csid_get_time_stamp_args { struct cam_isp_resource_node *node_res; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 5fd1172a40..02c1948e90 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -211,12 +211,16 @@ struct cam_isp_hw_cmd_buf_update { * * @ image_buf: image buffer address array * @ num_buf: Number of buffers in the image_buf array + * @ frame_header: frame header iova + * @ local_id: local id for the wm * @ io_cfg: IO buffer config information sent from UMD * */ struct cam_isp_hw_get_wm_update { dma_addr_t *image_buf; uint32_t num_buf; + uint64_t frame_header; + uint32_t local_id; struct cam_buf_io_cfg *io_cfg; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index ebe2e1d4e9..d6f66dffb6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3010,6 +3010,7 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, uint32_t i, j, k, size = 0; uint32_t frame_inc = 0, val; uint32_t loop_size = 0; + bool frame_header_enable = false; bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; @@ -3043,6 +3044,27 @@ static int cam_vfe_bus_ver3_update_wm(void *priv, void *cmd_args, wm_data = vfe_out_data->wm_res[i]->res_priv; ubwc_client = wm_data->hw_regs->ubwc_regs; + /* Disable frame header in case it was previously enabled */ + if ((wm_data->en_cfg) & (1 << 2)) + wm_data->en_cfg &= ~(1 << 2); + + if (update_buf->wm_update->frame_header && + !frame_header_enable) { + wm_data->en_cfg |= 1 << 2; + frame_header_enable = true; + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_header_addr, + update_buf->wm_update->frame_header); + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->frame_header_cfg, + update_buf->wm_update->local_id); + CAM_DBG(CAM_ISP, + "WM: %d en_cfg 0x%x frame_header %pK local_id %u", + wm_data->index, wm_data->en_cfg, + update_buf->wm_update->frame_header, + update_buf->wm_update->local_id); + } + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->cfg, wm_data->en_cfg); CAM_DBG(CAM_ISP, "WM:%d en_cfg 0x%X",