فهرست منبع

msm: camera: reqmgr: Add notify frame skip interface

This change adds support to notify frame skip when CRM
not ready to apply a normal setting. Sensor and custom
device also want to update the HW settings in some
conditions even if a frame is skipped.

CRs-Fixed: 2691642
Change-Id: Ibd2b22655d0f6b6c90663df75a0f5fad8565e918
Signed-off-by: Depeng Shao <[email protected]>
Depeng Shao 5 سال پیش
والد
کامیت
c782e8c3ab

+ 7 - 6
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 <linux/slab.h>
@@ -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);
 

+ 7 - 7
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);
 
 /**

+ 5 - 4
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 <linux/debugfs.h>
@@ -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);

+ 5 - 6
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,

+ 103 - 70
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;
 		}
 

+ 8 - 10
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;
 };
 

+ 24 - 25
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;
 };
 
 /**

+ 115 - 15
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,

+ 8 - 1
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
  *

+ 33 - 2
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);
 

+ 2 - 0
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 {

+ 18 - 1
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),