diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index d3ca4f2e1a..4b3078ad79 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -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. */ #include @@ -182,7 +182,7 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } -int cam_context_handle_crm_apply_default_req( +int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -199,11 +199,12 @@ int cam_context_handle_crm_apply_default_req( } mutex_lock(&ctx->ctx_mutex); - if (ctx->state_machine[ctx->state].crm_ops.apply_default) - rc = ctx->state_machine[ctx->state].crm_ops.apply_default(ctx, - apply); + if (ctx->state_machine[ctx->state].crm_ops.notify_frame_skip) + rc = ctx->state_machine[ctx->state].crm_ops.notify_frame_skip( + ctx, apply); else - CAM_DBG(CAM_CORE, "No crm apply_default in dev %d, state %d", + CAM_DBG(CAM_CORE, + "No crm notify_frame_skip in dev %d, state %d", ctx->dev_hdl, ctx->state); mutex_unlock(&ctx->ctx_mutex); diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index e2fd6c2cce..1f2f8154ae 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.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_CONTEXT_H_ @@ -121,7 +121,7 @@ struct cam_ctx_ioctl_ops { * @link: Link the context * @unlink: Unlink the context * @apply_req: Apply setting for the context - * @apply_default: Apply default settings for the context + * @notify_frame_skip: Notify device that a frame is skipped * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request @@ -136,7 +136,7 @@ struct cam_ctx_crm_ops { struct cam_req_mgr_core_dev_link_setup *unlink); int (*apply_req)(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); - int (*apply_default)(struct cam_context *ctx, + int (*notify_frame_skip)(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); int (*flush_req)(struct cam_context *ctx, struct cam_req_mgr_flush_request *flush); @@ -306,15 +306,15 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); /** - * cam_context_handle_crm_apply_default_req() + * cam_context_handle_crm_notify_frame_skip() * - * @brief: Handle apply default request command + * @brief: Handle notify frame skip command * * @ctx: Object pointer for cam_context - * @apply: Apply default request command payload + * @apply: Notify frame skip command payload * */ -int cam_context_handle_crm_apply_default_req( +int cam_context_handle_crm_notify_frame_skip( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); /** diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 23a440a3e0..6b24bde92a 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -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. */ #include @@ -570,7 +570,7 @@ static int __cam_node_crm_apply_req(struct cam_req_mgr_apply_request *apply) return cam_context_handle_crm_apply_req(ctx, apply); } -static int __cam_node_crm_apply_default_req( +static int __cam_node_crm_notify_frame_skip( struct cam_req_mgr_apply_request *apply) { struct cam_context *ctx = NULL; @@ -587,7 +587,7 @@ static int __cam_node_crm_apply_default_req( trace_cam_apply_req("Node", apply->request_id); - return cam_context_handle_crm_apply_default_req(ctx, apply); + return cam_context_handle_crm_notify_frame_skip(ctx, apply); } static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) @@ -703,7 +703,8 @@ int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf, node->crm_node_intf.flush_req = __cam_node_crm_flush_req; node->crm_node_intf.process_evt = __cam_node_crm_process_evt; node->crm_node_intf.dump_req = __cam_node_crm_dump_req; - node->crm_node_intf.apply_default = __cam_node_crm_apply_default_req; + node->crm_node_intf.notify_frame_skip = + __cam_node_crm_notify_frame_skip; mutex_init(&node->list_mutex); INIT_LIST_HEAD(&node->free_ctx_list); diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index de9777a8b1..f0b782c097 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -219,7 +219,7 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_custom_ctx_apply_req_in_activated, - .apply_default = + .notify_frame_skip = __cam_custom_ctx_apply_default_settings, }, .irq_ops = NULL, @@ -229,7 +229,7 @@ static struct cam_ctx_ops .ioctl_ops = {}, .crm_ops = { .apply_req = __cam_custom_ctx_apply_req_in_activated, - .apply_default = + .notify_frame_skip = __cam_custom_ctx_apply_default_settings, }, .irq_ops = NULL, @@ -414,7 +414,6 @@ static int __cam_custom_ctx_get_dev_info_in_acquired(struct cam_context *ctx, dev_info->dev_id = CAM_REQ_MGR_DEVICE_CUSTOM_HW; dev_info->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; - dev_info->enable_apply_default = true; return 0; } @@ -1452,8 +1451,8 @@ static int __cam_custom_ctx_apply_default_req( ctx_ops = &custom_ctx->substate_machine[ custom_ctx->substate_activated]; - if (ctx_ops->crm_ops.apply_default) { - rc = ctx_ops->crm_ops.apply_default(ctx, apply); + if (ctx_ops->crm_ops.notify_frame_skip) { + rc = ctx_ops->crm_ops.notify_frame_skip(ctx, apply); } else { CAM_WARN_RATE_LIMIT(CAM_CUSTOM, "No handle function in activated substate %d", @@ -1547,7 +1546,7 @@ static struct cam_ctx_ops .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_activated, .apply_req = __cam_custom_ctx_apply_req, - .apply_default = + .notify_frame_skip = __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index ae9a90caed..57ef31ee55 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -21,6 +21,8 @@ static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION]; void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) { + uint32_t pd = 0; + link->link_hdl = 0; link->num_devs = 0; link->max_delay = CAM_PIPELINE_DELAY_0; @@ -49,9 +51,13 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->initial_skip = true; link->sof_timestamp = 0; link->prev_sof_timestamp = 0; - link->enable_apply_default = false; link->skip_init_frame = false; atomic_set(&link->eof_event_cnt, 0); + + for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { + link->req.apply_data[pd].req_id = -1; + link->req.prev_apply_data[pd].req_id = -1; + } } void cam_req_mgr_handle_core_shutdown(void) @@ -212,32 +218,77 @@ static void __cam_req_mgr_find_dev_name( } /** - * __cam_req_mgr_apply_default() + * __cam_req_mgr_notify_frame_skip() * - * @brief : Apply default settings to all devices + * @brief : Notify all devices of frame skipping * @link : link on which we are applying these settings * */ -static void __cam_req_mgr_apply_default( - struct cam_req_mgr_core_link *link) +static int __cam_req_mgr_notify_frame_skip( + struct cam_req_mgr_core_link *link, + uint32_t trigger) { - int i; - struct cam_req_mgr_apply_request apply_req; + int rc = 0, i, pd, idx; + struct cam_req_mgr_apply_request frame_skip; + struct cam_req_mgr_apply *apply_data = NULL; struct cam_req_mgr_connected_device *dev = NULL; + struct cam_req_mgr_tbl_slot *slot = NULL; - if (!link->enable_apply_default) - return; + apply_data = link->req.prev_apply_data; for (i = 0; i < link->num_devs; i++) { dev = &link->l_dev[i]; - apply_req.request_id = 0; - apply_req.dev_hdl = dev->dev_hdl; - apply_req.link_hdl = link->link_hdl; - apply_req.trigger_point = 0; - apply_req.report_if_bubble = 0; - if (dev->ops && dev->ops->apply_default) - dev->ops->apply_default(&apply_req); + if (!dev) + continue; + + pd = dev->dev_info.p_delay; + if (pd >= CAM_PIPELINE_DELAY_MAX) { + CAM_WARN(CAM_CRM, "pd %d greater than max", + pd); + continue; + } + + idx = apply_data[pd].idx; + slot = &dev->pd_tbl->slot[idx]; + + if ((slot->ops.dev_hdl == dev->dev_hdl) && + (slot->ops.is_applied)) { + slot->ops.is_applied = false; + continue; + } + + /* + * If apply_at_eof is enabled do not apply at SOF + * e.x. Flash device + */ + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (dev->dev_hdl == slot->ops.dev_hdl) && + (slot->ops.apply_at_eof)) + continue; + + /* + * If apply_at_eof is not enabled ignore EOF + */ + if ((trigger == CAM_TRIGGER_POINT_EOF) && + (dev->dev_hdl == slot->ops.dev_hdl) && + (!slot->ops.apply_at_eof)) + continue; + + frame_skip.dev_hdl = dev->dev_hdl; + frame_skip.link_hdl = link->link_hdl; + frame_skip.request_id = + apply_data[pd].req_id; + frame_skip.trigger_point = trigger; + frame_skip.report_if_bubble = 0; + + CAM_DBG(CAM_REQ, + "Notify_frame_skip: pd %d req_id %lld", + link->link_hdl, pd, apply_data[pd].req_id); + if ((dev->ops) && (dev->ops->notify_frame_skip)) + dev->ops->notify_frame_skip(&frame_skip); } + + return rc; } /** @@ -716,6 +767,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_apply_request apply_req; struct cam_req_mgr_link_evt_data evt_data; struct cam_req_mgr_tbl_slot *slot = NULL; + struct cam_req_mgr_apply *apply_data = NULL; apply_req.link_hdl = link->link_hdl; apply_req.report_if_bubble = 0; @@ -725,6 +777,8 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.re_apply = true; } + apply_data = link->req.apply_data; + /* * This For loop is to address the special operation requested * by device @@ -740,7 +794,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, continue; } - idx = link->req.apply_data[pd].idx; + idx = apply_data[pd].idx; slot = &dev->pd_tbl->slot[idx]; if (slot->ops.dev_hdl < 0) { @@ -772,20 +826,21 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if ((trigger == CAM_TRIGGER_POINT_EOF) && (!slot->ops.apply_at_eof)) { CAM_DBG(CAM_CRM, "NO EOF DATA FOR REQ: %llu", - link->req.apply_data[pd].req_id); + apply_data[pd].req_id); break; } apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = - link->req.apply_data[pd].req_id; + apply_data[pd].req_id; apply_req.trigger_point = trigger; if ((dev->ops) && (dev->ops->apply_req) && (!slot->ops.is_applied)) { rc = dev->ops->apply_req(&apply_req); if (rc) { *failed_dev = dev; - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, + trigger); return rc; } } @@ -801,7 +856,8 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, CAM_DBG(CAM_REQ, "SEND: link_hdl: %x pd: %d req_id %lld", link->link_hdl, pd, apply_req.request_id); - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, + trigger); return -EAGAIN; } else if ((trigger == CAM_TRIGGER_POINT_EOF) && (slot->ops.apply_at_eof)) { @@ -810,7 +866,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, atomic_dec(&link->eof_event_cnt); CAM_DBG(CAM_REQ, "Req_id: %llu eof_event_cnt : %d", - link->req.apply_data[pd].req_id, + apply_data[pd].req_id, link->eof_event_cnt); return 0; } @@ -830,27 +886,27 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (!(dev->dev_info.trigger & trigger)) continue; - if (link->req.apply_data[pd].skip_idx || - (link->req.apply_data[pd].req_id < 0)) { + if (apply_data[pd].skip_idx || + (apply_data[pd].req_id < 0)) { CAM_DBG(CAM_CRM, "dev %s skip %d req_id %lld", dev->dev_info.name, - link->req.apply_data[pd].skip_idx, - link->req.apply_data[pd].req_id); + apply_data[pd].skip_idx, + apply_data[pd].req_id); apply_req.dev_hdl = dev->dev_hdl; - apply_req.request_id = 0; + apply_req.request_id = + link->req.prev_apply_data[pd].req_id; apply_req.trigger_point = 0; apply_req.report_if_bubble = 0; - if ((link->enable_apply_default) && - (dev->ops) && (dev->ops->apply_default)) - dev->ops->apply_default(&apply_req); + if ((dev->ops) && (dev->ops->notify_frame_skip)) + dev->ops->notify_frame_skip(&apply_req); continue; } apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = - link->req.apply_data[pd].req_id; - idx = link->req.apply_data[pd].idx; + apply_data[pd].req_id; + idx = apply_data[pd].idx; slot = &dev->pd_tbl->slot[idx]; apply_req.report_if_bubble = in_q->slot[idx].recover; @@ -880,7 +936,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.trigger_point = trigger; CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd %d req_id %lld", + "SEND: %d link_hdl: %x pd %d req_id %lld", link->link_hdl, pd, apply_req.request_id); if (dev->ops && dev->ops->apply_req) { rc = dev->ops->apply_req(&apply_req); @@ -906,8 +962,13 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (dev->ops && dev->ops->process_evt) dev->ops->process_evt(&evt_data); } - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, trigger); + } else { + memcpy(link->req.prev_apply_data, link->req.apply_data, + CAM_PIPELINE_DELAY_MAX * + sizeof(struct cam_req_mgr_apply)); } + return rc; } @@ -1598,7 +1659,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, rc = -EPERM; } spin_unlock_bh(&link->link_state_spin_lock); - __cam_req_mgr_apply_default(link); + __cam_req_mgr_notify_frame_skip(link, trigger); goto error; } } @@ -2197,38 +2258,6 @@ static void __cam_req_mgr_unreserve_link( /* Workqueue context processing section */ -/** - * cam_req_mgr_process_send_req() - * - * @brief: This runs in workque thread context. Call core funcs to send - * apply request id to drivers. - * @priv : link information. - * @data : contains information about frame_id, link etc. - * - * @return: 0 on success. - */ -int cam_req_mgr_process_send_req(void *priv, void *data) -{ - int rc = 0; - struct cam_req_mgr_core_link *link = NULL; - struct cam_req_mgr_send_request *send_req = NULL; - struct cam_req_mgr_req_queue *in_q = NULL; - struct cam_req_mgr_connected_device *dev; - - if (!data || !priv) { - CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv); - rc = -EINVAL; - goto end; - } - link = (struct cam_req_mgr_core_link *)priv; - send_req = (struct cam_req_mgr_send_request *)data; - in_q = send_req->in_q; - - rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF, &dev); -end: - return rc; -} - /** * cam_req_mgr_process_flush_req() * @@ -2242,6 +2271,7 @@ end: int cam_req_mgr_process_flush_req(void *priv, void *data) { int rc = 0, i = 0, idx = -1; + uint32_t pd = 0; struct cam_req_mgr_flush_info *flush_info = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_req_queue *in_q = NULL; @@ -2306,6 +2336,12 @@ int cam_req_mgr_process_flush_req(void *priv, void *data) if (device->ops && device->ops->flush_req) rc = device->ops->flush_req(&flush_req); } + + for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) { + link->req.apply_data[pd].req_id = -1; + link->req.prev_apply_data[pd].req_id = -1; + } + complete(&link->workq_comp); mutex_unlock(&link->req.lock); @@ -3297,9 +3333,6 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, if (dev->dev_info.p_delay > max_delay) max_delay = dev->dev_info.p_delay; - if (dev->dev_info.enable_apply_default) - link->enable_apply_default = true; - subscribe_event |= (uint32_t)dev->dev_info.trigger; } diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 6a806f1925..cc135d716d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -281,17 +281,20 @@ struct cam_req_mgr_req_queue { /** * struct cam_req_mgr_req_data - * @in_q : Poiner to Input request queue - * @l_tbl : unique pd request tables. - * @num_tbl : how many unique pd value devices are present - * @apply_data : Holds information about request id for a request - * @lock : mutex lock protecting request data ops. + * @in_q : Poiner to Input request queue + * @l_tbl : unique pd request tables. + * @num_tbl : how many unique pd value devices are present + * @apply_data : Holds information about request id for a request + * @prev_apply_data : Holds information about request id for a previous + * applied request + * @lock : mutex lock protecting request data ops. */ struct cam_req_mgr_req_data { struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_req_tbl *l_tbl; int32_t num_tbl; struct cam_req_mgr_apply apply_data[CAM_PIPELINE_DELAY_MAX]; + struct cam_req_mgr_apply prev_apply_data[CAM_PIPELINE_DELAY_MAX]; struct mutex lock; }; @@ -365,10 +368,6 @@ struct cam_req_mgr_connected_device { * applying the settings * @trigger_cnt : trigger count value per device initiating the trigger * @eof_event_cnt : Atomic variable to track the number of EOF requests - * @enable_apply_default : Link will apply a default settings to devices on - * frames where actual settings are not available. - * This will account for all devices irrespective of - * pipeline delay * @skip_init_frame : skip initial frames crm_wd_timer validation in the * case of long exposure use case */ @@ -404,7 +403,6 @@ struct cam_req_mgr_core_link { bool dual_trigger; uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; atomic_t eof_event_cnt; - bool enable_apply_default; bool skip_init_frame; }; diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index b832f3a46e..231cf397f3 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -44,17 +44,20 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); /** * @brief: cam req mgr to camera device drivers * - * @cam_req_mgr_get_dev_info: to fetch details about device linked - * @cam_req_mgr_link_setup : to establish link with device for a session - * @cam_req_mgr_apply_req : CRM asks device to apply certain request id - * @cam_req_mgr_flush_req : Flush or cancel request - * cam_req_mgr_process_evt : generic events - * @cam_req_mgr_dump_req : dump request + * @cam_req_mgr_get_dev_info : to fetch details about device linked + * @cam_req_mgr_link_setup : to establish link with device for a session + * @cam_req_mgr_apply_req : CRM asks device to apply certain request id + * @cam_req_mgr_notify_frame_skip: CRM asks device to apply setting for + * frame skip + * @cam_req_mgr_flush_req : Flush or cancel request + * cam_req_mgr_process_evt : generic events + * @cam_req_mgr_dump_req : dump request */ typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *); typedef int (*cam_req_mgr_link_setup)(struct cam_req_mgr_core_dev_link_setup *); typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *); -typedef int (*cam_req_mgr_apply_default)(struct cam_req_mgr_apply_request *); +typedef int (*cam_req_mgr_notify_frame_skip)( + struct cam_req_mgr_apply_request *); typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *); typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *); typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *); @@ -79,22 +82,22 @@ struct cam_req_mgr_crm_cb { /** * @brief : cam_req_mgr_kmd_ops - func table * - * @get_dev_info : payload to fetch device details - * @link_setup : payload to establish link with device - * @apply_req : payload to apply request id on a device linked - * @apply_default: payload to trigger default apply settings - * @flush_req : payload to flush request - * @process_evt : payload to generic event - * @dump_req : payload to dump request + * @get_dev_info : payload to fetch device details + * @link_setup : payload to establish link with device + * @apply_req : payload to apply request id on a device linked + * @notify_frame_skip: payload to notify frame skip + * @flush_req : payload to flush request + * @process_evt : payload to generic event + * @dump_req : payload to dump request */ struct cam_req_mgr_kmd_ops { - cam_req_mgr_get_dev_info get_dev_info; - cam_req_mgr_link_setup link_setup; - cam_req_mgr_apply_req apply_req; - cam_req_mgr_apply_default apply_default; - cam_req_mgr_flush_req flush_req; - cam_req_mgr_process_evt process_evt; - cam_req_mgr_dump_req dump_req; + cam_req_mgr_get_dev_info get_dev_info; + cam_req_mgr_link_setup link_setup; + cam_req_mgr_apply_req apply_req; + cam_req_mgr_notify_frame_skip notify_frame_skip; + cam_req_mgr_flush_req flush_req; + cam_req_mgr_process_evt process_evt; + cam_req_mgr_dump_req dump_req; }; /** @@ -296,9 +299,6 @@ struct cam_req_mgr_notify_stop { * @p_delay : delay between time settings applied and take effect * @trigger : Trigger point for the client * @trigger_on : This device provides trigger - * @enable_apply_default : Device requests CRM to apply default - * settings for devices on a link if actual - * settings for a given frame is not available */ struct cam_req_mgr_device_info { int32_t dev_hdl; @@ -307,7 +307,6 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; - bool enable_apply_default; }; /** diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 762b0a65e0..42f92279f0 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -78,6 +78,20 @@ static void cam_sensor_release_per_frame_resource( } } } + + if (s_ctrl->i2c_data.frame_skip != NULL) { + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(s_ctrl->i2c_data.frame_skip[i]); + if (i2c_set->is_settings_valid == 1) { + i2c_set->is_settings_valid = -1; + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request: %lld rc: %d", + i2c_set->request_id, rc); + } + } + } } static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, @@ -137,7 +151,6 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, CAM_ERR(CAM_SENSOR, "Invalid packet params"); rc = -EINVAL; goto end; - } if ((csl_packet->header.op_code & 0xFFFFFF) != @@ -240,6 +253,22 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, } break; } + case CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE: { + if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || + (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { + CAM_WARN(CAM_SENSOR, + "Rxed Update packets without linking"); + goto end; + } + + i2c_reg_settings = + &i2c_data->frame_skip[csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY]; + CAM_DBG(CAM_SENSOR, "Received not ready packet: %lld req: %lld", + csl_packet->header.request_id % MAX_PER_FRAME_ARRAY, + csl_packet->header.request_id); + break; + } case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: { if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || (s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) { @@ -275,6 +304,12 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl, cam_sensor_update_req_mgr(s_ctrl, csl_packet); } + if ((csl_packet->header.op_code & 0xFFFFFF) == + CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE) { + i2c_reg_settings->request_id = + csl_packet->header.request_id; + } + end: return rc; } @@ -1207,6 +1242,7 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, break; } case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE: + case CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE: case CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE: default: return 0; @@ -1227,11 +1263,16 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, } } else { offset = req_id % MAX_PER_FRAME_ARRAY; - i2c_set = &(s_ctrl->i2c_data.per_frame[offset]); - if (i2c_set->is_settings_valid == 1 && - i2c_set->request_id == req_id) { + + if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE) + i2c_set = s_ctrl->i2c_data.frame_skip; + else + i2c_set = s_ctrl->i2c_data.per_frame; + + if (i2c_set[offset].is_settings_valid == 1 && + i2c_set[offset].request_id == req_id) { list_for_each_entry(i2c_list, - &(i2c_set->list_head), list) { + &(i2c_set[offset].list_head), list) { rc = cam_sensor_i2c_modes_util( &(s_ctrl->io_master_info), i2c_list); @@ -1250,13 +1291,13 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, /* Change the logic dynamically */ for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { if ((req_id >= - s_ctrl->i2c_data.per_frame[i].request_id) && + i2c_set[i].request_id) && (top < - s_ctrl->i2c_data.per_frame[i].request_id) && - (s_ctrl->i2c_data.per_frame[i].is_settings_valid + i2c_set[i].request_id) && + (i2c_set[i].is_settings_valid == 1)) { del_req_id = top; - top = s_ctrl->i2c_data.per_frame[i].request_id; + top = i2c_set[i].request_id; } } @@ -1276,12 +1317,12 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { if ((del_req_id > - s_ctrl->i2c_data.per_frame[i].request_id) && ( - s_ctrl->i2c_data.per_frame[i].is_settings_valid + i2c_set[i].request_id) && ( + i2c_set[i].is_settings_valid == 1)) { - s_ctrl->i2c_data.per_frame[i].request_id = 0; + i2c_set[i].request_id = 0; rc = delete_request( - &(s_ctrl->i2c_data.per_frame[i])); + &(i2c_set[i])); if (rc < 0) CAM_ERR(CAM_SENSOR, "Delete request Fail:%lld rc:%d", @@ -1297,6 +1338,8 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply) { int32_t rc = 0; struct cam_sensor_ctrl_t *s_ctrl = NULL; + enum cam_sensor_packet_opcodes opcode = + CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE; if (!apply) return -EINVAL; @@ -1307,11 +1350,40 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply) CAM_ERR(CAM_SENSOR, "Device data is NULL"); return -EINVAL; } - CAM_DBG(CAM_REQ, " Sensor update req id: %lld", apply->request_id); + + CAM_DBG(CAM_REQ, " Sensor[%d] update req id: %lld", + s_ctrl->soc_info.index, apply->request_id); trace_cam_apply_req("Sensor", apply->request_id); mutex_lock(&(s_ctrl->cam_sensor_mutex)); rc = cam_sensor_apply_settings(s_ctrl, apply->request_id, - CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE); + opcode); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return rc; +} + +int32_t cam_sensor_notify_frame_skip(struct cam_req_mgr_apply_request *apply) +{ + int32_t rc = 0; + struct cam_sensor_ctrl_t *s_ctrl = NULL; + enum cam_sensor_packet_opcodes opcode = + CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE; + + if (!apply) + return -EINVAL; + + s_ctrl = (struct cam_sensor_ctrl_t *) + cam_get_device_priv(apply->dev_hdl); + if (!s_ctrl) { + CAM_ERR(CAM_SENSOR, "Device data is NULL"); + return -EINVAL; + } + + CAM_DBG(CAM_REQ, " Sensor[%d] handle frame skip for req id: %lld", + s_ctrl->soc_info.index, apply->request_id); + trace_cam_notify_frame_skip("Sensor", apply->request_id); + mutex_lock(&(s_ctrl->cam_sensor_mutex)); + rc = cam_sensor_apply_settings(s_ctrl, apply->request_id, + opcode); mutex_unlock(&(s_ctrl->cam_sensor_mutex)); return rc; } @@ -1346,6 +1418,12 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) return -EINVAL; } + if (s_ctrl->i2c_data.frame_skip == NULL) { + CAM_ERR(CAM_SENSOR, "i2c not ready data is NULL"); + mutex_unlock(&(s_ctrl->cam_sensor_mutex)); + return -EINVAL; + } + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { s_ctrl->last_flush_req = flush_req->req_id; CAM_DBG(CAM_SENSOR, "last reqest to flush is %lld", @@ -1374,6 +1452,28 @@ int32_t cam_sensor_flush_request(struct cam_req_mgr_flush_request *flush_req) } } + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + i2c_set = &(s_ctrl->i2c_data.frame_skip[i]); + + if ((flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) + && (i2c_set->request_id != flush_req->req_id)) + continue; + + if (i2c_set->is_settings_valid == 1) { + rc = delete_request(i2c_set); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "delete request for not ready packet: %lld rc: %d", + i2c_set->request_id, rc); + + if (flush_req->type == + CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) { + cancel_req_id_found = 1; + break; + } + } + } + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ && !cancel_req_id_found) CAM_DBG(CAM_SENSOR, diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h index b7a5923a6a..507776843a 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_CORE_H_ @@ -47,6 +47,13 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, int64_t req_id, */ int cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply); +/** + * @apply: Req mgr structure for notifying frame skip + * + * This API notifies a frame is skipped + */ +int cam_sensor_notify_frame_skip(struct cam_req_mgr_apply_request *apply); + /** * @flush: Req mgr structure for flushing request * diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c index 9d85f3f9c1..fd529205cd 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c @@ -176,25 +176,39 @@ static int32_t cam_sensor_driver_i2c_probe(struct i2c_client *client, goto unreg_subdev; } + s_ctrl->i2c_data.frame_skip = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (s_ctrl->i2c_data.frame_skip == NULL) { + rc = -ENOMEM; + goto free_perframe; + } + INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); - for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.frame_skip[i].list_head)); + } s_ctrl->bridge_intf.device_hdl = -1; s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; + s_ctrl->bridge_intf.ops.notify_frame_skip = + cam_sensor_notify_frame_skip; s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request; s_ctrl->sensordata->power_info.dev = soc_info->dev; return rc; +free_perframe: + kfree(s_ctrl->i2c_data.per_frame); unreg_subdev: cam_unregister_subdev(&(s_ctrl->v4l2_dev_str)); free_s_ctrl: @@ -252,20 +266,32 @@ static int cam_sensor_component_bind(struct device *dev, goto unreg_subdev; } + s_ctrl->i2c_data.frame_skip = + kzalloc(sizeof(struct i2c_settings_array) * + MAX_PER_FRAME_ARRAY, GFP_KERNEL); + if (s_ctrl->i2c_data.frame_skip == NULL) { + rc = -ENOMEM; + goto free_perframe; + } + INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamoff_settings.list_head)); INIT_LIST_HEAD(&(s_ctrl->i2c_data.read_settings.list_head)); - for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head)); + INIT_LIST_HEAD(&(s_ctrl->i2c_data.frame_skip[i].list_head)); + } s_ctrl->bridge_intf.device_hdl = -1; s_ctrl->bridge_intf.link_hdl = -1; s_ctrl->bridge_intf.ops.get_dev_info = cam_sensor_publish_dev_info; s_ctrl->bridge_intf.ops.link_setup = cam_sensor_establish_link; s_ctrl->bridge_intf.ops.apply_req = cam_sensor_apply_request; + s_ctrl->bridge_intf.ops.notify_frame_skip = + cam_sensor_notify_frame_skip; s_ctrl->bridge_intf.ops.flush_req = cam_sensor_flush_request; s_ctrl->sensordata->power_info.dev = &pdev->dev; @@ -274,6 +300,9 @@ static int cam_sensor_component_bind(struct device *dev, CAM_DBG(CAM_SENSOR, "Component bound successfully"); return rc; + +free_perframe: + kfree(s_ctrl->i2c_data.per_frame); unreg_subdev: cam_unregister_subdev(&(s_ctrl->v4l2_dev_str)); free_s_ctrl: @@ -305,6 +334,7 @@ static void cam_sensor_component_unbind(struct device *dev, devm_clk_put(soc_info->dev, soc_info->clk[i]); kfree(s_ctrl->i2c_data.per_frame); + kfree(s_ctrl->i2c_data.frame_skip); platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL); devm_kfree(&pdev->dev, s_ctrl); @@ -342,6 +372,7 @@ static int cam_sensor_driver_i2c_remove(struct i2c_client *client) devm_clk_put(soc_info->dev, soc_info->clk[i]); kfree(s_ctrl->i2c_data.per_frame); + kfree(s_ctrl->i2c_data.frame_skip); v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL); kfree(s_ctrl); diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 5889243dd3..e18b4bb1c8 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -154,6 +154,7 @@ enum cam_sensor_packet_opcodes { CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMOFF, CAM_SENSOR_PACKET_OPCODE_SENSOR_READ, + CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE, CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127 }; @@ -306,6 +307,7 @@ struct i2c_data_settings { struct i2c_settings_array streamoff_settings; struct i2c_settings_array read_settings; struct i2c_settings_array *per_frame; + struct i2c_settings_array *frame_skip; }; struct cam_sensor_power_ctrl_t { diff --git a/drivers/cam_utils/cam_trace.h b/drivers/cam_utils/cam_trace.h index c564b1582a..8868c43068 100644 --- a/drivers/cam_utils/cam_trace.h +++ b/drivers/cam_utils/cam_trace.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. */ #if !defined(_CAM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) @@ -140,6 +140,23 @@ TRACE_EVENT(cam_apply_req, ) ); +TRACE_EVENT(cam_notify_frame_skip, + TP_PROTO(const char *entity, uint64_t req_id), + TP_ARGS(entity, req_id), + TP_STRUCT__entry( + __string(entity, entity) + __field(uint64_t, req_id) + ), + TP_fast_assign( + __assign_str(entity, entity); + __entry->req_id = req_id; + ), + TP_printk( + "%8s: NotifyFrameSkip request=%llu", + __get_str(entity), __entry->req_id + ) +); + TRACE_EVENT(cam_flush_req, TP_PROTO(struct cam_req_mgr_core_link *link, struct cam_req_mgr_flush_info *info),