Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 438fc6a8 authored by Jigarkumar Zala's avatar Jigarkumar Zala Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: common: Enabling EOF support for flash



New usecase for flash driver requires to be trigger at EOF.
This change adds the new operation code support in flash
driver along with EOF enable support in crm and across
other drivers. Also to improve the performance, this change
adds the logic to dynamically update the subscribe event to
CRM, so that CRM can enqueue EOF events when Flash or any other
device add the request for EOF.

CRs-Fixed: 2633194
Change-Id: I2f68ac7fc6a4699debd39b64319728cdf17bbcfa
Signed-off-by: default avatarJigarkumar Zala <jzala@codeaurora.org>
parent d5c59602
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -3910,6 +3910,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
			add_req.dev_hdl  = ctx->dev_hdl;
			add_req.req_id   = req->request_id;
			add_req.skip_before_applying = 0;
			add_req.trigger_eof = false;
			rc = ctx->ctx_crm_intf->add_req(&add_req);
			if (rc) {
				CAM_ERR(CAM_ISP, "Add req failed: req id=%llu",
@@ -4525,7 +4526,8 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,

	ctx->link_hdl = link->link_hdl;
	ctx->ctx_crm_intf = link->crm_cb;
	ctx_isp->subscribe_event = link->subscribe_event;
	ctx_isp->subscribe_event =
		CAM_TRIGGER_POINT_SOF | CAM_TRIGGER_POINT_EOF;
	ctx_isp->trigger_id = link->trigger_id;

	/* change state only if we had the init config */
+142 −27
Original line number Diff line number Diff line
@@ -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;
	atomic_set(&link->eof_event_cnt, 0);
}

void cam_req_mgr_handle_core_shutdown(void)
@@ -456,10 +457,15 @@ static void __cam_req_mgr_flush_req_slot(
				tbl->pd, idx, tbl->slot[idx].state);
			tbl->slot[idx].req_ready_map = 0;
			tbl->slot[idx].state = CRM_REQ_STATE_EMPTY;
			tbl->slot[idx].ops.apply_at_eof = false;
			tbl->slot[idx].ops.skip_next_frame = false;
			tbl->slot[idx].ops.dev_hdl = -1;
			tbl->slot[idx].ops.is_applied = false;
			tbl = tbl->next;
		}
	}

	atomic_set(&link->eof_event_cnt, 0);
	in_q->wr_idx = 0;
	in_q->rd_idx = 0;
}
@@ -502,6 +508,10 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link,
			tbl->pd, idx, tbl->slot[idx].state);
		tbl->slot[idx].req_ready_map = 0;
		tbl->slot[idx].state = CRM_REQ_STATE_EMPTY;
		tbl->slot[idx].ops.apply_at_eof = false;
		tbl->slot[idx].ops.skip_next_frame = false;
		tbl->slot[idx].ops.dev_hdl = -1;
		tbl->slot[idx].ops.is_applied = false;
		tbl = tbl->next;
	}
}
@@ -668,6 +678,10 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
			apply_req.re_apply = true;
	}

	/*
	 * This For loop is to address the special operation requested
	 * by device
	 */
	for (i = 0; i < link->num_devs; i++) {
		dev = &link->l_dev[i];
		if (!dev)
@@ -681,37 +695,76 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,

		idx = link->req.apply_data[pd].idx;
		slot = &dev->pd_tbl->slot[idx];
		/*
		 * Just let flash go for this request and other
		 * device get restricted
		 */

		if ((slot->skip_next_frame != true) ||
			(slot->dev_hdl != dev->dev_hdl))
		if (slot->ops.dev_hdl < 0) {
			CAM_DBG(CAM_CRM,
				"No special ops detected for this table slot");
			continue;
		}

		if (!(dev->dev_info.trigger & trigger))
		if (slot->ops.apply_at_eof && slot->ops.skip_next_frame) {
			CAM_ERR(CAM_CRM,
				"Both EOF and SOF trigger is not supported");
			return -EINVAL;
		}

		if (dev->dev_hdl != slot->ops.dev_hdl) {
			CAM_DBG(CAM_CRM,
				"Dev_hdl : %d Not matched:: Expected dev_hdl: %d",
				dev->dev_hdl, slot->ops.dev_hdl);
			continue;
		}

		/* This one is to prevent EOF request to apply on SOF*/
		if ((trigger == CAM_TRIGGER_POINT_SOF) &&
			(slot->ops.apply_at_eof)) {
			CAM_DBG(CAM_CRM, "EOF event cannot be applied at SOF");
			break;
		}

		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);
			break;
		}

		apply_req.dev_hdl = dev->dev_hdl;
		apply_req.request_id =
			link->req.apply_data[pd].req_id;
		apply_req.trigger_point = trigger;
		if (dev->ops && dev->ops->apply_req) {
		if ((dev->ops) && (dev->ops->apply_req) &&
			(!slot->ops.is_applied)) {
			rc = dev->ops->apply_req(&apply_req);
			if (rc) {
				*failed_dev = dev;
				return rc;
			}
		}

		CAM_DBG(CAM_REQ,
			"SEND: link_hdl: %x pd: %d req_id %lld",
			link->link_hdl, pd, apply_req.request_id);
			slot->skip_next_frame = false;
			slot->is_applied = true;

		if (trigger == CAM_TRIGGER_POINT_SOF &&
			slot->ops.skip_next_frame) {
			slot->ops.skip_next_frame = false;
			slot->ops.is_applied = true;
			return -EAGAIN;
		} else if ((trigger == CAM_TRIGGER_POINT_EOF) &&
			(slot->ops.apply_at_eof)) {
			slot->ops.apply_at_eof = false;
			if (atomic_read(&link->eof_event_cnt) > 0)
				atomic_dec(&link->eof_event_cnt);
			CAM_DBG(CAM_REQ,
				"Req_id: %llu eof_event_cnt : %d",
				link->req.apply_data[pd].req_id,
				link->eof_event_cnt);
			return 0;
		}
	}

	/* For regular send requests */
	for (i = 0; i < link->num_devs; i++) {
		dev = &link->l_dev[i];
		if (dev) {
@@ -739,12 +792,29 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
			apply_req.report_if_bubble =
				in_q->slot[idx].recover;

			if ((slot->dev_hdl == dev->dev_hdl) &&
				(slot->is_applied == true)) {
				slot->is_applied = false;
			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;

			apply_req.trigger_point = trigger;
			CAM_DBG(CAM_REQ,
				"SEND: link_hdl: %x pd %d req_id %lld",
@@ -1507,6 +1577,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
		if (link->trigger_mask == link->subscribe_event) {
			slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
			link->trigger_mask = 0;
			if (!(atomic_read(&link->eof_event_cnt)) &&
				(trigger == CAM_TRIGGER_POINT_EOF)) {
				link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF;
				CAM_DBG(CAM_CRM,
					"Update link subscribe_event: %d",
					link->subscribe_event);
			}
			CAM_DBG(CAM_CRM, "req %d is applied on link %x",
				slot->req_id,
				link->link_hdl);
@@ -1591,11 +1668,19 @@ static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl,
 */
static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay)
{
	int i = 0;

	struct cam_req_mgr_req_tbl *tbl =
		kzalloc(sizeof(struct cam_req_mgr_req_tbl), GFP_KERNEL);
	if (tbl != NULL) {
		tbl->num_slots = MAX_REQ_SLOTS;
		CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots);
		for (i = 0; i < MAX_REQ_SLOTS; i++) {
			tbl->slot[i].ops.apply_at_eof = false;
			tbl->slot[i].ops.skip_next_frame = false;
			tbl->slot[i].ops.dev_hdl = -1;
			tbl->slot[i].ops.is_applied = false;
		}
	}

	return tbl;
@@ -2310,17 +2395,27 @@ int cam_req_mgr_process_add_req(void *priv, void *data)
	}

	slot = &tbl->slot[idx];
	slot->is_applied = false;
	slot->ops.is_applied = false;
	if ((add_req->skip_before_applying & 0xFF) > slot->inject_delay) {
		slot->inject_delay = (add_req->skip_before_applying & 0xFF);
		slot->dev_hdl = add_req->dev_hdl;
		if (add_req->skip_before_applying & SKIP_NEXT_FRAME)
			slot->skip_next_frame = true;
		if (add_req->skip_before_applying & SKIP_NEXT_FRAME) {
			slot->ops.skip_next_frame = true;
			slot->ops.dev_hdl = add_req->dev_hdl;
		}
		CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %llu",
			add_req->req_id,
			(add_req->skip_before_applying & 0xFF));
	}

	/* Used when Precise Flash is enabled */
	if ((add_req->trigger_eof) && (!add_req->skip_before_applying)) {
		slot->ops.apply_at_eof = true;
		slot->ops.dev_hdl = add_req->dev_hdl;
		CAM_DBG(CAM_REQ,
			"Req_id %llu added for EOF tigger for Device: %s",
			add_req->req_id, device->dev_info.name);
	}

	if (slot->state != CRM_REQ_STATE_PENDING &&
		slot->state != CRM_REQ_STATE_EMPTY) {
		CAM_WARN(CAM_CRM,
@@ -2658,9 +2753,10 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)
		return -EINVAL;
	}

	CAM_DBG(CAM_REQ, "dev name %s dev_hdl %d dev req %lld",
	CAM_DBG(CAM_REQ,
		"dev name %s dev_hdl %d dev req %lld, trigger_eof: %d",
		__cam_req_mgr_dev_handle_to_name(add_req->dev_hdl, link),
		add_req->dev_hdl, add_req->req_id);
		add_req->dev_hdl, add_req->req_id, add_req->trigger_eof);

	mutex_lock(&link->lock);
	spin_lock_bh(&link->link_state_spin_lock);
@@ -2695,6 +2791,16 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)
	dev_req->link_hdl = add_req->link_hdl;
	dev_req->dev_hdl = add_req->dev_hdl;
	dev_req->skip_before_applying = add_req->skip_before_applying;
	dev_req->trigger_eof = add_req->trigger_eof;
	if (dev_req->trigger_eof) {
		link->subscribe_event |= CAM_TRIGGER_POINT_EOF;
		atomic_inc(&link->eof_event_cnt);
		CAM_DBG(CAM_REQ,
			"Req_id: %llu, eof_event_cnt: %d, link subscribe event: %d",
			dev_req->req_id, link->eof_event_cnt,
			link->subscribe_event);
	}

	task->process_cb = &cam_req_mgr_process_add_req;
	rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
	CAM_DBG(CAM_CRM, "X: dev %x dev req %lld",
@@ -2935,6 +3041,12 @@ static int cam_req_mgr_cb_notify_trigger(

	trigger_id = trigger_data->trigger_id;

	if ((!atomic_read(&link->eof_event_cnt)) &&
		(trigger_data->trigger == CAM_TRIGGER_POINT_EOF)) {
		CAM_DBG(CAM_CRM, "Not any request to schedule at EOF");
		goto end;
	}

	spin_lock_bh(&link->link_state_spin_lock);
	if (link->state < CAM_CRM_LINK_STATE_READY) {
		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
@@ -2943,7 +3055,8 @@ static int cam_req_mgr_cb_notify_trigger(
		goto end;
	}

	if ((link->watchdog) && (link->watchdog->pause_timer))
	if ((link->watchdog) && (link->watchdog->pause_timer) &&
		(trigger_data->trigger == CAM_TRIGGER_POINT_SOF))
		link->watchdog->pause_timer = false;

	if (link->dual_trigger) {
@@ -2963,7 +3076,9 @@ static int cam_req_mgr_cb_notify_trigger(
		}
	}

	if (trigger_data->trigger == CAM_TRIGGER_POINT_SOF)
		crm_timer_reset(link->watchdog);

	spin_unlock_bh(&link->link_state_spin_lock);

	task = cam_req_mgr_workq_get_task(link->workq);
@@ -2974,7 +3089,8 @@ static int cam_req_mgr_cb_notify_trigger(
		goto end;
	}
	task_data = (struct crm_task_payload *)task->payload;
	task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF;
	task_data->type = (trigger_data->trigger == CAM_TRIGGER_POINT_SOF) ?
		CRM_WORKQ_TASK_NOTIFY_SOF : CRM_WORKQ_TASK_NOTIFY_EOF;
	notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u;
	notify_trigger->frame_id = trigger_data->frame_id;
	notify_trigger->link_hdl = trigger_data->link_hdl;
@@ -3022,8 +3138,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
		if (link_info->u.link_info_v1.num_devices >
			CAM_REQ_MGR_MAX_HANDLES)
			return -EPERM;
	}
	else if (link_info->version == VERSION_2) {
	} else if (link_info->version == VERSION_2) {
		if (link_info->u.link_info_v2.num_devices >
			CAM_REQ_MGR_MAX_HANDLES_V2)
			return -EPERM;
+28 −12
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ enum crm_workq_task_type {
	CRM_WORKQ_TASK_DEV_ADD_REQ,
	CRM_WORKQ_TASK_APPLY_REQ,
	CRM_WORKQ_TASK_NOTIFY_SOF,
	CRM_WORKQ_TASK_NOTIFY_EOF,
	CRM_WORKQ_TASK_NOTIFY_ERR,
	CRM_WORKQ_TASK_NOTIFY_FREEZE,
	CRM_WORKQ_TASK_SCHED_REQ,
@@ -178,25 +179,39 @@ struct cam_req_mgr_apply {
	int32_t skip_idx;
};

/**
 * struct crm_tbl_slot_special_ops
 * @dev_hdl         : Device handle who requested for special ops
 * @apply_at_eof    : Boolean Identifier for request to be applied at EOF
 * @skip_next_frame : Flag to drop the frame after skip_before_apply frame
 * @is_applied      : Flag to identify if request is already applied to device
 *                    in previous frame
 */
struct crm_tbl_slot_special_ops {
	int32_t dev_hdl;
	bool apply_at_eof;
	bool skip_next_frame;
	bool is_applied;
};

/**
 * struct cam_req_mgr_tbl_slot
 * @idx             : slot index
 * @req_ready_map   : mask tracking which all devices have request ready
 * @state           : state machine for life cycle of a slot
 * @inject_delay    : insert extra bubbling for flash type of use cases
 * @dev_hdl         : stores the dev_hdl, who is having higher inject delay
 * @skip_next_frame : flag to drop the frame after skip_before_apply frame
 * @is_applied      : flag to identify if request is already applied to
 *                    device.
 * @ops             : special operation for the table slot
 *                    e.g.
 *                    skip_next frame: in case of applying one device
 *                    and skip others
 *                    apply_at_eof: device that needs to apply at EOF
 */
struct cam_req_mgr_tbl_slot {
	int32_t                                idx;
	uint32_t                               req_ready_map;
	enum crm_req_state                     state;
	uint32_t                               inject_delay;
	int32_t             dev_hdl;
	bool                skip_next_frame;
	bool                is_applied;
	struct  crm_tbl_slot_special_ops       ops;
};

/**
@@ -348,6 +363,7 @@ struct cam_req_mgr_connected_device {
 * @dual_trigger         : Links needs to wait for two triggers prior to
 *                         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
 */
struct cam_req_mgr_core_link {
	int32_t                              link_hdl;
@@ -380,7 +396,7 @@ struct cam_req_mgr_core_link {
	uint64_t                             prev_sof_timestamp;
	bool                                 dual_trigger;
	uint32_t    trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS];

	atomic_t                             eof_event_cnt;
};

/**
+13 −10
Original line number Diff line number Diff line
@@ -190,7 +190,8 @@ enum cam_req_mgr_device_id {
 *                                         connected devices
 * @CAM_REQ_MGR_LINK_EVT_PAUSE           : to pause the link
 * @CAM_REQ_MGR_LINK_EVT_RESUME          : resumes the link which was paused
 * @CAM_REQ_MGR_LINK_EVT_SOF_FREEZE : request manager has detected an sof freeze
 * @CAM_REQ_MGR_LINK_EVT_SOF_FREEZE      : request manager has detected an
 *                                         sof freeze
 * @CAM_REQ_MGR_LINK_EVT_MAX             : invalid event type
 */
enum cam_req_mgr_link_evt_type {
@@ -261,12 +262,15 @@ struct cam_req_mgr_error_notify {
 * @req_id               : req id which device is ready to process
 * @skip_before_applying : before applying req mgr introduce bubble
 *                         by not sending request to devices. ex: IFE and Flash
 * @trigger_eof          : to identify that one of the device at this slot needs
 *                         to be apply at EOF
 */
struct cam_req_mgr_add_request {
	int32_t  link_hdl;
	int32_t  dev_hdl;
	uint64_t req_id;
	uint32_t skip_before_applying;
	bool     trigger_eof;
};


@@ -363,7 +367,6 @@ struct cam_req_mgr_link_evt_data {
	int32_t  link_hdl;
	int32_t  dev_hdl;
	uint64_t req_id;

	enum cam_req_mgr_link_evt_type evt_type;
	union {
		enum cam_req_mgr_device_error error;
+1 −0
Original line number Diff line number Diff line
@@ -370,6 +370,7 @@ static void cam_actuator_update_req_mgr(
	add_req.req_id = csl_packet->header.request_id;
	add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl;
	add_req.skip_before_applying = 0;
	add_req.trigger_eof = false;

	if (a_ctrl->bridge_intf.crm_cb &&
		a_ctrl->bridge_intf.crm_cb->add_req) {
Loading