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

Commit 25eb8adb authored by Tejas Prajapati's avatar Tejas Prajapati Committed by Trishansh Bhardwaj
Browse files

msm: camera: isp: Add support for QCFA CSID binning



Add support to configure CSID binning for QCFA.

Change-Id: I9e2673d89f521a4b4fddc41ad1217ffe229d8b01
Signed-off-by: default avatarTejas Prajapati <tpraja@codeaurora.org>
Signed-off-by: default avatarTrishansh Bhardwaj <tbhardwa@codeaurora.org>
parent a3491d28
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -12,9 +12,11 @@
#include <media/v4l2-subdev.h>
#include <media/cam_cpas.h>
#include <media/cam_req_mgr.h>
#include <dt-bindings/msm/msm-camera.h>

#include "cam_subdev.h"
#include "cam_cpas_hw_intf.h"
#include "cam_cpas_soc.h"

#define CAM_CPAS_DEV_NAME    "cam-cpas"
#define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done)
@@ -104,6 +106,31 @@ const char *cam_cpas_axi_util_trans_type_to_string(
}
EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string);

int cam_cpas_is_feature_supported(uint32_t flag)
{
	struct cam_hw_info *cpas_hw = NULL;
	struct cam_cpas_private_soc *soc_private = NULL;
	uint32_t feature_mask;

	if (!CAM_CPAS_INTF_INITIALIZED()) {
		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
		return -ENODEV;
	}

	cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
	soc_private =
		(struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
	feature_mask = soc_private->feature_mask;

	if (flag >= CAM_CPAS_FUSE_FEATURE_MAX) {
		CAM_ERR(CAM_CPAS, "Unknown feature flag %x", flag);
		return -EINVAL;
	}

	return feature_mask & flag ? 1 : 0;
}
EXPORT_SYMBOL(cam_cpas_is_feature_supported);

int cam_cpas_get_cpas_hw_version(uint32_t *hw_version)
{
	struct cam_hw_info *cpas_hw = NULL;
+42 −0
Original line number Diff line number Diff line
@@ -349,6 +349,45 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
	return 0;
}


int cam_cpas_get_hw_features(struct platform_device *pdev,
	struct cam_cpas_private_soc *soc_private)
{
	struct device_node *of_node;
	void *fuse;
	uint32_t fuse_addr, fuse_bit;
	uint32_t fuse_val = 0, feature_bit_pos;
	int count = 0, i = 0;

	of_node = pdev->dev.of_node;
	count = of_property_count_u32_elems(of_node, "cam_hw_fuse");

	for (i = 0; (i + 3) <= count; i = i + 3) {
		of_property_read_u32_index(of_node, "cam_hw_fuse", i,
				&feature_bit_pos);
		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1,
				&fuse_addr);
		of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2,
				&fuse_bit);
		CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d",
				feature_bit_pos, fuse_addr, fuse_bit);

		fuse = ioremap(fuse_addr, 4);
		if (fuse) {
			fuse_val = cam_io_r(fuse);
			if (fuse_val & BIT(fuse_bit))
				soc_private->feature_mask |= feature_bit_pos;
			else
				soc_private->feature_mask &= ~feature_bit_pos;
		}
		CAM_INFO(CAM_CPAS, "fuse %pK, fuse_val %x, feature_mask %x",
				fuse, fuse_val, soc_private->feature_mask);

	}

	return 0;
}

int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
	struct platform_device *pdev, struct cam_cpas_private_soc *soc_private)
{
@@ -363,6 +402,7 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
	}

	of_node = pdev->dev.of_node;
	soc_private->feature_mask = 0xFFFFFFFF;

	rc = of_property_read_string(of_node, "arch-compat",
		&soc_private->arch_compat);
@@ -372,6 +412,8 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
		return rc;
	}

	cam_cpas_get_hw_features(pdev, soc_private);

	soc_private->camnoc_axi_min_ib_bw = 0;
	rc = of_property_read_u64(of_node,
		"camnoc-axi-min-ib-bw",
+2 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ struct cam_cpas_tree_node {
 * @camnoc_axi_clk_bw_margin : BW Margin in percentage to add while calculating
 *      camnoc axi clock
 * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target
 * @feature_mask: feature mask value for hw supported features
 *
 */
struct cam_cpas_private_soc {
@@ -103,6 +104,7 @@ struct cam_cpas_private_soc {
	uint32_t camnoc_bus_width;
	uint32_t camnoc_axi_clk_bw_margin;
	uint64_t camnoc_axi_min_ib_bw;
	uint32_t feature_mask;
};

void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);
+13 −0
Original line number Diff line number Diff line
@@ -525,6 +525,19 @@ int cam_cpas_get_hw_info(
int cam_cpas_get_cpas_hw_version(
	uint32_t				 *hw_version);

/**
 * cam_cpas_is_feature_supported()
 *
 * @brief: API to get camera features
 *
 * @flag  : Camera hw features to check
 *
 * @return 1 if feature is supported
 *
 */
int cam_cpas_is_feature_supported(
	uint32_t flag);

/**
 * cam_cpas_axi_util_path_type_to_string()
 *
+68 −0
Original line number Diff line number Diff line
@@ -4234,6 +4234,54 @@ static int cam_isp_blob_csid_clock_update(
	return rc;
}

static int cam_isp_blob_csid_qcfa_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
	struct cam_isp_csid_qcfa_config       *qcfa_config,
	struct cam_hw_prepare_update_args     *prepare)
{
	struct cam_ife_hw_mgr_ctx             *ctx = NULL;
	struct cam_ife_hw_mgr_res             *hw_mgr_res;
	struct cam_hw_intf                    *hw_intf;
	struct cam_ife_csid_qcfa_update_args   csid_qcfa_upd_args;
	int                                    rc = -EINVAL;
	uint32_t                               i;

	ctx = prepare->ctxt_to_hw_map;

	CAM_DBG(CAM_ISP,
		"csid binning=%d", qcfa_config->csid_binning);

	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {

			if (!hw_mgr_res->hw_res[i] ||
				hw_mgr_res->res_id != CAM_IFE_PIX_PATH_RES_IPP)
				continue;

			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			if (hw_intf && hw_intf->hw_ops.process_cmd) {
				csid_qcfa_upd_args.qcfa_binning =
						qcfa_config->csid_binning;
				CAM_DBG(CAM_ISP, "i= %d QCFA binning=%d\n",
				i, csid_qcfa_upd_args.qcfa_binning);

				rc = hw_intf->hw_ops.process_cmd(
					hw_intf->hw_priv,
					CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED,
					&csid_qcfa_upd_args,
					sizeof(
					struct cam_ife_csid_qcfa_update_args));
				if (rc)
					CAM_ERR(CAM_ISP, "QCFA Update failed");
			} else
				CAM_ERR(CAM_ISP, "NULL hw_intf!");
		}
	}

	return rc;
}

static int cam_isp_blob_core_cfg_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
@@ -4846,6 +4894,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
			clock_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "Clock Update Failed");
	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG: {
		struct cam_isp_csid_qcfa_config *qcfa_config;

		if (blob_size < sizeof(struct cam_isp_csid_qcfa_config)) {
			CAM_ERR(CAM_ISP,
				"Invalid qcfa blob size %u expected %u",
				blob_size,
				sizeof(struct cam_isp_csid_qcfa_config));
			return -EINVAL;
		}

		qcfa_config = (struct cam_isp_csid_qcfa_config *)blob_data;

		rc = cam_isp_blob_csid_qcfa_update(blob_type, blob_info,
				qcfa_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "QCFA Update Failed rc: %d", rc);

	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: {
Loading