msm: camera: isp: Add support for AEB use-case

Add support to ensure epoch is programmed post second
exposure frame. Validate this, if this check fails
flag an error. The % factor of frame height to be configured
for epoch is obtained from userspace. This % factor will
depend on how the frame is spread for IFE to process.

CRs-Fixed: 2986303
Change-Id: I2d7d34ccdfde0192ebb73bbd920a4c738bbf9ca2
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
This commit is contained in:
Karthik Anantha Ram
2021-06-23 12:34:58 -07:00
parent 72f753f6a8
commit 5d5b3a5144
11 changed files with 297 additions and 36 deletions

View File

@@ -5579,6 +5579,8 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
(param.op_flags & CAM_IFE_CTX_APPLY_DEFAULT_CFG); (param.op_flags & CAM_IFE_CTX_APPLY_DEFAULT_CFG);
ctx_isp->support_consumed_addr = ctx_isp->support_consumed_addr =
(param.op_flags & CAM_IFE_CTX_CONSUME_ADDR_EN); (param.op_flags & CAM_IFE_CTX_CONSUME_ADDR_EN);
ctx_isp->aeb_enabled =
(param.op_flags & CAM_IFE_CTX_AEB_EN);
/* Query the context has rdi only resource */ /* Query the context has rdi only resource */
hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map; hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
@@ -6387,6 +6389,28 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context,
(struct cam_isp_context *)ctx->ctx_priv; (struct cam_isp_context *)ctx->ctx_priv;
spin_lock(&ctx->lock); spin_lock(&ctx->lock);
/*
* In case of custom AEB ensure first exposure frame has
* not moved forward with its settings without second/third
* expoure frame coming in. If this scenario occurs flag as error,
* and recover
*/
if ((ctx_isp->aeb_enabled) && (evt_id == CAM_ISP_HW_EVENT_SOF)) {
bool is_secondary_evt =
((struct cam_isp_hw_sof_event_data *)evt_data)->is_secondary_evt;
if (is_secondary_evt) {
if ((ctx_isp->substate_activated ==
CAM_ISP_CTX_ACTIVATED_APPLIED) ||
(ctx_isp->substate_activated ==
CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED)) {
CAM_ERR(CAM_ISP,
"AEB settings mismatch between exposures - needs a reset");
rc = -EAGAIN;
}
goto end;
}
}
trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id, trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id,
__cam_isp_ctx_get_event_ts(evt_id, evt_data)); __cam_isp_ctx_get_event_ts(evt_id, evt_data));
@@ -6408,6 +6432,7 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context,
CAM_DBG(CAM_ISP, "Exit: State %d Substate[%s]", CAM_DBG(CAM_ISP, "Exit: State %d Substate[%s]",
ctx->state, __cam_isp_ctx_substate_val_to_type( ctx->state, __cam_isp_ctx_substate_val_to_type(
ctx_isp->substate_activated)); ctx_isp->substate_activated));
end:
spin_unlock(&ctx->lock); spin_unlock(&ctx->lock);
return rc; return rc;
} }

View File

@@ -269,6 +269,7 @@ struct cam_isp_context_event_record {
* @custom_enabled: Custom HW enabled for this ctx * @custom_enabled: Custom HW enabled for this ctx
* @use_frame_header_ts: Use frame header for qtimer ts * @use_frame_header_ts: Use frame header for qtimer ts
* @support_consumed_addr: Indicate whether HW has last consumed addr reg * @support_consumed_addr: Indicate whether HW has last consumed addr reg
* @aeb_enabled: Indicate if stream is for AEB
* @apply_in_progress Whether request apply is in progress * @apply_in_progress Whether request apply is in progress
* @use_default_apply: Use default settings in case of frame skip * @use_default_apply: Use default settings in case of frame skip
* @init_timestamp: Timestamp at which this context is initialized * @init_timestamp: Timestamp at which this context is initialized
@@ -319,6 +320,7 @@ struct cam_isp_context {
bool custom_enabled; bool custom_enabled;
bool use_frame_header_ts; bool use_frame_header_ts;
bool support_consumed_addr; bool support_consumed_addr;
bool aeb_enabled;
atomic_t apply_in_progress; atomic_t apply_in_progress;
bool use_default_apply; bool use_default_apply;
unsigned int init_timestamp; unsigned int init_timestamp;

View File

@@ -3404,6 +3404,21 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
CAM_DBG(CAM_ISP, "setting inline shdr mode for res: 0x%x", CAM_DBG(CAM_ISP, "setting inline shdr mode for res: 0x%x",
out_port->res_type); out_port->res_type);
csid_acquire.sfe_inline_shdr = true; csid_acquire.sfe_inline_shdr = true;
/*
* Merged output will only be from the first n RDIs
* starting from RDI0. Any other RDI[1:2] resource
* if only being dumped will be considered as a
* no merge resource
*/
if ((ife_ctx->flags.is_aeb_mode) &&
((out_port->res_type - CAM_ISP_SFE_OUT_RES_RDI_0) >=
ife_ctx->sfe_info.num_fetches)) {
csid_acquire.en_secondary_evt = true;
CAM_DBG(CAM_ISP,
"Secondary evt enabled for path: 0x%x",
out_port->res_type);
}
} }
/* /*
@@ -4202,6 +4217,10 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
ife_ctx->flags.dsp_enabled = (bool)in_port->dsp_mode; ife_ctx->flags.dsp_enabled = (bool)in_port->dsp_mode;
ife_ctx->flags.is_dual = (bool)in_port->usage_type; ife_ctx->flags.is_dual = (bool)in_port->usage_type;
/* Update aeb mode for the given in_port once */
if ((in_port->aeb_mode) && (!ife_ctx->flags.is_aeb_mode))
ife_ctx->flags.is_aeb_mode = true;
/* get root node resource */ /* get root node resource */
rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port); rc = cam_ife_hw_mgr_acquire_res_root(ife_ctx, in_port);
if (rc) { if (rc) {
@@ -4515,6 +4534,18 @@ static inline int cam_ife_mgr_hw_check_in_res_type(
} }
} }
static inline void cam_ife_mgr_acquire_get_feature_flag_params(
struct cam_isp_in_port_info_v2 *in,
struct cam_isp_in_port_generic_info *in_port)
{
in_port->secure_mode = in->feature_flag & CAM_ISP_PARAM_FETCH_SECURITY_MODE;
in_port->dynamic_sensor_switch_en = in->feature_flag & CAM_ISP_DYNAMIC_SENOR_SWITCH_EN;
in_port->can_use_lite = in->feature_flag & CAM_ISP_CAN_USE_LITE_MODE;
in_port->sfe_binned_epoch_cfg = in->feature_flag & CAM_ISP_SFE_BINNED_EPOCH_CFG_ENABLE;
in_port->epd_supported = in->feature_flag & CAM_ISP_EPD_SUPPORT;
in_port->aeb_mode = in->feature_flag & CAM_ISP_AEB_MODE_EN;
}
static int cam_ife_mgr_acquire_get_unified_structure_v2( static int cam_ife_mgr_acquire_get_unified_structure_v2(
struct cam_isp_acquire_hw_info *acquire_hw_info, struct cam_isp_acquire_hw_info *acquire_hw_info,
uint32_t offset, uint32_t *input_size, uint32_t offset, uint32_t *input_size,
@@ -4589,16 +4620,8 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2(
in_port->num_out_res = in->num_out_res; in_port->num_out_res = in->num_out_res;
in_port->sfe_in_path_type = (in->sfe_in_path_type & 0xFFFF); in_port->sfe_in_path_type = (in->sfe_in_path_type & 0xFFFF);
in_port->sfe_ife_enable = in->sfe_in_path_type >> 16; in_port->sfe_ife_enable = in->sfe_in_path_type >> 16;
in_port->secure_mode = (in->feature_flag &
CAM_ISP_PARAM_FETCH_SECURITY_MODE); cam_ife_mgr_acquire_get_feature_flag_params(in, in_port);
in_port->dynamic_sensor_switch_en = (in->feature_flag &
CAM_ISP_DYNAMIC_SENOR_SWITCH_EN);
in_port->can_use_lite = in->feature_flag &
CAM_ISP_CAN_USE_LITE_MODE;
in_port->sfe_binned_epoch_cfg = (in->feature_flag &
CAM_ISP_SFE_BINNED_EPOCH_CFG_ENABLE);
in_port->epd_supported = (in->feature_flag &
CAM_ISP_EPD_SUPPORT);
in_port->data = kcalloc(in->num_out_res, in_port->data = kcalloc(in->num_out_res,
sizeof(struct cam_isp_out_port_generic_info), sizeof(struct cam_isp_out_port_generic_info),
@@ -4875,6 +4898,9 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
acquire_args->op_flags |= acquire_args->op_flags |=
CAM_IFE_CTX_SFE_EN; CAM_IFE_CTX_SFE_EN;
if (ife_ctx->flags.is_aeb_mode)
acquire_args->op_flags |= CAM_IFE_CTX_AEB_EN;
ife_ctx->flags.ctx_in_use = true; ife_ctx->flags.ctx_in_use = true;
ife_ctx->num_reg_dump_buf = 0; ife_ctx->num_reg_dump_buf = 0;
@@ -8373,6 +8399,50 @@ static inline int cam_isp_validate_bw_limiter_blob(
return 0; return 0;
} }
static int cam_isp_blob_ife_init_config_update(
struct cam_hw_prepare_update_args *prepare,
struct cam_isp_init_config *init_config)
{
int i, rc = -EINVAL;
struct cam_hw_intf *hw_intf;
struct cam_ife_hw_mgr_ctx *ctx = NULL;
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct cam_isp_hw_init_config_update init_cfg_update;
ctx = prepare->ctxt_to_hw_map;
/* Assign init config */
init_cfg_update.init_config = init_config;
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (!hw_mgr_res->hw_res[i])
continue;
if (hw_mgr_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF)
continue;
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
if (hw_intf && hw_intf->hw_ops.process_cmd) {
init_cfg_update.node_res =
hw_mgr_res->hw_res[i];
CAM_DBG(CAM_ISP, "Init config update for res_id: %u",
hw_mgr_res->res_id);
rc = hw_intf->hw_ops.process_cmd(
hw_intf->hw_priv,
CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE,
&init_cfg_update,
sizeof(
struct cam_isp_hw_init_config_update));
if (rc)
CAM_ERR(CAM_ISP, "Init cfg update failed rc: %d", rc);
}
}
}
return rc;
}
static int cam_isp_packet_generic_blob_handler(void *user_data, static int cam_isp_packet_generic_blob_handler(void *user_data,
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{ {
@@ -8956,6 +9026,38 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
fps_config->fps, ife_mgr_ctx->ctx_index, fps_config->fps, ife_mgr_ctx->ctx_index,
prepare_hw_data->packet->header.request_id); prepare_hw_data->packet->header.request_id);
}
break;
case CAM_ISP_GENERIC_BLOB_TYPE_INIT_CONFIG: {
struct cam_isp_init_config *init_config;
struct cam_isp_prepare_hw_update_data *prepare_hw_data;
prepare_hw_data = (struct cam_isp_prepare_hw_update_data *)
prepare->priv;
if (prepare_hw_data->packet_opcode_type !=
CAM_ISP_PACKET_INIT_DEV) {
CAM_ERR(CAM_ISP,
"Init config blob not supported for packet type: %u req: %llu",
prepare_hw_data->packet_opcode_type,
prepare->packet->header.request_id);
return -EINVAL;
}
if (blob_size < sizeof(struct cam_isp_init_config)) {
CAM_ERR(CAM_ISP,
"Invalid init config blob size %u expected %u",
blob_size, sizeof(struct cam_isp_init_config));
return -EINVAL;
}
init_config = (struct cam_isp_init_config *)blob_data;
rc = cam_isp_blob_ife_init_config_update(
prepare, init_config);
if (rc)
CAM_ERR(CAM_ISP,
"Init config failed for req: %llu rc: %d",
prepare->packet->header.request_id, rc);
} }
break; break;
default: default:
@@ -9420,6 +9522,7 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG: case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG:
case CAM_ISP_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES: case CAM_ISP_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES:
case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG: case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG:
case CAM_ISP_GENERIC_BLOB_TYPE_INIT_CONFIG:
break; break;
default: default:
CAM_WARN(CAM_ISP, "Invalid blob type: %u", blob_type); CAM_WARN(CAM_ISP, "Invalid blob type: %u", blob_type);
@@ -11591,6 +11694,40 @@ static int cam_ife_hw_mgr_handle_hw_epoch(
return 0; return 0;
} }
static int cam_ife_hw_mgr_handle_csid_camif_sof(
struct cam_ife_hw_mgr_ctx *ctx,
struct cam_isp_hw_event_info *event_info)
{
struct cam_isp_hw_sof_event_data sof_done_event_data;
cam_hw_event_cb_func ife_hw_irq_sof_cb;
/*
* Currently SOF update is from IFE TOP - this CSID CAMIF SOF
* is only to monitor second/third exposure frame for custom
* AEB use-case hence the checks
*/
if (!(ctx->flags.is_aeb_mode && event_info->is_secondary_evt)) {
CAM_DBG(CAM_ISP,
"Received CSID CAMIF SOF aeb_mode: %d secondary_evt: %d - skip update",
ctx->flags.is_aeb_mode, event_info->is_secondary_evt);
return 0;
}
CAM_DBG(CAM_ISP,
"Received CSID CAMIF SOF res: %d as secondary evt",
event_info->res_id);
ife_hw_irq_sof_cb = ctx->common.event_cb;
sof_done_event_data.is_secondary_evt = true;
sof_done_event_data.boot_time = 0;
sof_done_event_data.timestamp = 0;
ife_hw_irq_sof_cb(ctx->common.cb_priv,
CAM_ISP_HW_EVENT_SOF, (void *)&sof_done_event_data);
return 0;
}
static int cam_ife_hw_mgr_handle_hw_sof( static int cam_ife_hw_mgr_handle_hw_sof(
void *ctx, void *ctx,
void *evt_info) void *evt_info)
@@ -11601,6 +11738,9 @@ static int cam_ife_hw_mgr_handle_hw_sof(
struct cam_isp_hw_sof_event_data sof_done_event_data; struct cam_isp_hw_sof_event_data sof_done_event_data;
struct timespec64 ts; struct timespec64 ts;
if (event_info->hw_type == CAM_ISP_HW_TYPE_CSID)
return cam_ife_hw_mgr_handle_csid_camif_sof(ctx, event_info);
memset(&sof_done_event_data, 0, sizeof(sof_done_event_data)); memset(&sof_done_event_data, 0, sizeof(sof_done_event_data));
ife_hw_irq_sof_cb = ife_hw_mgr_ctx->common.event_cb; ife_hw_irq_sof_cb = ife_hw_mgr_ctx->common.event_cb;

View File

@@ -141,6 +141,7 @@ struct cam_ife_hw_mgr_sfe_info {
* @is_sfe_fs: indicate if stream is for inline SFE FS * @is_sfe_fs: indicate if stream is for inline SFE FS
* @dump_on_flush: Set if reg dump triggered on flush * @dump_on_flush: Set if reg dump triggered on flush
* @dump_on_error: Set if reg dump triggered on error * @dump_on_error: Set if reg dump triggered on error
* @custom_aeb_mode: Set if custom AEB stream
* @sys_cache_usage: Per context sys cache usage * @sys_cache_usage: Per context sys cache usage
* The corresponding index will be set * The corresponding index will be set
* for the cache type * for the cache type
@@ -162,6 +163,7 @@ struct cam_ife_hw_mgr_ctx_flags {
bool is_sfe_fs; bool is_sfe_fs;
bool dump_on_flush; bool dump_on_flush;
bool dump_on_error; bool dump_on_error;
bool is_aeb_mode;
bool sys_cache_usage[CAM_LLCC_MAX]; bool sys_cache_usage[CAM_LLCC_MAX];
}; };

View File

@@ -38,6 +38,7 @@
#define CAM_IFE_CTX_CONSUME_ADDR_EN BIT(2) #define CAM_IFE_CTX_CONSUME_ADDR_EN BIT(2)
#define CAM_IFE_CTX_APPLY_DEFAULT_CFG BIT(3) #define CAM_IFE_CTX_APPLY_DEFAULT_CFG BIT(3)
#define CAM_IFE_CTX_SFE_EN BIT(4) #define CAM_IFE_CTX_SFE_EN BIT(4)
#define CAM_IFE_CTX_AEB_EN BIT(5)
/* /*
* Maximum configuration entry size - This is based on the * Maximum configuration entry size - This is based on the
@@ -215,11 +216,13 @@ struct cam_isp_prepare_hw_update_data {
/** /**
* struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF * struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF
* *
* @timestamp: Time stamp for the sof event * @is_secondary_event: Event notified as secondary
* @boot_time: Boot time stamp for the sof event * @timestamp : Time stamp for the sof event
* @boot_time : Boot time stamp for the sof event
* *
*/ */
struct cam_isp_hw_sof_event_data { struct cam_isp_hw_sof_event_data {
bool is_secondary_evt;
uint64_t timestamp; uint64_t timestamp;
uint64_t boot_time; uint64_t boot_time;
}; };

View File

@@ -1495,6 +1495,7 @@ static int cam_ife_csid_ver2_rdi_bottom_half(
uint32_t err_type = 0; uint32_t err_type = 0;
uint32_t expected_frame = 0; uint32_t expected_frame = 0;
uint32_t actual_frame = 0; uint32_t actual_frame = 0;
bool skip_sof_notify = false;
struct cam_isp_hw_event_info evt_info; struct cam_isp_hw_event_info evt_info;
if (!handler_priv || !evt_payload_priv) { if (!handler_priv || !evt_payload_priv) {
@@ -1567,9 +1568,6 @@ static int cam_ife_csid_ver2_rdi_bottom_half(
goto end; goto end;
} }
if (!path_cfg->handle_camif_irq)
goto end;
if (!csid_hw->event_cb) { if (!csid_hw->event_cb) {
CAM_DBG(CAM_ISP, "CSID[%u] no cb registered", CAM_DBG(CAM_ISP, "CSID[%u] no cb registered",
csid_hw->hw_intf->hw_idx); csid_hw->hw_intf->hw_idx);
@@ -1578,13 +1576,30 @@ static int cam_ife_csid_ver2_rdi_bottom_half(
evt_info.res_id = res->res_id; evt_info.res_id = res->res_id;
evt_info.reg_val = irq_status_rdi; evt_info.reg_val = irq_status_rdi;
evt_info.hw_type = CAM_ISP_HW_TYPE_CSID;
/* Check for secondary evt */
if ((path_cfg->en_secondary_evt) &&
(irq_status_rdi & IFE_CSID_VER2_PATH_INFO_INPUT_SOF)) {
evt_info.is_secondary_evt = true;
CAM_DBG(CAM_ISP,
"CSID[%u] RDI:%u notify CAMIF SOF as secondary evt",
csid_hw->hw_intf->hw_idx, res->res_id);
csid_hw->event_cb(csid_hw->token,
CAM_ISP_HW_EVENT_SOF, (void *)&evt_info);
skip_sof_notify = true;
}
if (!path_cfg->handle_camif_irq)
goto end;
if (irq_status_rdi & IFE_CSID_VER2_PATH_CAMIF_EOF) if (irq_status_rdi & IFE_CSID_VER2_PATH_CAMIF_EOF)
csid_hw->event_cb(csid_hw->token, csid_hw->event_cb(csid_hw->token,
CAM_ISP_HW_EVENT_EOF, CAM_ISP_HW_EVENT_EOF,
(void *)&evt_info); (void *)&evt_info);
if (irq_status_rdi & IFE_CSID_VER2_PATH_CAMIF_SOF) if (!skip_sof_notify && (irq_status_rdi & IFE_CSID_VER2_PATH_CAMIF_SOF))
csid_hw->event_cb(csid_hw->token, csid_hw->event_cb(csid_hw->token,
CAM_ISP_HW_EVENT_SOF, CAM_ISP_HW_EVENT_SOF,
(void *)&evt_info); (void *)&evt_info);
@@ -1885,6 +1900,8 @@ static int cam_ife_csid_hw_ver2_config_path_data(
path_cfg->vertical_bin = reserve->in_port->vertical_bin; path_cfg->vertical_bin = reserve->in_port->vertical_bin;
path_cfg->qcfa_bin = reserve->in_port->qcfa_bin; path_cfg->qcfa_bin = reserve->in_port->qcfa_bin;
path_cfg->num_bytes_out = reserve->in_port->num_bytes_out; path_cfg->num_bytes_out = reserve->in_port->num_bytes_out;
path_cfg->en_secondary_evt = reserve->en_secondary_evt;
if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
path_cfg->start_pixel = reserve->in_port->left_start; path_cfg->start_pixel = reserve->in_port->left_start;
path_cfg->end_pixel = reserve->in_port->left_stop; path_cfg->end_pixel = reserve->in_port->left_stop;
@@ -1958,9 +1975,9 @@ static int cam_ife_csid_hw_ver2_config_rx(
reserve->in_port->lane_num; reserve->in_port->lane_num;
csid_hw->res_type = reserve->in_port->res_type; csid_hw->res_type = reserve->in_port->res_type;
csid_hw->rx_cfg.dynamic_sensor_switch_en = csid_hw->rx_cfg.dynamic_sensor_switch_en =
(bool)reserve->in_port->dynamic_sensor_switch_en; reserve->in_port->dynamic_sensor_switch_en;
csid_hw->rx_cfg.epd_supported = if (reserve->in_port->epd_supported)
reserve->in_port->epd_supported; csid_hw->rx_cfg.epd_supported = 1;
switch (reserve->in_port->res_type) { switch (reserve->in_port->res_type) {
case CAM_ISP_IFE_IN_RES_TPG: case CAM_ISP_IFE_IN_RES_TPG:
@@ -2769,6 +2786,14 @@ static int cam_ife_csid_ver2_program_rdi_path(
path_cfg->handle_camif_irq = true; path_cfg->handle_camif_irq = true;
} }
/* Currently CAMIF SOF is the secondary evt enabled for HW mgr */
if (path_cfg->en_secondary_evt) {
val |= IFE_CSID_VER2_PATH_CAMIF_SOF;
CAM_DBG(CAM_ISP,
"Enable camif SOF irq for res: %s",
res->res_name);
}
res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
path_cfg->irq_reg_idx = path_cfg->irq_reg_idx =

View File

@@ -157,6 +157,8 @@ struct cam_ife_csid_ver2_camif_data {
* @crop_enable: flag to indicate crop enable * @crop_enable: flag to indicate crop enable
* @drop_enable: flag to indicate drop enable * @drop_enable: flag to indicate drop enable
* @discard_init_frames: discard initial frames * @discard_init_frames: discard initial frames
* @en_secondary_evt: Enable secondary evt for this path, to notify
* hw manager
* *
*/ */
struct cam_ife_csid_ver2_path_cfg { struct cam_ife_csid_ver2_path_cfg {
@@ -191,6 +193,7 @@ struct cam_ife_csid_ver2_path_cfg {
bool drop_enable; bool drop_enable;
bool handle_camif_irq; bool handle_camif_irq;
bool discard_init_frames; bool discard_init_frames;
bool en_secondary_evt;
}; };
struct cam_ife_csid_ver2_top_reg_info { struct cam_ife_csid_ver2_top_reg_info {

View File

@@ -132,11 +132,13 @@ struct cam_isp_in_port_generic_info {
uint32_t lite_path_count; uint32_t lite_path_count;
uint32_t sfe_in_path_type; uint32_t sfe_in_path_type;
uint32_t sfe_ife_enable; uint32_t sfe_ife_enable;
uint32_t secure_mode; uint32_t epoch_factor;
uint32_t dynamic_sensor_switch_en; bool secure_mode;
uint32_t can_use_lite; bool dynamic_sensor_switch_en;
uint32_t sfe_binned_epoch_cfg; bool can_use_lite;
uint32_t epd_supported; bool sfe_binned_epoch_cfg;
bool epd_supported;
bool aeb_mode;
struct cam_isp_out_port_generic_info *data; struct cam_isp_out_port_generic_info *data;
}; };
@@ -162,6 +164,8 @@ struct cam_isp_in_port_generic_info {
* @sfe_inline_shdr: Flag to indicate if sfe is inline shdr * @sfe_inline_shdr: Flag to indicate if sfe is inline shdr
* @is_offline : Flag to indicate offline * @is_offline : Flag to indicate offline
* @need_top_cfg: Flag to indicate if top cfg is needed * @need_top_cfg: Flag to indicate if top cfg is needed
* @en_secondary_evt: Flag to enable secondary event for the given resource
* depending on the use-case
* @tasklet: Tasklet to schedule bottom halves * @tasklet: Tasklet to schedule bottom halves
* @buf_done_controller: IRQ controller for buf done for version 680 hw * @buf_done_controller: IRQ controller for buf done for version 680 hw
* @cdm_ops: CDM Ops * @cdm_ops: CDM Ops
@@ -186,6 +190,7 @@ struct cam_csid_hw_reserve_resource_args {
bool sfe_inline_shdr; bool sfe_inline_shdr;
bool is_offline; bool is_offline;
bool need_top_cfg; bool need_top_cfg;
bool en_secondary_evt;
void *tasklet; void *tasklet;
void *buf_done_controller; void *buf_done_controller;
void *cdm_ops; void *cdm_ops;

View File

@@ -197,6 +197,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG, CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG,
CAM_ISP_HW_CMD_RM_ENABLE_DISABLE, CAM_ISP_HW_CMD_RM_ENABLE_DISABLE,
CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE, CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE,
CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE,
CAM_ISP_HW_CMD_MAX, CAM_ISP_HW_CMD_MAX,
}; };
@@ -270,19 +271,21 @@ struct cam_isp_blanking_config {
/* /*
* struct cam_isp_hw_event_info: * struct cam_isp_hw_event_info:
* *
* @Brief: Structure to pass event details to hw mgr * @Brief: Structure to pass event details to hw mgr
* *
* @res_type: Type of IFE resource * @res_type: Type of IFE resource
* @res_id: Unique resource ID * @is_secondary_evt: Indicates if event was requested by hw mgr
* @hw_idx: IFE hw index * @res_id: Unique resource ID
* @err_type: Error type if any * @hw_idx: IFE hw index
* @reg_val: Any critical register value captured during irq handling * @err_type: Error type if any
* @hw_type: Hw Type sending the event * @reg_val: Any critical register value captured during irq handling
* @in_core_idx: Input core type if CSID error evt * @hw_type: Hw Type sending the event
* @in_core_idx: Input core type if CSID error evt
* *
*/ */
struct cam_isp_hw_event_info { struct cam_isp_hw_event_info {
enum cam_isp_resource_type res_type; enum cam_isp_resource_type res_type;
bool is_secondary_evt;
uint32_t res_id; uint32_t res_id;
uint32_t hw_idx; uint32_t hw_idx;
uint32_t err_type; uint32_t err_type;
@@ -502,4 +505,18 @@ struct cam_isp_hw_path_port_map {
uint32_t entry[CAM_ISP_HW_PATH_PORT_MAP_MAX][2]; uint32_t entry[CAM_ISP_HW_PATH_PORT_MAP_MAX][2];
}; };
/**
* struct cam_isp_hw_init_config_update:
*
* @Brief: Init config params for CSID/SFE/IFE resources
*
* @node_res: HW Resource
* @init_config: Init config params from userspace
*/
struct cam_isp_hw_init_config_update {
struct cam_isp_resource_node *node_res;
struct cam_isp_init_config *init_config;
};
#endif /* _CAM_ISP_HW_H_ */ #endif /* _CAM_ISP_HW_H_ */

View File

@@ -516,6 +516,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD: case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
case CAM_ISP_HW_CMD_GET_PATH_PORT_MAP: case CAM_ISP_HW_CMD_GET_PATH_PORT_MAP:
case CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE: case CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE:
case CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE:
rc = core_info->vfe_top->hw_ops.process_cmd( rc = core_info->vfe_top->hw_ops.process_cmd(
core_info->vfe_top->top_priv, cmd_type, cmd_args, core_info->vfe_top->top_priv, cmd_type, cmd_args,
arg_size); arg_size);

View File

@@ -69,6 +69,7 @@ struct cam_vfe_mux_ver4_data {
uint32_t qcfa_bin; uint32_t qcfa_bin;
uint32_t dual_hw_idx; uint32_t dual_hw_idx;
uint32_t is_dual; uint32_t is_dual;
uint32_t epoch_factor;
bool is_fe_enabled; bool is_fe_enabled;
bool is_offline; bool is_offline;
bool is_lite; bool is_lite;
@@ -1063,6 +1064,30 @@ static int cam_vfe_core_config_control(
return 0; return 0;
} }
static int cam_vfe_init_config_update(
void *cmd_args, uint32_t arg_size)
{
struct cam_isp_hw_init_config_update *init_cfg = cmd_args;
struct cam_isp_resource_node *rsrc_node = init_cfg->node_res;
struct cam_vfe_mux_ver4_data *mux_data = rsrc_node->res_priv;
if (arg_size != sizeof(struct cam_isp_hw_init_config_update)) {
CAM_ERR(CAM_ISP, "Invalid args size expected: %zu actual: %zu",
sizeof(struct cam_isp_hw_init_config_update),
arg_size);
return -EINVAL;
}
mux_data->epoch_factor =
init_cfg->init_config->epoch_cfg.epoch_factor;
CAM_DBG(CAM_ISP,
"Init Update for res_name: %s epoch_factor: %u%%",
rsrc_node->res_name, mux_data->epoch_factor);
return 0;
}
static int cam_vfe_top_ver4_mux_get_reg_update( static int cam_vfe_top_ver4_mux_get_reg_update(
struct cam_vfe_top_ver4_priv *top_priv, struct cam_vfe_top_ver4_priv *top_priv,
void *cmd_args, uint32_t arg_size) void *cmd_args, uint32_t arg_size)
@@ -1185,7 +1210,7 @@ int cam_vfe_top_acquire_resource(
acquire_data->vfe_in.in_port->horizontal_bin; acquire_data->vfe_in.in_port->horizontal_bin;
res_data->vbi_value = 0; res_data->vbi_value = 0;
res_data->hbi_value = 0; res_data->hbi_value = 0;
res_data->sfe_binned_epoch_cfg = (bool) res_data->sfe_binned_epoch_cfg =
acquire_data->vfe_in.in_port->sfe_binned_epoch_cfg; acquire_data->vfe_in.in_port->sfe_binned_epoch_cfg;
if (res_data->is_dual) if (res_data->is_dual)
@@ -1472,6 +1497,9 @@ int cam_vfe_top_ver4_process_cmd(void *device_priv, uint32_t cmd_type,
case CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE: case CAM_ISP_HW_CMD_APPLY_CLK_BW_UPDATE:
rc = cam_vfe_top_apply_clk_bw_update(&top_priv->top_common, cmd_args, arg_size); rc = cam_vfe_top_apply_clk_bw_update(&top_priv->top_common, cmd_args, arg_size);
break; break;
case CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE:
rc = cam_vfe_init_config_update(cmd_args, arg_size);
break;
default: default:
rc = -EINVAL; rc = -EINVAL;
CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type); CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type);
@@ -1621,6 +1649,7 @@ static int cam_vfe_handle_irq_bottom_half(void *handler_priv,
irq_status[i] = payload->irq_reg_val[i]; irq_status[i] = payload->irq_reg_val[i];
evt_info.hw_idx = vfe_res->hw_intf->hw_idx; evt_info.hw_idx = vfe_res->hw_intf->hw_idx;
evt_info.hw_type = CAM_ISP_HW_TYPE_VFE;
evt_info.res_id = vfe_res->res_id; evt_info.res_id = vfe_res->res_id;
evt_info.res_type = vfe_res->res_type; evt_info.res_type = vfe_res->res_type;
evt_info.reg_val = 0; evt_info.reg_val = 0;
@@ -1781,7 +1810,7 @@ static int cam_vfe_resource_start(
struct cam_isp_resource_node *vfe_res) struct cam_isp_resource_node *vfe_res)
{ {
struct cam_vfe_mux_ver4_data *rsrc_data; struct cam_vfe_mux_ver4_data *rsrc_data;
uint32_t val = 0; uint32_t val = 0, epoch_factor = 50;
int rc = 0; int rc = 0;
uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; uint32_t err_irq_mask[CAM_IFE_IRQ_REGISTERS_MAX];
uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX]; uint32_t irq_mask[CAM_IFE_IRQ_REGISTERS_MAX];
@@ -1817,8 +1846,13 @@ static int cam_vfe_resource_start(
cam_io_r_mb(rsrc_data->mem_base + cam_io_r_mb(rsrc_data->mem_base +
rsrc_data->common_reg->core_cfg_1)); rsrc_data->common_reg->core_cfg_1));
/* % epoch factor from userland */
if ((rsrc_data->epoch_factor) && (rsrc_data->epoch_factor <= 100))
epoch_factor = rsrc_data->epoch_factor;
val = ((rsrc_data->last_line + rsrc_data->vbi_value) - val = ((rsrc_data->last_line + rsrc_data->vbi_value) -
rsrc_data->first_line) / 2; rsrc_data->first_line) * epoch_factor / 100;
if (val > rsrc_data->last_line) if (val > rsrc_data->last_line)
val = rsrc_data->last_line; val = rsrc_data->last_line;
@@ -1828,7 +1862,10 @@ static int cam_vfe_resource_start(
cam_io_w_mb(val, rsrc_data->mem_base + cam_io_w_mb(val, rsrc_data->mem_base +
rsrc_data->common_reg->epoch_height_cfg); rsrc_data->common_reg->epoch_height_cfg);
CAM_DBG(CAM_ISP, "epoch_line_cfg: 0x%X", val); CAM_DBG(CAM_ISP,
"height [0x%x : 0x%x] vbi_val: 0x%x epoch_factor: %u%% epoch_line_cfg: 0x%x",
rsrc_data->first_line, rsrc_data->last_line,
rsrc_data->vbi_value, epoch_factor, val);
skip_core_cfg: skip_core_cfg:
vfe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; vfe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
@@ -1986,6 +2023,7 @@ skip_core_decfg:
vfe_priv->irq_err_handle = 0; vfe_priv->irq_err_handle = 0;
} }
vfe_priv->epoch_factor = 0;
CAM_DBG(CAM_ISP, "VFE:%d Res: %s Stopped", CAM_DBG(CAM_ISP, "VFE:%d Res: %s Stopped",
vfe_res->hw_intf->hw_idx, vfe_res->hw_intf->hw_idx,
vfe_res->res_name); vfe_res->res_name);