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

Commit c16dc6e8 authored by Venkat Chinta's avatar Venkat Chinta
Browse files

msm: camera: ife: Enable UBWC 4.0



This change adds uapi and bus driver support to enable
UBWC 4.0 on version 480 hardware. The change also adds
a generic, expandable internal structure to handle all
api versions of ubwc blob updates.

Change-Id: I021c3bf5444575e03f5760ff5e7c3966045e443f
Signed-off-by: default avatarJeyaprakash Soundrapandian <jsoundra@codeaurora.org>
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
Signed-off-by: default avatarVenkat Chinta <vchinta@codeaurora.org>
parent 79865e82
Loading
Loading
Loading
Loading
+179 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@
	(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)

#define CAM_ISP_GENERIC_BLOB_TYPE_MAX               \
	(CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG + 1)
	(CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2 + 1)

static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
	CAM_ISP_HW_CMD_GET_HFR_UPDATE,
@@ -45,6 +45,7 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
	CAM_ISP_HW_CMD_UBWC_UPDATE,
	CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
	CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG,
	CAM_ISP_HW_CMD_UBWC_UPDATE_V2,
};

static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -3238,6 +3239,172 @@ static int cam_isp_blob_ubwc_update(
	return rc;
}

static int cam_isp_get_generic_ubwc_data_v2(
	struct cam_ubwc_plane_cfg_v2       *ubwc_cfg,
	uint32_t                            version,
	struct cam_vfe_generic_ubwc_config *generic_ubwc_cfg)
{
	int i = 0;

	generic_ubwc_cfg->api_version = version;
	for (i = 0; i < CAM_PACKET_MAX_PLANES - 1; i++) {
		generic_ubwc_cfg->ubwc_plane_cfg[i].port_type             =
			ubwc_cfg[i].port_type;
		generic_ubwc_cfg->ubwc_plane_cfg[i].meta_stride           =
			ubwc_cfg[i].meta_stride;
		generic_ubwc_cfg->ubwc_plane_cfg[i].meta_size             =
			ubwc_cfg[i].meta_size;
		generic_ubwc_cfg->ubwc_plane_cfg[i].meta_offset           =
			ubwc_cfg[i].meta_offset;
		generic_ubwc_cfg->ubwc_plane_cfg[i].packer_config         =
			ubwc_cfg[i].packer_config;
		generic_ubwc_cfg->ubwc_plane_cfg[i].mode_config_0         =
			ubwc_cfg[i].mode_config_0;
		generic_ubwc_cfg->ubwc_plane_cfg[i].mode_config_1         =
			ubwc_cfg[i].mode_config_1;
		generic_ubwc_cfg->ubwc_plane_cfg[i].tile_config           =
			ubwc_cfg[i].tile_config;
		generic_ubwc_cfg->ubwc_plane_cfg[i].h_init                =
			ubwc_cfg[i].h_init;
		generic_ubwc_cfg->ubwc_plane_cfg[i].v_init                =
			ubwc_cfg[i].v_init;
		generic_ubwc_cfg->ubwc_plane_cfg[i].static_ctrl           =
			ubwc_cfg[i].static_ctrl;
		generic_ubwc_cfg->ubwc_plane_cfg[i].ctrl_2                =
			ubwc_cfg[i].ctrl_2;
		generic_ubwc_cfg->ubwc_plane_cfg[i].stats_ctrl_2          =
			ubwc_cfg[i].stats_ctrl_2;
		generic_ubwc_cfg->ubwc_plane_cfg[i].lossy_threshold_0     =
			ubwc_cfg[i].lossy_threshold_0;
		generic_ubwc_cfg->ubwc_plane_cfg[i].lossy_threshold_1     =
			ubwc_cfg[i].lossy_threshold_1;
		generic_ubwc_cfg->ubwc_plane_cfg[i].lossy_var_offset =
			ubwc_cfg[i].lossy_var_offset;
		generic_ubwc_cfg->ubwc_plane_cfg[i].bandwidth_limit       =
			ubwc_cfg[i].bandwidth_limit;
	}

	return 0;
}

static int cam_isp_blob_ubwc_update_v2(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
	struct cam_ubwc_config_v2             *ubwc_config,
	struct cam_hw_prepare_update_args     *prepare)
{
	struct cam_ubwc_plane_cfg_v2          *ubwc_plane_cfg;
	struct cam_kmd_buf_info               *kmd_buf_info;
	struct cam_ife_hw_mgr_ctx             *ctx = NULL;
	struct cam_ife_hw_mgr_res             *hw_mgr_res;
	uint32_t                               res_id_out, i;
	uint32_t                               total_used_bytes = 0;
	uint32_t                               kmd_buf_remain_size;
	uint32_t                              *cmd_buf_addr;
	uint32_t                               bytes_used = 0;
	int                                    num_ent, rc = 0;
	struct cam_vfe_generic_ubwc_config     generic_ubwc_cfg;

	ctx = prepare->ctxt_to_hw_map;
	if (!ctx) {
		CAM_ERR(CAM_ISP, "Invalid ctx");
		rc = -EINVAL;
		goto end;
	}

	if (prepare->num_hw_update_entries + 1 >=
		prepare->max_hw_update_entries) {
		CAM_ERR(CAM_ISP, "Insufficient HW entries :%d max:%d",
			prepare->num_hw_update_entries,
			prepare->max_hw_update_entries);
		rc = -EINVAL;
		goto end;
	}

	CAM_DBG(CAM_ISP, "num_ports= %d", ubwc_config->num_ports);

	kmd_buf_info = blob_info->kmd_buf_info;
	for (i = 0; i < ubwc_config->num_ports; i++) {
		ubwc_plane_cfg = &ubwc_config->ubwc_plane_cfg[i][0];
		res_id_out = ubwc_plane_cfg->port_type & 0xFF;

		CAM_DBG(CAM_ISP, "UBWC config idx %d, port_type=%d", i,
			ubwc_plane_cfg->port_type);

		if (res_id_out >= CAM_IFE_HW_OUT_RES_MAX) {
			CAM_ERR(CAM_ISP, "Invalid port type:%x",
				ubwc_plane_cfg->port_type);
			rc = -EINVAL;
			goto end;
		}

		if ((kmd_buf_info->used_bytes
			+ total_used_bytes) < kmd_buf_info->size) {
			kmd_buf_remain_size = kmd_buf_info->size -
				(kmd_buf_info->used_bytes
				+ total_used_bytes);
		} else {
			CAM_ERR(CAM_ISP,
				"no free kmd memory for base=%d bytes_used=%u buf_size=%u",
				blob_info->base_info->idx, bytes_used,
				kmd_buf_info->size);
			rc = -ENOMEM;
			goto end;
		}

		cmd_buf_addr = kmd_buf_info->cpu_addr +
			kmd_buf_info->used_bytes/4 +
			total_used_bytes/4;
		hw_mgr_res = &ctx->res_list_ife_out[res_id_out];

		if (!hw_mgr_res) {
			CAM_ERR(CAM_ISP, "Invalid hw_mgr_res");
			rc = -EINVAL;
			goto end;
		}

		rc = cam_isp_get_generic_ubwc_data_v2(ubwc_plane_cfg,
			ubwc_config->api_version, &generic_ubwc_cfg);

		rc = cam_isp_add_cmd_buf_update(
			hw_mgr_res, blob_type,
			blob_type_hw_cmd_map[blob_type],
			blob_info->base_info->idx,
			(void *)cmd_buf_addr,
			kmd_buf_remain_size,
			(void *)&generic_ubwc_cfg,
			&bytes_used);
		if (rc < 0) {
			CAM_ERR(CAM_ISP,
				"Failed cmd_update, base_idx=%d, bytes_used=%u, res_id_out=0x%x",
				blob_info->base_info->idx,
				bytes_used,
				res_id_out);
			goto end;
		}

		total_used_bytes += bytes_used;
	}

	if (total_used_bytes) {
		/* Update the HW entries */
		num_ent = prepare->num_hw_update_entries;
		prepare->hw_update_entries[num_ent].handle =
			kmd_buf_info->handle;
		prepare->hw_update_entries[num_ent].len =
			total_used_bytes;
		prepare->hw_update_entries[num_ent].offset =
			kmd_buf_info->offset;
		num_ent++;

		kmd_buf_info->used_bytes += total_used_bytes;
		kmd_buf_info->offset     += total_used_bytes;
		prepare->num_hw_update_entries = num_ent;
	}
end:
	return rc;
}

static int cam_isp_blob_hfr_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
@@ -3570,6 +3737,17 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
			CAM_ERR(CAM_ISP, "UBWC Update Failed rc: %d", rc);
	}
		break;

	case CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG_V2: {
		struct cam_ubwc_config_v2 *ubwc_config =
			(struct cam_ubwc_config_v2 *)blob_data;

		rc = cam_isp_blob_ubwc_update_v2(blob_type, blob_info,
			ubwc_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "UBWC Update Failed rc: %d", rc);
	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG: {
		struct cam_isp_csid_clock_config    *clock_config =
			(struct cam_isp_csid_clock_config *)blob_data;
+3 −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.
 */

#ifndef _CAM_ISP_HW_H_
@@ -97,6 +97,7 @@ enum cam_isp_hw_cmd_type {
	CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE,
	CAM_ISP_HW_CMD_FE_UPDATE_IN_RD,
	CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD,
	CAM_ISP_HW_CMD_UBWC_UPDATE_V2,
	CAM_ISP_HW_CMD_MAX,
};

@@ -206,6 +207,7 @@ struct cam_isp_hw_get_cmd_update {
		struct cam_isp_bw_config             *bw_update;
		struct cam_ubwc_plane_cfg_v1         *ubwc_update;
		struct cam_fe_config                 *fe_update;
		struct cam_vfe_generic_ubwc_config   *ubwc_config;
	};
};

+52 −0
Original line number Diff line number Diff line
@@ -299,6 +299,58 @@ struct cam_vfe_irq_handler_priv {
	uint32_t                     hw_version;
};

/**
 * struct cam_ubwc_generic_plane_config - UBWC Plane configuration info
 *
 * @port_type:                  Port Type
 * @meta_stride:                UBWC metadata stride
 * @meta_size:                  UBWC metadata plane size
 * @meta_offset:                UBWC metadata offset
 * @packer_config:              UBWC packer config
 * @mode_config:                UBWC mode config
 * @static ctrl:                UBWC static ctrl
 * @ctrl_2:                     UBWC ctrl 2
 * @tile_config:                UBWC tile config
 * @h_init:                     UBWC horizontal initial coordinate in pixels
 * @v_init:                     UBWC vertical initial coordinate in lines
 * @stats_ctrl_2:               UBWC stats control
 * @lossy_threshold0            UBWC lossy threshold 0
 * @lossy_threshold1            UBWC lossy threshold 1
 * @lossy_var_offset            UBWC offset variance threshold
 * @bandwidth limit             UBWC bandwidth limit
 */
struct cam_vfe_generic_ubwc_plane_config {
	uint32_t                port_type;
	uint32_t                meta_stride;
	uint32_t                meta_size;
	uint32_t                meta_offset;
	uint32_t                packer_config;
	uint32_t                mode_config_0;
	uint32_t                mode_config_1;
	uint32_t                tile_config;
	uint32_t                h_init;
	uint32_t                v_init;
	uint32_t                static_ctrl;
	uint32_t                ctrl_2;
	uint32_t                stats_ctrl_2;
	uint32_t                lossy_threshold_0;
	uint32_t                lossy_threshold_1;
	uint32_t                lossy_var_offset;
	uint32_t                bandwidth_limit;
};

/**
 * struct cam_ubwc_generic_config - UBWC Configuration Payload
 *
 * @api_version:         UBWC config api version
 * @ubwc_plane_config:   Array of UBWC configurations per plane
 */
struct cam_vfe_generic_ubwc_config {
	uint32_t   api_version;
	struct cam_vfe_generic_ubwc_plane_config
		ubwc_plane_cfg[CAM_PACKET_MAX_PLANES - 1];
};

/*
 * cam_vfe_hw_init()
 *
+1 −0
Original line number Diff line number Diff line
@@ -801,6 +801,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
	case CAM_ISP_HW_CMD_STRIPE_UPDATE:
	case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ:
	case CAM_ISP_HW_CMD_UBWC_UPDATE:
	case CAM_ISP_HW_CMD_UBWC_UPDATE_V2:
		rc = core_info->vfe_bus->hw_ops.process_cmd(
			core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
			arg_size);
+43 −8
Original line number Diff line number Diff line
@@ -36,7 +36,14 @@ static bool cam_vfe_cpas_cb(uint32_t client_handle, void *userdata,

static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info)
{
	int rc = 0;
	int rc = 0, num_ubwc_cfg = 0, i = 0;
	struct device_node *of_node = NULL;
	struct platform_device *pdev = NULL;
	struct cam_vfe_soc_private *vfe_soc_private;

	pdev = soc_info->pdev;
	of_node = pdev->dev.of_node;
	vfe_soc_private = soc_info->soc_private;

	rc = cam_soc_util_get_dt_properties(soc_info);
	if (rc) {
@@ -44,6 +51,34 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info)
		return rc;
	}

	switch (soc_info->hw_version) {
	case CAM_CPAS_TITAN_480_V100:
		num_ubwc_cfg = of_property_count_u32_elems(of_node,
			"ubwc-static-cfg");

		if (num_ubwc_cfg < 0 || num_ubwc_cfg > UBWC_STATIC_CONFIG_MAX) {
			CAM_ERR(CAM_ISP, "wrong num_ubwc_cfg: %d",
				num_ubwc_cfg);
			rc = num_ubwc_cfg;
			goto end;
		}

		for (i = 0; i < num_ubwc_cfg; i++) {
			rc = of_property_read_u32_index(of_node,
				"ubwc-static-cfg", i,
				&vfe_soc_private->ubwc_static_ctrl[i]);
			if (rc < 0) {
				CAM_ERR(CAM_ISP,
					"unable to read ubwc static config");
				break;
			}
		}
		break;
	default:
		break;
	}

end:
	return rc;
}

@@ -89,6 +124,13 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
	}
	soc_info->soc_private = soc_private;

	rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version);
	if (rc) {
		CAM_ERR(CAM_ISP, "Error! Invalid cpas version rc=%d", rc);
		goto free_soc_private;
	}
	soc_info->hw_version = soc_private->cpas_version;

	rc = cam_vfe_get_dt_properties(soc_info);
	if (rc < 0) {
		CAM_ERR(CAM_ISP, "Error! Get DT properties failed rc=%d", rc);
@@ -116,13 +158,6 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
	cpas_register_param.cam_cpas_client_cb = cam_vfe_cpas_cb;
	cpas_register_param.userdata = soc_info;

	rc = cam_cpas_get_cpas_hw_version(&soc_private->cpas_version);
	if (rc) {
		CAM_ERR(CAM_ISP, "Error! Invalid cpas version rc=%d", rc);
		goto free_soc_private;
	}
	soc_info->hw_version = soc_private->cpas_version;

	switch (soc_private->cpas_version) {
	case CAM_CPAS_TITAN_175_V120:
		strlcpy(cpas_register_param.identifier, "iferdi",
Loading