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

Commit 03e07e03 authored by Camera Software Integration's avatar Camera Software Integration Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: cpas: Add mechanism to check camnoc idle status" into camera-kernel.lnx.4.0

parents 74553e55 3f527598
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -1544,6 +1544,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
	struct cam_cpas_private_soc *soc_private = NULL;
	int rc = 0;
	long result;
	int retry_camnoc_idle = 0;

	if (!hw_priv || !stop_args) {
		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
@@ -1597,6 +1598,18 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
			}
		}

		if (cpas_core->internal_ops.qchannel_handshake) {
			rc = cpas_core->internal_ops.qchannel_handshake(
				cpas_hw, false);
			if (rc) {
				CAM_ERR(CAM_CPAS,
					"failed in qchannel_handshake rc=%d",
					rc);
				retry_camnoc_idle = 1;
				/* Do not return error, passthrough */
			}
		}

		rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info);
		if (rc) {
			CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc);
@@ -1612,6 +1625,19 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
				atomic_read(&cpas_core->irq_count));
		}

		/* try again incase camnoc is still not idle */
		if (cpas_core->internal_ops.qchannel_handshake &&
			retry_camnoc_idle) {
			rc = cpas_core->internal_ops.qchannel_handshake(
				cpas_hw, false);
			if (rc) {
				CAM_ERR(CAM_CPAS,
					"failed in qchannel_handshake rc=%d",
					rc);
				/* Do not return error, passthrough */
			}
		}

		rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info,
			true, false);
		if (rc) {
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@ enum cam_cpas_access_type {
 * @power_off: Function pointer for hw core specific power off settings
 * @setup_qos_settings: Function pointer for hw to select a specific qos header
 * @print_poweron_settings: Function pointer for hw to print poweron settings
 * @qchannel_handshake: Function pointer for hw core specific qchannel
 *                      handshake settings
 *
 */
struct cam_cpas_internal_ops {
@@ -85,6 +87,7 @@ struct cam_cpas_internal_ops {
	int (*setup_qos_settings)(struct cam_hw_info *cpas_hw,
		uint32_t selection_mask);
	int (*print_poweron_settings)(struct cam_hw_info *cpas_hw);
	int (*qchannel_handshake)(struct cam_hw_info *cpas_hw, bool power_on);
};

/**
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#define CAM_CPAS_POLL_MIN_USECS 200
/* Maximum usecs to sleep while polling */
#define CAM_CPAS_POLL_MAX_USECS 250
/* Number of times to retry while polling */
#define CAM_CPAS_POLL_QH_RETRY_CNT 50

/**
 * enum cam_cpas_hw_type - Enum for CPAS HW type
+1 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops)
	internal_ops->power_off = NULL;
	internal_ops->setup_qos_settings = NULL;
	internal_ops->print_poweron_settings = NULL;
	internal_ops->qchannel_handshake = NULL;

	return 0;
}
+62 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#include "cam_req_mgr_workq.h"

struct cam_camnoc_info *camnoc_info;
struct cam_cpas_camnoc_qchannel *qchannel_info;


#define CAMNOC_SLAVE_MAX_ERR_CODE 7
static const char * const camnoc_salve_err_code[] = {
@@ -818,11 +820,65 @@ static int cam_cpastop_poweroff(struct cam_hw_info *cpas_hw)
	return rc;
}

static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw,
	bool power_on)
{
	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
	int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CPASTOP];
	uint32_t mask = 0;
	uint32_t wait_data, qchannel_status, qdeny;
	int rc = 0;

	if (reg_indx == -1)
		return -EINVAL;

	if (!qchannel_info)
		return 0;

	if (power_on) {
		/* wait for QACCEPTN in QCHANNEL status*/
		mask = BIT(0);
		wait_data = 1;
	} else {
		/* Clear the quiecience request in QCHANNEL ctrl*/
		cam_io_w_mb(0, soc_info->reg_map[reg_indx].mem_base +
			qchannel_info->qchannel_ctrl);
		/* wait for QACCEPTN and QDENY in QCHANNEL status*/
		mask = BIT(1) | BIT(0);
		wait_data = 0;
	}

	rc = cam_io_poll_value_wmask(
		soc_info->reg_map[reg_indx].mem_base +
		qchannel_info->qchannel_status,
		wait_data, mask, CAM_CPAS_POLL_QH_RETRY_CNT,
		CAM_CPAS_POLL_MIN_USECS, CAM_CPAS_POLL_MAX_USECS);
	if (rc) {
		CAM_ERR(CAM_CPAS,
			"camnoc idle sequence failed, qstat 0x%x",
			cam_io_r(soc_info->reg_map[reg_indx].mem_base +
			qchannel_info->qchannel_status));
		/* Do not return error, passthrough */
		rc = 0;
	}

	/* check if deny bit is set */
	qchannel_status = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base +
				qchannel_info->qchannel_status);
	qdeny = (qchannel_status & BIT(1));
	if (!power_on && qdeny)
		rc = -EBUSY;

	return rc;
}

static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
	struct cam_cpas_hw_caps *hw_caps)
{
	int rc = 0;
	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
	qchannel_info = NULL;

	CAM_DBG(CAM_CPAS,
		"hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d",
@@ -864,18 +920,23 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
		break;
	case CAM_CPAS_TITAN_580_V100:
		camnoc_info = &cam580_cpas100_camnoc_info;
		qchannel_info = &cam580_cpas100_qchannel_info;
		break;
	case CAM_CPAS_TITAN_540_V100:
		camnoc_info = &cam540_cpas100_camnoc_info;
		qchannel_info = &cam540_cpas100_qchannel_info;
		break;
	case CAM_CPAS_TITAN_520_V100:
		camnoc_info = &cam520_cpas100_camnoc_info;
		qchannel_info = &cam520_cpas100_qchannel_info;
		break;
	case CAM_CPAS_TITAN_545_V100:
		camnoc_info = &cam545_cpas100_camnoc_info;
		qchannel_info = &cam545_cpas100_qchannel_info;
		break;
	case CAM_CPAS_TITAN_570_V200:
		camnoc_info = &cam570_cpas200_camnoc_info;
		qchannel_info = &cam570_cpas200_qchannel_info;
		break;
	case CAM_CPAS_TITAN_680_V100:
		camnoc_info = &cam680_cpas100_camnoc_info;
@@ -961,6 +1022,7 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops)
	internal_ops->setup_qos_settings = cam_cpastop_setup_qos_settings;
	internal_ops->print_poweron_settings =
		cam_cpastop_print_poweron_settings;
	internal_ops->qchannel_handshake = cam_cpastop_qchannel_handshake;

	return 0;
}
Loading