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

Commit e5450be4 authored by Vishalsingh Hajeri's avatar Vishalsingh Hajeri Committed by Pavan Kumar Chilamkurthi
Browse files

msm: camera: ife: Handle per-frame bw config updates



Add support to handle per-frame bw updates from
umd, secondly when reducing bw compred to previous
request delay it by few frames so that we finish with
the current request which might need previous
high bw.

Change-Id: Ia209bcc64d2cd927021b6efebe6d7c12a8dfc23b
Signed-off-by: default avatarvhajeri <vhajeri@codeaurora.org>
Signed-off-by: default avatarPavan Kumar Chilamkurthi <pchilamk@codeaurora.org>
parent 57c62991
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -86,7 +86,8 @@ static int __cam_isp_ctx_enqueue_init_request(
		struct cam_ctx_request, list);
	req_isp_old = (struct cam_isp_ctx_req *) req_old->req_priv;
	req_isp_new = (struct cam_isp_ctx_req *) req->req_priv;
	if (req_isp_old->packet_opcode_type == CAM_ISP_PACKET_INIT_DEV) {
	if (req_isp_old->hw_update_data.packet_opcode_type ==
		CAM_ISP_PACKET_INIT_DEV) {
		if ((req_isp_old->num_cfg + req_isp_new->num_cfg) >=
			CAM_ISP_CTX_CFG_MAX) {
			CAM_WARN(CAM_ISP, "Can not merge INIT pkt");
@@ -1071,6 +1072,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
	cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
	cfg.hw_update_entries = req_isp->cfg;
	cfg.num_hw_update_entries = req_isp->num_cfg;
	cfg.priv  = &req_isp->hw_update_data;

	rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
	if (rc) {
@@ -1817,7 +1819,6 @@ static int __cam_isp_ctx_config_dev_in_top_state(
	struct cam_req_mgr_add_request    add_req;
	struct cam_isp_context           *ctx_isp =
		(struct cam_isp_context *) ctx->ctx_priv;
	struct cam_isp_prepare_hw_update_data    hw_update_data;

	CAM_DBG(CAM_ISP, "get free request object......");

@@ -1868,7 +1869,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
	cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX;
	cfg.out_map_entries = req_isp->fence_map_out;
	cfg.in_map_entries = req_isp->fence_map_in;
	cfg.priv  = &hw_update_data;
	cfg.priv  = &req_isp->hw_update_data;

	CAM_DBG(CAM_ISP, "try to prepare config packet......");

@@ -1883,7 +1884,6 @@ static int __cam_isp_ctx_config_dev_in_top_state(
	req_isp->num_fence_map_out = cfg.num_out_map_entries;
	req_isp->num_fence_map_in = cfg.num_in_map_entries;
	req_isp->num_acked = 0;
	req_isp->packet_opcode_type = hw_update_data.packet_opcode_type;

	CAM_DBG(CAM_ISP, "num_entry: %d, num fence out: %d, num fence in: %d",
		req_isp->num_cfg, req_isp->num_fence_map_out,
@@ -1893,9 +1893,11 @@ static int __cam_isp_ctx_config_dev_in_top_state(
	req->status = 1;

	CAM_DBG(CAM_ISP, "Packet request id 0x%llx packet opcode:%d",
		packet->header.request_id, req_isp->packet_opcode_type);
		packet->header.request_id,
		req_isp->hw_update_data.packet_opcode_type);

	if (req_isp->packet_opcode_type == CAM_ISP_PACKET_INIT_DEV) {
	if (req_isp->hw_update_data.packet_opcode_type ==
		CAM_ISP_PACKET_INIT_DEV) {
		if (ctx->state < CAM_CTX_ACTIVATED) {
			rc = __cam_isp_ctx_enqueue_init_request(ctx, req);
			if (rc)
@@ -2140,7 +2142,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
	struct cam_start_stop_dev_cmd *cmd)
{
	int rc = 0;
	struct cam_hw_start_args         arg;
	struct cam_hw_config_args        arg;
	struct cam_ctx_request          *req;
	struct cam_isp_ctx_req          *req_isp;
	struct cam_isp_context          *ctx_isp =
@@ -2168,9 +2170,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
		rc = -EFAULT;
		goto end;
	}

	arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
	arg.hw_update_entries = req_isp->cfg;
	arg.num_hw_update_entries = req_isp->num_cfg;
	arg.priv  = &req_isp->hw_update_data;

	ctx_isp->frame_id = 0;
	ctx_isp->active_req_cnt = 0;
+13 −13
Original line number Diff line number Diff line
@@ -82,8 +82,7 @@ struct cam_isp_ctx_irq_ops {
 *                         the request has been completed.
 * @bubble_report:         Flag to track if bubble report is active on
 *                         current request
 * @packet_opcode_type:    Request packet opcode type,
 *                         ie INIT packet or update packet
 * @hw_update_data:        HW update data for this request
 *
 */
struct cam_isp_ctx_req {
@@ -91,13 +90,14 @@ struct cam_isp_ctx_req {

	struct cam_hw_update_entry            cfg[CAM_ISP_CTX_CFG_MAX];
	uint32_t                              num_cfg;
	struct cam_hw_fence_map_entry    fence_map_out[CAM_ISP_CTX_RES_MAX];
	struct cam_hw_fence_map_entry         fence_map_out
						[CAM_ISP_CTX_RES_MAX];
	uint32_t                              num_fence_map_out;
	struct cam_hw_fence_map_entry         fence_map_in[CAM_ISP_CTX_RES_MAX];
	uint32_t                              num_fence_map_in;
	uint32_t                              num_acked;
	int32_t                               bubble_report;
	uint32_t                         packet_opcode_type;
	struct cam_isp_prepare_hw_update_data hw_update_data;
};

/**
+121 −94
Original line number Diff line number Diff line
@@ -1444,15 +1444,97 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv,
	return rc;
}

static int cam_isp_blob_bw_update(
	struct cam_isp_bw_config              *bw_config,
	struct cam_ife_hw_mgr_ctx             *ctx)
{
	struct cam_ife_hw_mgr_res             *hw_mgr_res;
	struct cam_hw_intf                    *hw_intf;
	struct cam_vfe_bw_update_args          bw_upd_args;
	uint64_t                               cam_bw_bps = 0;
	uint64_t                               ext_bw_bps = 0;
	int                                    rc = -EINVAL;
	uint32_t                               i;

	CAM_DBG(CAM_ISP,
		"usage=%u left cam_bw_bps=%llu ext_bw_bps=%llu\n"
		"right cam_bw_bps=%llu ext_bw_bps=%llu",
		bw_config->usage_type,
		bw_config->left_pix_vote.cam_bw_bps,
		bw_config->left_pix_vote.ext_bw_bps,
		bw_config->right_pix_vote.cam_bw_bps,
		bw_config->right_pix_vote.ext_bw_bps);

	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;

			if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
				if (i == CAM_ISP_HW_SPLIT_LEFT) {
					cam_bw_bps =
					bw_config->left_pix_vote.cam_bw_bps;
					ext_bw_bps =
					bw_config->left_pix_vote.ext_bw_bps;
				} else {
					cam_bw_bps =
					bw_config->right_pix_vote.cam_bw_bps;
					ext_bw_bps =
					bw_config->right_pix_vote.ext_bw_bps;
				}
			else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0)
						&& (hw_mgr_res->res_id <=
						CAM_ISP_HW_VFE_IN_RDI3)) {
				uint32_t idx = hw_mgr_res->res_id -
						CAM_ISP_HW_VFE_IN_RDI0;
				if (idx >= bw_config->num_rdi)
					continue;

				cam_bw_bps =
					bw_config->rdi_vote[idx].cam_bw_bps;
				ext_bw_bps =
					bw_config->rdi_vote[idx].ext_bw_bps;
			} else
				if (hw_mgr_res->hw_res[i]) {
					CAM_ERR(CAM_ISP, "Invalid res_id %u",
						hw_mgr_res->res_id);
					rc = -EINVAL;
					return rc;
				}

			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			if (hw_intf && hw_intf->hw_ops.process_cmd) {
				bw_upd_args.node_res =
					hw_mgr_res->hw_res[i];

				bw_upd_args.camnoc_bw_bytes = cam_bw_bps;
				bw_upd_args.external_bw_bytes = ext_bw_bps;

				rc = hw_intf->hw_ops.process_cmd(
					hw_intf->hw_priv,
					CAM_ISP_HW_CMD_BW_UPDATE,
					&bw_upd_args,
					sizeof(struct cam_vfe_bw_update_args));
				if (rc)
					CAM_ERR(CAM_ISP, "BW Update failed");
			} else
				CAM_WARN(CAM_ISP, "NULL hw_intf!");
		}
	}

	return rc;
}

/* entry function: config_hw */
static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
					void *config_hw_args)
{
	int rc = -1, i;
	struct cam_hw_start_args *cfg;
	struct cam_hw_config_args *cfg;
	struct cam_hw_update_entry *cmd;
	struct cam_cdm_bl_request *cdm_cmd;
	struct cam_ife_hw_mgr_ctx *ctx;
	struct cam_isp_prepare_hw_update_data *hw_update_data;

	CAM_DBG(CAM_ISP, "Enter");
	if (!hw_mgr_priv || !config_hw_args) {
@@ -1474,6 +1556,18 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
	if (atomic_read(&ctx->overflow_pending))
		return -EINVAL;

	hw_update_data = (struct cam_isp_prepare_hw_update_data  *) cfg->priv;

	for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
		if (hw_update_data->bw_config_valid[i] == true) {
			rc = cam_isp_blob_bw_update(
				(struct cam_isp_bw_config *)
				&hw_update_data->bw_config[i], ctx);
			if (rc)
				CAM_ERR(CAM_ISP, "Bandwidth Update Failed");
			}
	}

	CAM_DBG(CAM_ISP, "Enter ctx id:%d num_hw_upd_entries %d",
		ctx->ctx_index, cfg->num_hw_update_entries);

@@ -1805,7 +1899,7 @@ static int cam_ife_mgr_restart_hw(void *start_hw_args)
static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
{
	int                               rc = -1;
	struct cam_hw_start_args         *start_args = start_hw_args;
	struct cam_hw_config_args        *start_args = start_hw_args;
	struct cam_ife_hw_mgr_ctx        *ctx;
	struct cam_ife_hw_mgr_res        *hw_mgr_res;
	uint32_t                          i;
@@ -2211,92 +2305,6 @@ static int cam_isp_blob_clock_update(
	return rc;
}

static int cam_isp_blob_bw_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
	struct cam_isp_bw_config              *bw_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_vfe_bw_update_args          bw_upd_args;
	uint64_t                               cam_bw_bps = 0;
	uint64_t                               ext_bw_bps = 0;
	int                                    rc = -EINVAL;
	uint32_t                               i;

	ctx = prepare->ctxt_to_hw_map;

	CAM_DBG(CAM_ISP,
		"usage=%u left cam_bw_bps=%llu ext_bw_bps=%llu\n"
		"right cam_bw_bps=%llu ext_bw_bps=%llu",
		bw_config->usage_type,
		bw_config->left_pix_vote.cam_bw_bps,
		bw_config->left_pix_vote.ext_bw_bps,
		bw_config->right_pix_vote.cam_bw_bps,
		bw_config->right_pix_vote.ext_bw_bps);

	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;

			if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
				if (i == CAM_ISP_HW_SPLIT_LEFT) {
					cam_bw_bps =
					bw_config->left_pix_vote.cam_bw_bps;
					ext_bw_bps =
					bw_config->left_pix_vote.ext_bw_bps;
				} else {
					cam_bw_bps =
					bw_config->right_pix_vote.cam_bw_bps;
					ext_bw_bps =
					bw_config->right_pix_vote.ext_bw_bps;
				}
			else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0)
						&& (hw_mgr_res->res_id <=
						CAM_ISP_HW_VFE_IN_RDI3)) {
				uint32_t idx = hw_mgr_res->res_id -
						CAM_ISP_HW_VFE_IN_RDI0;
				if (idx >= bw_config->num_rdi)
					continue;

				cam_bw_bps =
					bw_config->rdi_vote[idx].cam_bw_bps;
				ext_bw_bps =
					bw_config->rdi_vote[idx].ext_bw_bps;
			} else
				if (hw_mgr_res->hw_res[i]) {
					CAM_ERR(CAM_ISP, "Invalid res_id %u",
						hw_mgr_res->res_id);
					rc = -EINVAL;
					return rc;
				}

			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			if (hw_intf && hw_intf->hw_ops.process_cmd) {
				bw_upd_args.node_res =
					hw_mgr_res->hw_res[i];

				bw_upd_args.camnoc_bw_bytes = cam_bw_bps;
				bw_upd_args.external_bw_bytes = ext_bw_bps;

				rc = hw_intf->hw_ops.process_cmd(
					hw_intf->hw_priv,
					CAM_ISP_HW_CMD_BW_UPDATE,
					&bw_upd_args,
					sizeof(struct cam_vfe_bw_update_args));
				if (rc)
					CAM_ERR(CAM_ISP, "BW Update failed");
			} else
				CAM_WARN(CAM_ISP, "NULL hw_intf!");
		}
	}

	return rc;
}

static int cam_isp_packet_generic_blob_handler(void *user_data,
	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{
@@ -2347,11 +2355,22 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
	case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
		struct cam_isp_bw_config    *bw_config =
			(struct cam_isp_bw_config *)blob_data;
		struct cam_isp_prepare_hw_update_data   *prepare_hw_data;

		if (!prepare || !prepare->priv ||
			(bw_config->usage_type >= CAM_IFE_HW_NUM_MAX)) {
			CAM_ERR(CAM_ISP, "Invalid inputs");
			rc = -EINVAL;
			break;
		}

		prepare_hw_data = (struct cam_isp_prepare_hw_update_data  *)
			prepare->priv;

		memcpy(&prepare_hw_data->bw_config[bw_config->usage_type],
			bw_config, sizeof(prepare_hw_data->bw_config[0]));
		prepare_hw_data->bw_config_valid[bw_config->usage_type] = true;

		rc = cam_isp_blob_bw_update(blob_type, blob_info,
			bw_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "Bandwidth Update Failed");
	}
		break;
	default:
@@ -2382,6 +2401,9 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,

	CAM_DBG(CAM_ISP, "enter");

	prepare_hw_data = (struct cam_isp_prepare_hw_update_data  *)
		prepare->priv;

	ctx = (struct cam_ife_hw_mgr_ctx *) prepare->ctxt_to_hw_map;
	hw_mgr = (struct cam_ife_hw_mgr *)hw_mgr_priv;

@@ -2406,6 +2428,13 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	prepare->num_in_map_entries = 0;
	prepare->num_out_map_entries = 0;

	memset(&prepare_hw_data->bw_config[0], 0x0,
		sizeof(prepare_hw_data->bw_config[0]) *
		CAM_IFE_HW_NUM_MAX);
	memset(&prepare_hw_data->bw_config_valid[0], 0x0,
		sizeof(prepare_hw_data->bw_config_valid[0]) *
		CAM_IFE_HW_NUM_MAX);

	for (i = 0; i < ctx->num_base; i++) {
		CAM_DBG(CAM_ISP, "process cmd buffer for device %d", i);

@@ -2459,8 +2488,6 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
	 * bits to get the type of operation since UMD definition
	 * of op_code has some difference from KMD.
	 */
	prepare_hw_data = (struct cam_isp_prepare_hw_update_data  *)
		prepare->priv;
	if (((prepare->packet->header.op_code + 1) & 0xF) ==
		CAM_ISP_PACKET_INIT_DEV) {
		prepare_hw_data->packet_opcode_type = CAM_ISP_PACKET_INIT_DEV;
+1 −4
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -18,9 +18,6 @@
#include "cam_ife_csid_hw_intf.h"
#include "cam_tasklet_util.h"

/* MAX IFE instance */
#define CAM_IFE_HW_NUM_MAX                       4

/* enum cam_ife_hw_mgr_res_type - manager resource node type */
enum cam_ife_hw_mgr_res_type {
	CAM_IFE_HW_MGR_RES_UNINIT,
+30 −3
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@
#include <uapi/media/cam_isp.h>
#include "cam_hw_mgr_intf.h"

/* MAX IFE instance */
#define CAM_IFE_HW_NUM_MAX   4
#define CAM_IFE_RDI_NUM_MAX  4

/**
 *  enum cam_isp_hw_event_type - Collection of the ISP hardware events
 */
@@ -46,16 +50,39 @@ enum cam_isp_hw_err_type {
	CAM_ISP_HW_ERROR_MAX,
};

/**
 * struct cam_isp_bw_config_internal - Internal Bandwidth configuration
 *
 * @usage_type:                 Usage type (Single/Dual)
 * @num_rdi:                    Number of RDI votes
 * @left_pix_vote:              Bandwidth vote for left ISP
 * @right_pix_vote:             Bandwidth vote for right ISP
 * @rdi_vote:                   RDI bandwidth requirements
 */

struct cam_isp_bw_config_internal {
	uint32_t                       usage_type;
	uint32_t                       num_rdi;
	struct cam_isp_bw_vote         left_pix_vote;
	struct cam_isp_bw_vote         right_pix_vote;
	struct cam_isp_bw_vote         rdi_vote[CAM_IFE_RDI_NUM_MAX];
};

/**
 * struct cam_isp_prepare_hw_update_data - hw prepare data
 *
 * @packet_opcode_type:     Packet header opcode in the packet header
 *                          this opcode defines, packet is init packet or
 *                          update packet
 * @bw_config:              BW config information
 * @bw_config_valid:        Flag indicating whether the bw_config at the index
 *                          is valid or not
 *
 */
struct cam_isp_prepare_hw_update_data {
	uint32_t                          packet_opcode_type;
	struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX];
	bool                              bw_config_valid[CAM_IFE_HW_NUM_MAX];
};


Loading