diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 267b23dafa..d3ca4f2e1a 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -182,6 +182,34 @@ int cam_context_handle_crm_apply_req(struct cam_context *ctx, return rc; } +int cam_context_handle_crm_apply_default_req( + struct cam_context *ctx, + struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if (!apply) { + CAM_ERR(CAM_CORE, "Invalid apply request payload"); + return -EINVAL; + } + + 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); + else + CAM_DBG(CAM_CORE, "No crm apply_default in dev %d, state %d", + ctx->dev_hdl, ctx->state); + mutex_unlock(&ctx->ctx_mutex); + + return rc; +} + int cam_context_handle_crm_flush_req(struct cam_context *ctx, struct cam_req_mgr_flush_request *flush) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index 770451faad..e2fd6c2cce 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -121,6 +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 * @flush_req: Flush request to remove request ids * @process_evt: Handle event notification from CRM.(optional) * @dump_req: Dump information for the issue request @@ -135,6 +136,8 @@ 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, + struct cam_req_mgr_apply_request *apply); int (*flush_req)(struct cam_context *ctx, struct cam_req_mgr_flush_request *flush); int (*process_evt)(struct cam_context *ctx, @@ -302,6 +305,18 @@ int cam_context_handle_crm_unlink(struct cam_context *ctx, 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() + * + * @brief: Handle apply default request command + * + * @ctx: Object pointer for cam_context + * @apply: Apply default request command payload + * + */ +int cam_context_handle_crm_apply_default_req( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply); + /** * cam_context_handle_crm_flush_req() * diff --git a/drivers/cam_core/cam_node.c b/drivers/cam_core/cam_node.c index 672ae35b62..23a440a3e0 100644 --- a/drivers/cam_core/cam_node.c +++ b/drivers/cam_core/cam_node.c @@ -570,6 +570,26 @@ 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( + struct cam_req_mgr_apply_request *apply) +{ + struct cam_context *ctx = NULL; + + if (!apply) + return -EINVAL; + + ctx = (struct cam_context *) cam_get_device_priv(apply->dev_hdl); + if (!ctx) { + CAM_ERR(CAM_CORE, "Can not get context for handle %d", + apply->dev_hdl); + return -EINVAL; + } + + trace_cam_apply_req("Node", apply->request_id); + + return cam_context_handle_crm_apply_default_req(ctx, apply); +} + static int __cam_node_crm_flush_req(struct cam_req_mgr_flush_request *flush) { struct cam_context *ctx = NULL; @@ -683,6 +703,7 @@ 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; 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 0fff3f0792..b38b08750c 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -162,6 +162,7 @@ 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; } @@ -456,6 +457,32 @@ static int __cam_custom_release_dev_in_acquired(struct cam_context *ctx, return rc; } +static int __cam_custom_ctx_apply_default_settings( + struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) +{ + int rc = 0; + struct cam_custom_context *custom_ctx = + (struct cam_custom_context *) ctx->ctx_priv; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_custom_hw_cmd_args custom_hw_cmd_args; + + hw_cmd_args.ctxt_to_hw_map = custom_ctx->hw_ctx; + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + custom_hw_cmd_args.cmd_type = + CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG; + hw_cmd_args.u.internal_args = (void *)&custom_hw_cmd_args; + + rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_cmd_args); + if (rc) + CAM_ERR(CAM_CUSTOM, + "Failed to apply default settings rc %d", rc); + else + CAM_DBG(CAM_CUSTOM, "Applied default settings rc %d", rc); + + return rc; +} + static int __cam_custom_ctx_apply_req_in_activated_state( struct cam_context *ctx, struct cam_req_mgr_apply_request *apply) { @@ -1194,6 +1221,8 @@ static struct cam_ctx_ops .unlink = __cam_custom_ctx_unlink_in_activated, .apply_req = __cam_custom_ctx_apply_req_in_activated_state, + .apply_default = + __cam_custom_ctx_apply_default_settings, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, }, diff --git a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c index 7587e41aa6..eb42913ea4 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c +++ b/drivers/cam_cust/cam_custom_hw_mgr/cam_custom_hw_mgr.c @@ -1281,6 +1281,57 @@ static int cam_custom_hw_mgr_irq_cb(void *data, return 0; } +static int cam_custom_mgr_cmd(void *hw_mgr_priv, void *cmd_args) +{ + int rc = 0; + struct cam_hw_cmd_args *hw_cmd_args = cmd_args; + struct cam_custom_hw_cmd_args *custom_hw_cmd_args; + struct cam_custom_hw_mgr_ctx *custom_ctx = NULL; + + if (!hw_mgr_priv || !cmd_args) { + CAM_ERR(CAM_CUSTOM, "Invalid arguments"); + return -EINVAL; + } + + custom_ctx = + (struct cam_custom_hw_mgr_ctx *) + hw_cmd_args->ctxt_to_hw_map; + + if (!custom_ctx || !custom_ctx->ctx_in_use) { + CAM_ERR(CAM_CUSTOM, "Fatal: Invalid context is used"); + return -EPERM; + } + + switch (hw_cmd_args->cmd_type) { + case CAM_HW_MGR_CMD_INTERNAL: + if (!hw_cmd_args->u.internal_args) { + CAM_ERR(CAM_CUSTOM, "Invalid cmd arguments"); + return -EINVAL; + } + + custom_hw_cmd_args = (struct cam_custom_hw_cmd_args *) + hw_cmd_args->u.internal_args; + + switch (custom_hw_cmd_args->cmd_type) { + case CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG: + CAM_DBG(CAM_CUSTOM, "configure RUP and scratch buffer"); + /* Handle event accordingly */ + break; + default: + CAM_ERR(CAM_CUSTOM, "Invalid HW mgr command:0x%x", + hw_cmd_args->cmd_type); + rc = -EINVAL; + break; + } + break; + default: + rc = -EINVAL; + break; + } + + return rc; +} + int cam_custom_hw_mgr_init(struct device_node *of_node, struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) { @@ -1376,6 +1427,7 @@ int cam_custom_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_prepare_update = cam_custom_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_custom_mgr_config_hw; hw_mgr_intf->hw_reset = cam_custom_hw_mgr_reset; + hw_mgr_intf->hw_cmd = cam_custom_mgr_cmd; if (iommu_hdl) *iommu_hdl = g_custom_hw_mgr.img_iommu_hdl; diff --git a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h index 0577cd6ef9..b47ebb5f78 100644 --- a/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h +++ b/drivers/cam_cust/cam_custom_hw_mgr/include/cam_custom_hw_mgr_intf.h @@ -32,6 +32,22 @@ enum cam_custom_cmd_types { CAM_CUSTOM_SUBMIT_REQ, }; +enum cam_custom_hw_mgr_cmd { + CAM_CUSTOM_HW_MGR_CMD_NONE, + CAM_CUSTOM_HW_MGR_PROG_DEFAULT_CONFIG, +}; + +/** + * struct cam_custom_hw_cmd_args - Payload for hw manager command + * + * @cmd_type HW command type + * @reserved any other required data + */ +struct cam_custom_hw_cmd_args { + uint32_t cmd_type; + uint32_t reserved; +}; + /** * struct cam_custom_stop_args - hardware stop arguments * diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 5359cf1e7f..701757d00d 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -49,6 +49,7 @@ 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; atomic_set(&link->eof_event_cnt, 0); } @@ -209,6 +210,35 @@ static void __cam_req_mgr_find_dev_name( } } +/** + * __cam_req_mgr_apply_default() + * + * @brief : Apply default settings to all devices + * @link : link on which we are applying these settings + * + */ +static void __cam_req_mgr_apply_default( + struct cam_req_mgr_core_link *link) +{ + int i; + struct cam_req_mgr_apply_request apply_req; + struct cam_req_mgr_connected_device *dev = NULL; + + if (!link->enable_apply_default) + return; + + 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); + } +} + /** * __cam_req_mgr_notify_error_on_link() * @@ -738,6 +768,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, rc = dev->ops->apply_req(&apply_req); if (rc) { *failed_dev = dev; + __cam_req_mgr_apply_default(link); return rc; } } @@ -750,6 +781,10 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, slot->ops.skip_next_frame) { slot->ops.skip_next_frame = false; slot->ops.is_applied = true; + 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); return -EAGAIN; } else if ((trigger == CAM_TRIGGER_POINT_EOF) && (slot->ops.apply_at_eof)) { @@ -774,16 +809,27 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, pd); continue; } - if (link->req.apply_data[pd].skip_idx || - link->req.apply_data[pd].req_id < 0) { - CAM_DBG(CAM_CRM, "skip %d req_id %lld", - link->req.apply_data[pd].skip_idx, - link->req.apply_data[pd].req_id); - continue; - } + if (!(dev->dev_info.trigger & trigger)) continue; + if (link->req.apply_data[pd].skip_idx || + (link->req.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_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = 0; + 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); + continue; + } + apply_req.dev_hdl = dev->dev_hdl; apply_req.request_id = link->req.apply_data[pd].req_id; @@ -843,6 +889,7 @@ 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); } return rc; } @@ -1534,6 +1581,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); goto error; } } @@ -3223,6 +3271,9 @@ 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 e406590c94..3f1102b8d5 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -364,6 +364,10 @@ 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 */ struct cam_req_mgr_core_link { int32_t link_hdl; @@ -397,6 +401,7 @@ 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; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index c40a479419..b832f3a46e 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -54,6 +54,7 @@ typedef int (*cam_req_mgr_notify_stop)(struct cam_req_mgr_notify_stop *); 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_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 *); @@ -81,6 +82,7 @@ struct cam_req_mgr_crm_cb { * @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 @@ -89,6 +91,7 @@ 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; @@ -293,6 +296,9 @@ 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; @@ -301,6 +307,7 @@ struct cam_req_mgr_device_info { enum cam_pipeline_delay p_delay; uint32_t trigger; bool trigger_on; + bool enable_apply_default; }; /**