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

Commit 79baead7 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: Add support for IFE features"

parents 6188eb8c 24d06999
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -83,6 +83,11 @@ struct cam_hw_done_event_data {
 * @num_acq:               Total number of acquire in the payload
 * @acquire_info:          Acquired resource array pointer
 * @ctxt_to_hw_map:        HW context (returned)
 * @acquired_hw_id:        Acquired hardware mask
 * @acquired_hw_path:      Acquired path mask for an input
 *                         if input splits into multiple paths,
 *                         its updated per hardware
 * valid_acquired_hw:      Valid num of acquired hardware
 *
 */
struct cam_hw_acquire_args {
@@ -92,6 +97,10 @@ struct cam_hw_acquire_args {
	uint32_t                     acquire_info_size;
	uintptr_t                    acquire_info;
	void                        *ctxt_to_hw_map;

	uint32_t    acquired_hw_id[CAM_MAX_ACQ_RES];
	uint32_t    acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT];
	uint32_t    valid_acquired_hw;
};

/**
+50 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/debugfs.h>
@@ -161,6 +161,45 @@ static int __cam_node_handle_acquire_hw_v1(struct cam_node *node,
	return 0;
}

static int __cam_node_handle_acquire_hw_v2(struct cam_node *node,
	struct cam_acquire_hw_cmd_v2 *acquire)
{
	int rc = 0;
	struct cam_context *ctx = NULL;

	if (!acquire)
		return -EINVAL;

	if (acquire->dev_handle <= 0) {
		CAM_ERR(CAM_CORE, "Invalid device handle for context");
		return -EINVAL;
	}

	if (acquire->session_handle <= 0) {
		CAM_ERR(CAM_CORE, "Invalid session handle for context");
		return -EINVAL;
	}

	ctx = (struct cam_context *)cam_get_device_priv(acquire->dev_handle);
	if (!ctx) {
		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
			acquire->dev_handle);
		return -EINVAL;
	}

	rc = cam_context_handle_acquire_hw(ctx, acquire);
	if (rc) {
		CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
			node->name);
		return rc;
	}

	CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d",
		node->name, ctx->ctx_id);

	return 0;
}

static int __cam_node_handle_start_dev(struct cam_node *node,
	struct cam_start_stop_dev_cmd *start)
{
@@ -624,6 +663,8 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)

		if (api_version == 1) {
			acquire_size = sizeof(struct cam_acquire_hw_cmd_v1);
		} else if (api_version == 2) {
			acquire_size = sizeof(struct cam_acquire_hw_cmd_v2);
		} else {
			CAM_ERR(CAM_CORE, "Unsupported api version %d",
				api_version);
@@ -652,6 +693,14 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
				goto acquire_kfree;
			}
			CAM_INFO(CAM_CORE, "Acquire HW successful");
		} else if (api_version == 2) {
			rc = __cam_node_handle_acquire_hw_v2(node, acquire_ptr);
			if (rc) {
				CAM_ERR(CAM_CORE,
					"acquire device failed(rc = %d)", rc);
				goto acquire_kfree;
			}
			CAM_INFO(CAM_CORE, "Acquire HW successful");
		}

		if (copy_to_user((void __user *)cmd->handle, acquire_ptr,
+144 −0
Original line number Diff line number Diff line
@@ -2933,6 +2933,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
		goto free_res;
	}

	memset(&param, 0, sizeof(param));
	param.context_data = ctx;
	param.event_cb = ctx->irq_cb_intf;
	param.num_acq = CAM_API_COMPAT_CONSTANT;
@@ -3007,6 +3008,147 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
	return rc;
}

static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
	void *args)
{
	int rc = 0, i, j;
	struct cam_acquire_hw_cmd_v2 *cmd =
		(struct cam_acquire_hw_cmd_v2 *)args;
	struct cam_hw_acquire_args       param;
	struct cam_hw_release_args       release;
	struct cam_isp_context          *ctx_isp =
		(struct cam_isp_context *) ctx->ctx_priv;
	struct cam_hw_cmd_args           hw_cmd_args;
	struct cam_isp_hw_cmd_args       isp_hw_cmd_args;
	struct cam_isp_acquire_hw_info  *acquire_hw_info = NULL;

	if (!ctx->hw_mgr_intf) {
		CAM_ERR(CAM_ISP, "HW interface is not ready");
		rc = -EFAULT;
		goto end;
	}

	CAM_DBG(CAM_ISP,
		"session_hdl 0x%x, hdl type %d, res %lld",
		cmd->session_handle, cmd->handle_type, cmd->resource_hdl);

	/* for now we only support user pointer */
	if (cmd->handle_type != 1)  {
		CAM_ERR(CAM_ISP, "Only user pointer is supported");
		rc = -EINVAL;
		goto end;
	}

	if (cmd->data_size < sizeof(*acquire_hw_info)) {
		CAM_ERR(CAM_ISP, "data_size is not a valid value");
		goto end;
	}

	acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL);
	if (!acquire_hw_info) {
		rc = -ENOMEM;
		goto end;
	}

	CAM_DBG(CAM_ISP, "start copy resources from user");

	if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl,
		cmd->data_size)) {
		rc = -EFAULT;
		goto free_res;
	}

	memset(&param, 0, sizeof(param));
	param.context_data = ctx;
	param.event_cb = ctx->irq_cb_intf;
	param.num_acq = CAM_API_COMPAT_CONSTANT;
	param.acquire_info_size = cmd->data_size;
	param.acquire_info = (uint64_t) acquire_hw_info;

	/* call HW manager to reserve the resource */
	rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv,
		&param);
	if (rc != 0) {
		CAM_ERR(CAM_ISP, "Acquire device failed");
		goto free_res;
	}

	/* Query the context has rdi only resource */
	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
	hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
	isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_CTX_TYPE;
	hw_cmd_args.u.internal_args = (void *)&isp_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_ISP, "HW command failed");
		goto free_hw;
	}

	if (param.valid_acquired_hw) {
		for (i = 0; i < CAM_MAX_ACQ_RES; i++)
			cmd->hw_info.acquired_hw_id[i] =
				param.acquired_hw_id[i];

		for (i = 0; i < CAM_MAX_ACQ_RES; i++)
			for (j = 0; j < CAM_MAX_HW_SPLIT; j++)
				cmd->hw_info.acquired_hw_path[i][j] =
					param.acquired_hw_path[i][j];
	}
	cmd->hw_info.valid_acquired_hw =
		param.valid_acquired_hw;

	cmd->hw_info.valid_acquired_hw = param.valid_acquired_hw;

	if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_RDI) {
		/*
		 * this context has rdi only resource assign rdi only
		 * state machine
		 */
		CAM_DBG(CAM_ISP, "RDI only session Context");

		ctx_isp->substate_machine_irq =
			cam_isp_ctx_rdi_only_activated_state_machine_irq;
		ctx_isp->substate_machine =
			cam_isp_ctx_rdi_only_activated_state_machine;
		ctx_isp->rdi_only_context = true;
	} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
		CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
		ctx_isp->substate_machine_irq =
			cam_isp_ctx_fs2_state_machine_irq;
		ctx_isp->substate_machine =
			cam_isp_ctx_fs2_state_machine;
	} else {
		CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
		ctx_isp->substate_machine_irq =
			cam_isp_ctx_activated_state_machine_irq;
		ctx_isp->substate_machine =
			cam_isp_ctx_activated_state_machine;
	}

	ctx_isp->hw_ctx = param.ctxt_to_hw_map;
	ctx_isp->hw_acquired = true;
	ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;

	trace_cam_context_state("ISP", ctx);
	CAM_DBG(CAM_ISP,
		"Acquire success on session_hdl 0x%xs ctx_type %d ctx_id %u",
		ctx->session_hdl, isp_hw_cmd_args.u.ctx_type, ctx->ctx_id);
	kfree(acquire_hw_info);
	return rc;

free_hw:
	release.ctxt_to_hw_map = ctx_isp->hw_ctx;
	ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release);
	ctx_isp->hw_ctx = NULL;
	ctx_isp->hw_acquired = false;
free_res:
	kfree(acquire_hw_info);
end:
	return rc;
}


static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx,
	void *args)
{
@@ -3021,6 +3163,8 @@ static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx,
	api_version = *((uint32_t *)args);
	if (api_version == 1)
		rc = __cam_isp_ctx_acquire_hw_v1(ctx, args);
	else if (api_version == 2)
		rc = __cam_isp_ctx_acquire_hw_v2(ctx, args);
	else
		CAM_ERR(CAM_ISP, "Unsupported api version %d", api_version);

+482 −83

File changed.

Preview size limit exceeded, changes collapsed.

+133 −27
Original line number Diff line number Diff line
@@ -294,8 +294,41 @@ static int cam_ife_csid_get_format_ipp_ppp(
	return rc;
}

static int cam_ife_match_vc_dt_pair(int32_t *vc, uint32_t *dt,
	uint32_t num_valid_vc_dt, struct cam_ife_csid_cid_data *cid_data)
{
	uint32_t camera_hw_version;
	int rc = 0;

	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
	if (rc) {
		CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
		return -EINVAL;
	}

	if (camera_hw_version != CAM_CPAS_TITAN_480_V100)
		num_valid_vc_dt = 1;

	switch (num_valid_vc_dt) {
	case 2:
		if (vc[1] != cid_data->vc1 ||
			dt[1] != cid_data->dt1)
			return -EINVAL;
	case 1:
		if (vc[0] != cid_data->vc ||
			dt[0] != cid_data->dt)
			return -EINVAL;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
	struct cam_isp_resource_node **res, int32_t vc, uint32_t dt)
	struct cam_isp_resource_node **res, int32_t *vc, uint32_t *dt,
	uint32_t num_valid_vc_dt)
{
	struct cam_ife_csid_cid_data    *cid_data;
	uint32_t  i = 0;
@@ -308,10 +341,11 @@ static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
			CAM_ISP_RESOURCE_STATE_RESERVED) {
			cid_data = (struct cam_ife_csid_cid_data *)
				csid_hw->cid_res[i].res_priv;
			if (cid_data->vc == vc && cid_data->dt == dt) {
			if (!cam_ife_match_vc_dt_pair(vc, dt,
				num_valid_vc_dt, cid_data)) {
				cid_data->cnt++;
				*res = &csid_hw->cid_res[i];
				CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
				CAM_DBG(CAM_ISP, "CSID:%d CID %d",
					csid_hw->hw_intf->hw_idx,
					csid_hw->cid_res[i].res_id);
				return 0;
@@ -324,8 +358,13 @@ static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
			CAM_ISP_RESOURCE_STATE_AVAILABLE) {
			cid_data = (struct cam_ife_csid_cid_data *)
				csid_hw->cid_res[i].res_priv;
			cid_data->vc  = vc;
			cid_data->dt  = dt;
			cid_data->vc  = vc[0];
			cid_data->dt  = dt[0];
			if (num_valid_vc_dt > 1) {
				cid_data->vc1  = vc[1];
				cid_data->dt1  = dt[1];
				cid_data->is_valid_vc1_dt1 = 1;
			}
			cid_data->cnt = 1;
			csid_hw->cid_res[i].res_state =
				CAM_ISP_RESOURCE_STATE_RESERVED;
@@ -585,9 +624,10 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw,
static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
	struct cam_csid_hw_reserve_resource_args  *cid_reserv)
{
	int rc = 0;
	int rc = 0, i;
	struct cam_ife_csid_cid_data       *cid_data;
	uint32_t camera_hw_version;
	uint32_t valid_vc_dt;

	CAM_DBG(CAM_ISP,
		"CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d",
@@ -595,8 +635,8 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
		cid_reserv->in_port->res_type,
		cid_reserv->in_port->lane_type,
		cid_reserv->in_port->lane_num,
		cid_reserv->in_port->dt,
		cid_reserv->in_port->vc);
		cid_reserv->in_port->dt[0],
		cid_reserv->in_port->vc[0]);

	if (cid_reserv->in_port->res_type >= CAM_ISP_IFE_IN_RES_MAX) {
		CAM_ERR(CAM_ISP, "CSID:%d  Invalid phy sel %d",
@@ -635,15 +675,20 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
		goto end;
	}

	valid_vc_dt = cid_reserv->in_port->num_valid_vc_dt;

	/* CSID  CSI2 v2.0 supports 31 vc  */
	if (cid_reserv->in_port->dt > 0x3f ||
		cid_reserv->in_port->vc > 0x1f) {
		CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d",
	for (i = 0; i < valid_vc_dt; i++) {
		if (cid_reserv->in_port->vc[i] > 0x1f ||
			cid_reserv->in_port->dt[i] > 0x3f) {
			CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d or dt: %d",
				csid_hw->hw_intf->hw_idx,
			cid_reserv->in_port->vc, cid_reserv->in_port->dt);
				cid_reserv->in_port->vc[i],
				cid_reserv->in_port->dt[i]);
			rc = -EINVAL;
			goto end;
		}
	}

	if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG && (
		(cid_reserv->in_port->format < CAM_FORMAT_MIPI_RAW_8 &&
@@ -684,6 +729,21 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
			goto end;
		}
		break;
	case CAM_CPAS_TITAN_480_V100:
		if (cid_reserv->in_port->cust_node == 1) {
			if (cid_reserv->in_port->usage_type == 1) {
				CAM_ERR(CAM_ISP, "Dual IFE is not supported");
				rc = -EINVAL;
				goto end;
			}
			if (csid_hw->hw_intf->hw_idx != 0) {
				CAM_DBG(CAM_ISP, "CSID%d not eligible",
					csid_hw->hw_intf->hw_idx);
				rc = -EINVAL;
				goto end;
			}
		}
		break;
	default:
		break;
	}
@@ -767,7 +827,8 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
	rc = cam_ife_csid_cid_get(csid_hw,
		&cid_reserv->node_res,
		cid_reserv->in_port->vc,
		cid_reserv->in_port->dt);
		cid_reserv->in_port->dt,
		cid_reserv->in_port->num_valid_vc_dt);
	if (rc) {
		CAM_ERR(CAM_ISP, "CSID:%d CID Reserve failed res_type %d",
			csid_hw->hw_intf->hw_idx,
@@ -835,20 +896,27 @@ static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
	struct cam_csid_hw_reserve_resource_args  *reserve)
{
	int rc = 0;
	int rc = 0, i;
	struct cam_ife_csid_path_cfg    *path_data;
	struct cam_isp_resource_node    *res;

	/* CSID  CSI2 v2.0 supports 31 vc */
	if (reserve->in_port->dt > 0x3f || reserve->in_port->vc > 0x1f ||
		(reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX)) {
		CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d mode:%d",
			 csid_hw->hw_intf->hw_idx,
			reserve->in_port->vc, reserve->in_port->dt,
	if (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX) {
		CAM_ERR(CAM_ISP, "CSID: %d Sync Mode: %d",
			reserve->sync_mode);
		return -EINVAL;
	}

	for (i = 0; i < reserve->in_port->num_valid_vc_dt; i++) {
		if (reserve->in_port->dt[i] > 0x3f ||
			reserve->in_port->vc[i] > 0x1f) {
			CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d",
				csid_hw->hw_intf->hw_idx,
				reserve->in_port->vc, reserve->in_port->dt);
			rc = -EINVAL;
			goto end;
		}
	}

	switch (reserve->res_id) {
	case CAM_IFE_PIX_PATH_RES_IPP:
@@ -980,8 +1048,13 @@ static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
		path_data->dt = CAM_IFE_CSID_TPG_DT_VAL;
		path_data->vc = CAM_IFE_CSID_TPG_VC_VAL;
	} else {
		path_data->dt = reserve->in_port->dt;
		path_data->vc = reserve->in_port->vc;
		path_data->dt = reserve->in_port->dt[0];
		path_data->vc = reserve->in_port->vc[0];
		if (reserve->in_port->num_valid_vc_dt) {
			path_data->dt1 = reserve->in_port->dt[1];
			path_data->vc1 = reserve->in_port->vc[1];
			path_data->is_valid_vc1_dt1 = 1;
		}
	}

	if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
@@ -1364,7 +1437,8 @@ static int cam_ife_csid_enable_csi2(
	/* rx cfg1*/
	val = (1 << csid_reg->csi2_reg->csi2_misr_enable_shift_val);
	/* if VC value is more than 3 than set full width of VC */
	if (cid_data->vc > 3)
	if (cid_data->vc > 3 || (cid_data->is_valid_vc1_dt1 &&
		cid_data->vc1 > 3))
		val |= (1 << csid_reg->csi2_reg->csi2_vc_mode_shift_val);

	/* enable packet ecc correction */
@@ -1496,6 +1570,7 @@ static int cam_ife_csid_init_config_pxl_path(
	const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL;
	bool                                      is_ipp;
	uint32_t decode_format = 0, plain_format = 0, val = 0;
	uint32_t camera_hw_version;

	path_data = (struct cam_ife_csid_path_cfg  *) res->res_priv;
	csid_reg = csid_hw->csid_info->csid_reg;
@@ -1540,6 +1615,21 @@ static int cam_ife_csid_init_config_pxl_path(
	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
		pxl_reg->csid_pxl_cfg0_addr);

	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
	if (rc) {
		CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
		camera_hw_version = 0;
	}
	CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version);

	if (path_data->is_valid_vc1_dt1 &&
		camera_hw_version == CAM_CPAS_TITAN_480_V100) {
		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
			pxl_reg->csid_pxl_multi_vcdt_cfg0_addr);
		val |= ((path_data->vc1 << 2) |
			(path_data->dt1 << 7) | 1);
	}

	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
		pxl_reg->csid_pxl_cfg1_addr);

@@ -1907,6 +1997,7 @@ static int cam_ife_csid_init_config_rdi_path(
	struct cam_hw_soc_info                 *soc_info;
	uint32_t path_format = 0, plain_fmt = 0, val = 0, id;
	uint32_t format_measure_addr;
	uint32_t camera_hw_version;

	path_data = (struct cam_ife_csid_path_cfg   *) res->res_priv;
	csid_reg = csid_hw->csid_info->csid_reg;
@@ -1946,6 +2037,21 @@ static int cam_ife_csid_init_config_rdi_path(
	cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
			csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);

	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
	if (rc) {
		CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
		camera_hw_version = 0;
	}
	CAM_DBG(CAM_ISP, "HW version: %x", camera_hw_version);

	if (path_data->is_valid_vc1_dt1 &&
		camera_hw_version == CAM_CPAS_TITAN_480_V100) {
		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
			csid_reg->rdi_reg[id]->csid_rdi_multi_vcdt_cfg0_addr);
		val |= ((path_data->vc1 << 2) |
			(path_data->dt1 << 7) | 1);
	}

	/* select the post irq sub sample strobe for time stamp capture */
	cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base +
			csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr);
Loading