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

Commit 89b3962f authored by Junzhe Zou's avatar Junzhe Zou Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: icp: allow reconfig io during streaming



Get io config settings in BLOB, and submit to FW during
streaming to support MFSR.

Change-Id: Ic884e0e48352293737d1e45f42e27e74970b9e24
Signed-off-by: default avatarJunzhe Zou <jnzhezou@codeaurora.org>
parent f5073b48
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -92,7 +92,8 @@ int hfi_write_cmd(void *cmd_ptr)
		(q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) :
		(read_idx - q->qhdr_write_idx);
	if (empty_space <= size_in_words) {
		CAM_ERR(CAM_HFI, "failed");
		CAM_ERR(CAM_HFI, "failed: empty space %u, size_in_words %u",
			empty_space, size_in_words);
		rc = -EIO;
		goto err;
	}
+160 −54
Original line number Diff line number Diff line
@@ -1833,7 +1833,7 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data)

	rc = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG, &read_len);
	if (rc) {
		CAM_DBG(CAM_ICP, "Unable to read msg q");
		CAM_DBG(CAM_ICP, "Unable to read msg q rc %d", rc);
	} else {
		read_len = read_len << BYTE_WORD_SHIFT;
		msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf;
@@ -2859,8 +2859,10 @@ static int cam_icp_mgr_enqueue_config(struct cam_icp_hw_mgr *hw_mgr,
	struct hfi_cmd_work_data *task_data;
	struct hfi_cmd_ipebps_async *hfi_cmd;
	struct cam_hw_update_entry *hw_update_entries;
	struct icp_frame_info *frame_info = NULL;

	request_id = *(uint64_t *)config_args->priv;
	frame_info = (struct icp_frame_info *)config_args->priv;
	request_id = frame_info->request_id;
	hw_update_entries = config_args->hw_update_entries;
	CAM_DBG(CAM_ICP, "req_id = %lld %pK", request_id, config_args->priv);

@@ -2882,6 +2884,81 @@ static int cam_icp_mgr_enqueue_config(struct cam_icp_hw_mgr *hw_mgr,
	return rc;
}

static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
	uint32_t io_buf_addr)
{
	int rc = 0;
	struct hfi_cmd_work_data *task_data;
	struct hfi_cmd_ipebps_async ioconfig_cmd;
	unsigned long rem_jiffies;
	int timeout = 5000;
	struct crm_workq_task *task;
	uint32_t size_in_words;

	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
	if (!task)
		return -ENOMEM;

	ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async);
	ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
	else
		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;

	reinit_completion(&ctx_data->wait_complete);

	ioconfig_cmd.num_fw_handles = 1;
	ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
	ioconfig_cmd.payload.indirect = io_buf_addr;
	ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
	ioconfig_cmd.user_data2 = (uint64_t)0x0;
	task_data = (struct hfi_cmd_work_data *)task->payload;
	task_data->data = (void *)&ioconfig_cmd;
	task_data->request_id = 0;
	task_data->type = ICP_WORKQ_TASK_MSG_TYPE;
	task->process_cb = cam_icp_mgr_process_cmd;
	size_in_words = (*(uint32_t *)task_data->data) >> 2;
	CAM_INFO(CAM_ICP, "size_in_words %u", size_in_words);
	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
		CRM_TASK_PRIORITY_0);
	if (rc)
		return rc;

	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
		msecs_to_jiffies((timeout)));
	if (!rem_jiffies) {
		rc = -ETIMEDOUT;
		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
	}

	return rc;
}

static int cam_icp_mgr_send_recfg_io(struct cam_icp_hw_ctx_data *ctx_data,
	struct hfi_cmd_ipebps_async *ioconfig_cmd, uint64_t req_id)
{
	int rc = 0;
	struct hfi_cmd_work_data *task_data;
	struct crm_workq_task *task;

	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
	if (!task)
		return -ENOMEM;

	task_data = (struct hfi_cmd_work_data *)task->payload;
	task_data->data = (void *)ioconfig_cmd;
	task_data->request_id = req_id;
	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
	task->process_cb = cam_icp_mgr_process_cmd;
	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
		CRM_TASK_PRIORITY_0);
	if (rc)
		return rc;

	return rc;
}

static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
{
	int rc = 0;
@@ -2890,6 +2967,7 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
	struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
	struct cam_hw_config_args *config_args = config_hw_args;
	struct cam_icp_hw_ctx_data *ctx_data = NULL;
	struct icp_frame_info *frame_info = NULL;

	if (!hw_mgr || !config_args) {
		CAM_ERR(CAM_ICP, "Invalid arguments %pK %pK",
@@ -2913,11 +2991,23 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
		return -EINVAL;
	}

	req_id = *(uint64_t *)config_args->priv;
	frame_info = (struct icp_frame_info *)config_args->priv;
	req_id = frame_info->request_id;
	idx = cam_icp_clk_idx_from_req_id(ctx_data, req_id);
	ctx_data->hfi_frame_process.fw_process_flag[idx] = true;
	cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx);

	CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id,
		frame_info->io_config);

	if (frame_info->io_config != 0) {
		CAM_INFO(CAM_ICP, "Send recfg io");
		rc = cam_icp_mgr_send_recfg_io(ctx_data,
			&frame_info->hfi_cfg_io_cmd, req_id);
		if (rc)
			CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd");
	}

	rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args);
	if (rc)
		goto config_err;
@@ -3148,7 +3238,9 @@ static int cam_icp_packet_generic_blob_handler(void *user_data,
	struct icp_cmd_generic_blob *blob;
	struct cam_icp_hw_ctx_data *ctx_data;
	uint32_t index;
	size_t io_buf_size;
	int rc = 0;
	uint64_t pResource;

	if (!blob_data || (blob_size == 0)) {
		CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data,
@@ -3177,6 +3269,28 @@ static int cam_icp_packet_generic_blob_handler(void *user_data,
			clk_info->compressed_bw);
		break;

	case CAM_ICP_CMD_GENERIC_BLOB_CFG_IO:
		CAM_DBG(CAM_ICP, "CAM_ICP_CMD_GENERIC_BLOB_CFG_IO");
		pResource = *((uint32_t *)blob_data);
		if (copy_from_user(&ctx_data->icp_dev_io_info,
			(void __user *)pResource,
			sizeof(struct cam_icp_acquire_dev_info))) {
			CAM_ERR(CAM_ICP, "Failed in copy from user");
			return -EFAULT;
		}
		CAM_DBG(CAM_ICP, "buf handle %d",
			ctx_data->icp_dev_io_info.io_config_cmd_handle);
		rc = cam_mem_get_io_buf(
			ctx_data->icp_dev_io_info.io_config_cmd_handle,
			icp_hw_mgr.iommu_hdl,
			blob->io_buf_addr, &io_buf_size);
		if (rc)
			CAM_ERR(CAM_ICP, "Failed in blob update");
		else
			CAM_DBG(CAM_ICP, "io buf addr %llu",
				*blob->io_buf_addr);
		break;

	default:
		CAM_WARN(CAM_ICP, "Invalid blob type %d", blob_type);
		break;
@@ -3187,7 +3301,8 @@ static int cam_icp_packet_generic_blob_handler(void *user_data,
static int cam_icp_process_generic_cmd_buffer(
	struct cam_packet *packet,
	struct cam_icp_hw_ctx_data *ctx_data,
	int32_t index)
	int32_t index,
	uint64_t *io_buf_addr)
{
	int i, rc = 0;
	struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -3195,6 +3310,7 @@ static int cam_icp_process_generic_cmd_buffer(

	cmd_generic_blob.ctx = ctx_data;
	cmd_generic_blob.frame_info_idx = index;
	cmd_generic_blob.io_buf_addr = io_buf_addr;

	cmd_desc = (struct cam_cmd_buf_desc *)
		((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
@@ -3214,6 +3330,28 @@ static int cam_icp_process_generic_cmd_buffer(
	return rc;
}

static int cam_icp_mgr_process_cfg_io_cmd(
	struct cam_icp_hw_ctx_data *ctx_data,
	struct hfi_cmd_ipebps_async *ioconfig_cmd,
	uint64_t request_id,
	uint64_t io_config)
{
	ioconfig_cmd->size = sizeof(struct hfi_cmd_ipebps_async);
	ioconfig_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
		ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
	else
		ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;

	ioconfig_cmd->num_fw_handles = 1;
	ioconfig_cmd->fw_handles[0] = ctx_data->fw_handle;
	ioconfig_cmd->payload.indirect = io_config;
	ioconfig_cmd->user_data1 = (uint64_t)ctx_data;
	ioconfig_cmd->user_data2 = request_id;

	return 0;
}

static int cam_icp_mgr_update_hfi_frame_process(
	struct cam_icp_hw_ctx_data *ctx_data,
	struct cam_packet *packet,
@@ -3221,6 +3359,7 @@ static int cam_icp_mgr_update_hfi_frame_process(
	int32_t *idx)
{
	int32_t index, rc;
	struct hfi_cmd_ipebps_async *hfi_cmd = NULL;

	index = find_first_zero_bit(ctx_data->hfi_frame_process.bitmap,
		ctx_data->hfi_frame_process.bits);
@@ -3232,15 +3371,27 @@ static int cam_icp_mgr_update_hfi_frame_process(

	ctx_data->hfi_frame_process.request_id[index] =
		packet->header.request_id;
	rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index);
	ctx_data->hfi_frame_process.frame_info[index].request_id =
		packet->header.request_id;
	ctx_data->hfi_frame_process.frame_info[index].io_config = 0;
	rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index,
		&ctx_data->hfi_frame_process.frame_info[index].io_config);
	if (rc) {
		clear_bit(index, ctx_data->hfi_frame_process.bitmap);
		ctx_data->hfi_frame_process.request_id[index] = -1;
		return rc;
	}

	if (ctx_data->hfi_frame_process.frame_info[index].io_config)  {
		hfi_cmd = (struct hfi_cmd_ipebps_async *)&ctx_data->
			hfi_frame_process.frame_info[index].hfi_cfg_io_cmd;
		rc = cam_icp_mgr_process_cfg_io_cmd(ctx_data, hfi_cmd,
			packet->header.request_id, ctx_data->
			hfi_frame_process.frame_info[index].io_config);
	}
	*idx = index;

	return 0;
	return rc;
}

static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
@@ -3321,7 +3472,7 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,

	prepare_args->num_hw_update_entries = 1;
	prepare_args->hw_update_entries[0].addr = (uint64_t)hfi_cmd;
	prepare_args->priv = &ctx_data->hfi_frame_process.request_id[idx];
	prepare_args->priv = &ctx_data->hfi_frame_process.frame_info[idx];

	CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u",
		packet->header.request_id, ctx_data->ctx_id);
@@ -3585,53 +3736,6 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
	return rc;
}

static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
	uint32_t io_buf_addr)
{
	int rc = 0;
	struct hfi_cmd_work_data *task_data;
	struct hfi_cmd_ipebps_async ioconfig_cmd;
	unsigned long rem_jiffies;
	int timeout = 5000;
	struct crm_workq_task *task;

	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
	if (!task)
		return -ENOMEM;

	ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async);
	ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
	else
		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;

	reinit_completion(&ctx_data->wait_complete);
	ioconfig_cmd.num_fw_handles = 1;
	ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
	ioconfig_cmd.payload.indirect = io_buf_addr;
	ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
	ioconfig_cmd.user_data2 = (uint64_t)0x0;
	task_data = (struct hfi_cmd_work_data *)task->payload;
	task_data->data = (void *)&ioconfig_cmd;
	task_data->request_id = 0;
	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
	task->process_cb = cam_icp_mgr_process_cmd;
	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
		CRM_TASK_PRIORITY_0);
	if (rc)
		return rc;

	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
			msecs_to_jiffies((timeout)));
	if (!rem_jiffies) {
		rc = -ETIMEDOUT;
		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
	}

	return rc;
}

static int cam_icp_mgr_create_handle(uint32_t dev_type,
	struct cam_icp_hw_ctx_data *ctx_data)
{
@@ -3844,6 +3948,8 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)

	icp_dev_acquire_info = ctx_data->icp_dev_acquire_info;

	CAM_DBG(CAM_ICP, "acquire io buf handle %d",
		icp_dev_acquire_info->io_config_cmd_handle);
	rc = cam_mem_get_io_buf(
		icp_dev_acquire_info->io_config_cmd_handle,
		hw_mgr->iommu_hdl,
+19 −0
Original line number Diff line number Diff line
@@ -125,6 +125,19 @@ struct clk_work_data {
	void *data;
};

/**
  * struct icp_frame_info
  * @request_id: request id
  * @io_config: the address of io config
  * @hfi_cfg_io_cmd: command struct to be sent to hfi
  */
struct icp_frame_info {
	uint64_t request_id;
	uint64_t io_config;
	struct hfi_cmd_ipebps_async hfi_cfg_io_cmd;
};


/**
 * struct hfi_frame_process_info
 * @hfi_frame_cmd: Frame process command info
@@ -136,6 +149,7 @@ struct clk_work_data {
 * @out_resource: Out sync info
 * @fw_process_flag: Frame process flag
 * @clk_info: Clock information for a request
 * @frame_info: information needed to process request
 */
struct hfi_frame_process_info {
	struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX];
@@ -149,6 +163,7 @@ struct hfi_frame_process_info {
	uint32_t in_free_resource[CAM_FRAME_CMD_MAX];
	uint32_t fw_process_flag[CAM_FRAME_CMD_MAX];
	struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX];
	struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX];
};

/**
@@ -189,6 +204,7 @@ struct cam_ctx_clk_info {
 * @clk_info: Current clock info of a context
 * @watch_dog: watchdog timer handle
 * @watch_dog_reset_counter: Counter for watch dog reset
 * @icp_dev_io_info: io config resource
 */
struct cam_icp_hw_ctx_data {
	void *context_priv;
@@ -208,16 +224,19 @@ struct cam_icp_hw_ctx_data {
	struct cam_ctx_clk_info clk_info;
	struct cam_req_mgr_timer *watch_dog;
	uint32_t watch_dog_reset_counter;
	struct cam_icp_acquire_dev_info icp_dev_io_info;
};

/**
 * struct icp_cmd_generic_blob
 * @ctx: Current context info
 * @frame_info_idx: Index used for frame process info
 * @io_buf_addr: pointer to io buffer address
 */
struct icp_cmd_generic_blob {
	struct cam_icp_hw_ctx_data *ctx;
	uint32_t frame_info_idx;
	uint64_t *io_buf_addr;
};

/**
+2 −1
Original line number Diff line number Diff line
@@ -59,8 +59,9 @@
/* Command meta types */
#define CAM_ICP_CMD_META_GENERIC_BLOB           0x1

/* Generic blon types */
/* Generic blob types */
#define CAM_ICP_CMD_GENERIC_BLOB_CLK            0x1
#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO         0x2

/**
 * struct cam_icp_clk_bw_request