diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index f69e0fc914..8141d75bc9 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -470,6 +470,7 @@ static void __cam_isp_ctx_send_sof_boot_timestamp( req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp; req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; req_msg.u.frame_msg.sof_status = sof_event_status; + 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", @@ -497,6 +498,7 @@ static void __cam_isp_ctx_send_sof_timestamp( 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; + 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", @@ -863,11 +865,20 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( struct cam_isp_context *ctx_isp, void *evt_data) { int rc = 0; + uint64_t request_id = 0; struct cam_req_mgr_trigger_notify notify; struct cam_context *ctx = ctx_isp->base; struct cam_ctx_request *req; struct cam_isp_ctx_req *req_isp; - uint64_t request_id = 0; + struct cam_isp_hw_epoch_event_data *epoch_done_event_data = + (struct cam_isp_hw_epoch_event_data *)evt_data; + + if (!evt_data) { + CAM_ERR(CAM_ISP, "invalid event data"); + return -EINVAL; + } + + ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; /* * notify reqmgr with sof signal. Note, due to scheduling delay @@ -1082,11 +1093,19 @@ end: static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { - struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; - struct cam_context *ctx = ctx_isp->base; - uint64_t request_id = 0; + uint64_t request_id = 0; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_epoch_event_data *epoch_done_event_data = + (struct cam_isp_hw_epoch_event_data *)evt_data; + if (!evt_data) { + CAM_ERR(CAM_ISP, "invalid event data"); + return -EINVAL; + } + + ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; if (list_empty(&ctx->wait_req_list)) { /* * If no wait req in epoch, this is an error case. @@ -1248,10 +1267,19 @@ static int __cam_isp_ctx_buf_done_in_bubble( static int __cam_isp_ctx_epoch_in_bubble_applied( struct cam_isp_context *ctx_isp, void *evt_data) { - struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; - struct cam_context *ctx = ctx_isp->base; uint64_t request_id = 0; + struct cam_ctx_request *req; + struct cam_isp_ctx_req *req_isp; + struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_epoch_event_data *epoch_done_event_data = + (struct cam_isp_hw_epoch_event_data *)evt_data; + + if (!evt_data) { + CAM_ERR(CAM_ISP, "invalid event data"); + return -EINVAL; + } + + ctx_isp->frame_id_meta = epoch_done_event_data->frame_id_meta; /* * This means we missed the reg upd ack. So we need to diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index c29a57fc33..3e4e601b9b 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -166,6 +166,8 @@ struct cam_isp_context_req_id_info { * * @base: Common context object pointer * @frame_id: Frame id tracking for the isp context + * @frame_id_meta: Frame id read every epoch for the ctx + * meta from the sensor * @substate_actiavted: Current substate for the activated state. * @process_bubble: Atomic variable to check if ctx is still * processing bubble. @@ -195,27 +197,28 @@ struct cam_isp_context_req_id_info { * */ struct cam_isp_context { - struct cam_context *base; + struct cam_context *base; - int64_t frame_id; - enum cam_isp_ctx_activated_substate substate_activated; - atomic_t process_bubble; - uint32_t bubble_frame_cnt; - struct cam_ctx_ops *substate_machine; - struct cam_isp_ctx_irq_ops *substate_machine_irq; + int64_t frame_id; + uint32_t frame_id_meta; + uint32_t substate_activated; + atomic_t process_bubble; + uint32_t bubble_frame_cnt; + struct cam_ctx_ops *substate_machine; + struct cam_isp_ctx_irq_ops *substate_machine_irq; - struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; - struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; + struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; + struct cam_isp_ctx_req req_isp[CAM_CTX_REQ_MAX]; - void *hw_ctx; - uint64_t sof_timestamp_val; - uint64_t boot_timestamp; - int32_t active_req_cnt; - int64_t reported_req_id; - uint32_t subscribe_event; - int64_t last_applied_req_id; - atomic64_t state_monitor_head; - struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ + void *hw_ctx; + uint64_t sof_timestamp_val; + uint64_t boot_timestamp; + int32_t active_req_cnt; + int64_t reported_req_id; + uint32_t subscribe_event; + int64_t last_applied_req_id; + atomic64_t state_monitor_head; + struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[ CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES]; struct cam_isp_context_req_id_info req_info; bool rdi_only_context; 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 7bf3c518cb..44c42e2e71 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 @@ -4775,29 +4775,36 @@ static int cam_isp_blob_core_cfg_update( list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { clk_rate = 0; - if (!hw_mgr_res->hw_res[i] || - hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF) + if (!hw_mgr_res->hw_res[i]) continue; - hw_intf = hw_mgr_res->hw_res[i]->hw_intf; - if (hw_intf && hw_intf->hw_ops.process_cmd) { - vfe_core_config.node_res = - hw_mgr_res->hw_res[i]; + if ((hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_CAMIF) || + (hw_mgr_res->res_id == + CAM_ISP_HW_VFE_IN_PDLIB)) { + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + vfe_core_config.node_res = + hw_mgr_res->hw_res[i]; - memcpy(&vfe_core_config.core_config, - core_config, - sizeof(struct cam_isp_core_config)); + memcpy(&vfe_core_config.core_config, + core_config, + sizeof( + struct cam_isp_core_config)); - rc = hw_intf->hw_ops.process_cmd( - hw_intf->hw_priv, - CAM_ISP_HW_CMD_CORE_CONFIG, - &vfe_core_config, - sizeof( - struct cam_vfe_core_config_args)); - if (rc) - CAM_ERR(CAM_ISP, "Core cfg parse fail"); - } else { - CAM_WARN(CAM_ISP, "NULL hw_intf!"); + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CORE_CONFIG, + &vfe_core_config, + sizeof( + struct cam_vfe_core_config_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Core cfg parse fail"); + } else { + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } } } } @@ -6434,6 +6441,9 @@ static int cam_ife_hw_mgr_handle_hw_epoch( if (!rc) { if (atomic_read(&ife_hw_mgr_ctx->overflow_pending)) break; + + epoch_done_event_data.frame_id_meta = + event_info->th_reg_val; ife_hw_irq_epoch_cb(ife_hw_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EPOCH, &epoch_done_event_data); } 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 a0c0e60a30..86b47da0b3 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 @@ -170,10 +170,11 @@ struct cam_isp_hw_reg_update_event_data { * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH * * @timestamp: Time stamp for the epoch event - * + * @frame_id_meta: Frame id value corresponding to this frame */ struct cam_isp_hw_epoch_event_data { uint64_t timestamp; + uint32_t frame_id_meta; }; /** 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 def4624597..22b2bf1f53 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 @@ -174,6 +174,7 @@ struct cam_isp_resource_node { * @res_id: Unique resource ID * @hw_idx: IFE hw index * @err_type: Error type if any + * @th_reg_val: Any critical register value captured during th * */ struct cam_isp_hw_event_info { @@ -181,6 +182,7 @@ struct cam_isp_hw_event_info { uint32_t res_id; uint32_t hw_idx; uint32_t err_type; + uint32_t th_reg_val; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 24ae56de50..c3f2aabf56 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -263,11 +263,15 @@ struct cam_vfe_bw_control_args { * @list: list_head node for the payload * @irq_reg_val: IRQ and Error register values, read when IRQ was * handled + * @th_reg_val: Value of any critical register that needs to be + * read at th to avoid any latencies in bh processing + * * @ts: Timestamp */ struct cam_vfe_top_irq_evt_payload { struct list_head list; uint32_t irq_reg_val[CAM_IFE_IRQ_REGISTERS_MAX]; + uint32_t th_reg_val; struct cam_isp_timestamp ts; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index ae65df7c11..0cd59de02f 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ @@ -77,6 +77,7 @@ static struct cam_vfe_camif_ver3_reg_data vfe_480_camif_reg_data = { .error_irq_mask0 = 0x82000200, .error_irq_mask2 = 0x30301F80, .subscribe_irq_mask1 = 0x00000007, + .frame_id_irq_mask = 0x400, .enable_diagnostic_hw = 0x1, .pp_camif_cfg_en_shift = 0, .pp_camif_cfg_ife_out_en_shift = 8, @@ -101,7 +102,7 @@ static struct cam_vfe_top_ver3_reg_offset_common vfe480_top_common_reg = { .ahb_cgc_ovd = 0x00000024, .noc_cgc_ovd = 0x00000028, .trigger_cdm_events = 0x00000090, - .sbi_frame_idx = 0x00000110, + .custom_frame_idx = 0x00000110, .dsp_status = 0x0000007C, .diag_config = 0x00000064, .diag_sensor_status_0 = 0x00000068, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index e558e9087f..d9fe166d39 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -507,6 +507,9 @@ static int cam_vfe_camif_ver3_resource_start( irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS1] = rsrc_data->reg_data->sof_irq_mask; + if (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) + irq_mask[CAM_IFE_IRQ_CAMIF_REG_STATUS0] = + rsrc_data->reg_data->frame_id_irq_mask; if (!rsrc_data->sof_irq_handle) { rsrc_data->sof_irq_handle = cam_irq_controller_subscribe_irq( @@ -1191,10 +1194,21 @@ static int cam_vfe_camif_ver3_handle_irq_top_half(uint32_t evt_id, } cam_isp_hw_get_timestamp(&evt_payload->ts); + evt_payload->th_reg_val = 0; for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; + /* Read frame_id meta at every epoch if custom hw is enabled */ + if (evt_payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1] + & camif_priv->reg_data->epoch0_irq_mask) { + if ((camif_priv->common_reg->custom_frame_idx) && + (camif_priv->cam_common_cfg.input_mux_sel_pp & 0x3)) + evt_payload->th_reg_val = cam_io_r_mb( + camif_priv->mem_base + + camif_priv->common_reg->custom_frame_idx); + } + th_payload->evt_payload_priv = evt_payload; CAM_DBG(CAM_ISP, "Exit"); @@ -1210,6 +1224,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; + uint32_t val = 0; int i = 0; if (!handler_priv || !evt_payload_priv) { @@ -1229,6 +1244,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, evt_info.hw_idx = camif_node->hw_intf->hw_idx; evt_info.res_id = camif_node->res_id; evt_info.res_type = camif_node->res_type; + evt_info.th_reg_val = 0; if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->sof_irq_mask) { @@ -1259,6 +1275,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); + evt_info.th_reg_val = payload->th_reg_val; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1294,6 +1311,15 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, cam_vfe_camif_ver3_reg_dump(camif_node); } + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + & camif_priv->reg_data->frame_id_irq_mask) { + val = cam_io_r_mb(camif_priv->mem_base + + camif_priv->common_reg->custom_frame_idx); + CAM_DBG(CAM_ISP, + "VFE:%d Frame id change to: %u", evt_info.hw_idx, + val); + } + if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h index e611d1ac62..6e02c58ee6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.h @@ -53,6 +53,7 @@ struct cam_vfe_camif_ver3_reg_data { uint32_t error_irq_mask0; uint32_t error_irq_mask2; uint32_t subscribe_irq_mask1; + uint32_t frame_id_irq_mask; uint32_t enable_diagnostic_hw; uint32_t pp_camif_cfg_en_shift; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h index 14c96097cd..4a24ba6ddf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_TOP_VER3_H_ @@ -41,7 +41,7 @@ struct cam_vfe_top_ver3_reg_offset_common { uint32_t reg_update_cmd; uint32_t trigger_cdm_events; uint32_t violation_status; - uint32_t sbi_frame_idx; + uint32_t custom_frame_idx; uint32_t dsp_status; uint32_t diag_config; uint32_t diag_sensor_status_0;