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

Commit a56cd66b authored by Mukund Madhusudan Atre's avatar Mukund Madhusudan Atre Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: Add new bw voting logic for cpas and its clients



Adding new logic for bandwidth voting in client drivers by
classifying and comparing bw vote updates. Also, adding logic
to update bw vote and camnoc axi clock frequency as per camnoc
hw block by representing bus paths inside camnoc hw as tree
graph in DT. Overall voting includes traversing through the
tree and calculating consolidated votes to finally determine
appropriate camnoc axi clock frequency and mnoc bw vote.

Change-Id: Iea07973ca6d38cce4190d601eca7909e601b6924
Signed-off-by: default avatarMukund Madhusudan Atre <matre@codeaurora.org>
parent 4c13fa38
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -271,12 +271,21 @@ int cam_cdm_stream_ops_internal(void *hw_priv,
	if (operation == true) {
		if (!cdm_hw->open_count) {
			struct cam_ahb_vote ahb_vote;
			struct cam_axi_vote axi_vote;
			struct cam_axi_vote axi_vote = {0};

			ahb_vote.type = CAM_VOTE_ABSOLUTE;
			ahb_vote.vote.level = CAM_SVS_VOTE;
			axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
			axi_vote.uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
			axi_vote.num_paths = 1;
			axi_vote.axi_path[0].path_data_type =
				CAM_AXI_PATH_DATA_ALL;
			axi_vote.axi_path[0].transac_type =
				CAM_AXI_TRANSACTION_READ;
			axi_vote.axi_path[0].camnoc_bw =
				CAM_CPAS_DEFAULT_AXI_BW;
			axi_vote.axi_path[0].mnoc_ab_bw =
				CAM_CPAS_DEFAULT_AXI_BW;
			axi_vote.axi_path[0].mnoc_ib_bw =
				CAM_CPAS_DEFAULT_AXI_BW;

			rc = cam_cpas_start(core->cpas_handle,
				&ahb_vote, &axi_vote);
+8 −3
Original line number Diff line number Diff line
@@ -826,7 +826,7 @@ int cam_hw_cdm_probe(struct platform_device *pdev)
	struct cam_cdm_private_dt_data *soc_private = NULL;
	struct cam_cpas_register_params cpas_parms;
	struct cam_ahb_vote ahb_vote;
	struct cam_axi_vote axi_vote;
	struct cam_axi_vote axi_vote = {0};

	cdm_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
	if (!cdm_hw_intf)
@@ -932,8 +932,13 @@ int cam_hw_cdm_probe(struct platform_device *pdev)

	ahb_vote.type = CAM_VOTE_ABSOLUTE;
	ahb_vote.vote.level = CAM_SVS_VOTE;
	axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
	axi_vote.uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
	axi_vote.num_paths = 1;
	axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL;
	axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_READ;
	axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
	axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
	axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW;

	rc = cam_cpas_start(cdm_core->cpas_handle, &ahb_vote, &axi_vote);
	if (rc) {
		CAM_ERR(CAM_CDM, "CPAS start failed");
+465 −319

File changed.

Preview size limit exceeded, changes collapsed.

+33 −24
Original line number Diff line number Diff line
@@ -6,12 +6,18 @@
#ifndef _CAM_CPAS_HW_H_
#define _CAM_CPAS_HW_H_

#include <dt-bindings/msm/msm-camera.h>
#include "cam_cpas_api.h"
#include "cam_cpas_hw_intf.h"
#include "cam_common_util.h"

#define CAM_CPAS_MAX_CLIENTS 40
#define CAM_CPAS_INFLIGHT_WORKS              5
#define CAM_CPAS_MAX_CLIENTS                 40
#define CAM_CPAS_MAX_AXI_PORTS               6
#define CAM_CPAS_MAX_TREE_LEVELS             4
#define CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT   32
#define CAM_CPAS_PATH_DATA_MAX               38
#define CAM_CPAS_TRANSACTION_MAX             2

#define CAM_CPAS_AXI_MIN_MNOC_AB_BW   (2048 * 1024)
#define CAM_CPAS_AXI_MIN_MNOC_IB_BW   (2048 * 1024)
@@ -25,7 +31,7 @@
	((indx >= 0) && (indx < CAM_CPAS_MAX_CLIENTS))
#define CAM_CPAS_CLIENT_REGISTERED(cpas_core, indx)        \
	((CAM_CPAS_CLIENT_VALID(indx)) && \
	(cpas_core->cpas_client[indx]))
	(cpas_core->cpas_client[indx]->registered))
#define CAM_CPAS_CLIENT_STARTED(cpas_core, indx)          \
	((CAM_CPAS_CLIENT_REGISTERED(cpas_core, indx)) && \
	(cpas_core->cpas_client[indx]->started))
@@ -87,20 +93,25 @@ struct cam_cpas_reg {
 * struct cam_cpas_client : CPAS Client structure info
 *
 * @data: Client register params
 * @registered: Whether client has registered with cpas
 * @started: Whether client has streamed on
 * @tree_node_valid: Indicates whether tree node has at least one valid node
 * @ahb_level: Determined/Applied ahb level for the client
 * @axi_vote: Determined/Applied axi vote for the client
 * @axi_port: Client's parent axi port
 * @axi_sibling_client: Client's sibllings sharing the same axi port
 * @tree_node: All granular path voting nodes for the client
 *
 */
struct cam_cpas_client {
	struct cam_cpas_register_params data;
	bool registered;
	bool started;
	bool tree_node_valid;
	enum cam_vote_level ahb_level;
	struct cam_axi_vote axi_vote;
	struct cam_cpas_axi_port *axi_port;
	struct list_head axi_sibling_client;
	struct cam_cpas_tree_node *tree_node[CAM_CPAS_PATH_DATA_MAX]
		[CAM_CPAS_TRANSACTION_MAX];
};

/**
@@ -136,30 +147,24 @@ struct cam_cpas_bus_client {
/**
 * struct cam_cpas_axi_port : AXI port information
 *
 * @sibling_port: Sibling AXI ports
 * @clients_list_head: List head pointing to list of clients sharing this port
 * @lock: Mutex lock for accessing this port
 * @camnoc_bus: CAMNOC bus client info for this port
 * @mnoc_bus: MNOC bus client info for this port
 * @axi_port_name: Name of this AXI port
 * @lock: Mutex lock for accessing this port
 * @bus_client: bus client info for this port
 * @ib_bw_voting_needed: if this port can update ib bw dynamically
 * @axi_port_node: Node representing this AXI Port
 * @axi_port_mnoc_node: Node representing mnoc in this AXI Port
 * @axi_port_camnoc_node: Node representing camnoc in this AXI Port
 * @consolidated_axi_vote: Consolidated axi bw values for this AXI port
 * @axi_port_node: Node representing AXI Port info in device tree
 * @ab_bw: AB bw value for this port
 * @ib_bw: IB bw value for this port
 * @additional_bw: Additional bandwidth to cover non-hw cpas clients
 */
struct cam_cpas_axi_port {
	struct list_head sibling_port;
	struct list_head clients_list_head;
	struct mutex lock;
	struct cam_cpas_bus_client camnoc_bus;
	struct cam_cpas_bus_client mnoc_bus;
	const char *axi_port_name;
	struct mutex lock;
	struct cam_cpas_bus_client bus_client;
	bool ib_bw_voting_needed;
	struct device_node *axi_port_node;
	struct device_node *axi_port_mnoc_node;
	struct device_node *axi_port_camnoc_node;
	struct cam_axi_vote consolidated_axi_vote;
	uint64_t ab_bw;
	uint64_t ib_bw;
	uint64_t additional_bw;
};

/**
@@ -169,11 +174,12 @@ struct cam_cpas_axi_port {
 * @cpas_client: Array of pointers to CPAS clients info
 * @client_mutex: Mutex for accessing client info
 * @num_clients: Total number of clients that CPAS supports
 * @num_axi_ports: Total number of axi ports found in device tree
 * @registered_clients: Number of Clients registered currently
 * @streamon_clients: Number of Clients that are in start state currently
 * @regbase_index: Register base indices for CPAS register base IDs
 * @ahb_bus_client: AHB Bus client info
 * @axi_ports_list_head: Head pointing to list of AXI ports
 * @axi_port: AXI port info for a specific axi index
 * @internal_ops: CPAS HW internal ops
 * @work_queue: Work queue handle
 *
@@ -183,11 +189,12 @@ struct cam_cpas {
	struct cam_cpas_client *cpas_client[CAM_CPAS_MAX_CLIENTS];
	struct mutex client_mutex[CAM_CPAS_MAX_CLIENTS];
	uint32_t num_clients;
	uint32_t num_axi_ports;
	uint32_t registered_clients;
	uint32_t streamon_clients;
	int32_t regbase_index[CAM_CPAS_REG_MAX];
	struct cam_cpas_bus_client ahb_bus_client;
	struct list_head axi_ports_list_head;
	struct cam_cpas_axi_port axi_port[CAM_CPAS_MAX_AXI_PORTS];
	struct cam_cpas_internal_ops internal_ops;
	struct workqueue_struct *work_queue;
	atomic_t irq_count;
@@ -200,4 +207,6 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops);
int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
	enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info);

int cam_cpas_util_client_cleanup(struct cam_hw_info *cpas_hw);

#endif /* _CAM_CPAS_HW_H_ */
+72 −2
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/of.h>
@@ -43,6 +43,67 @@ struct cam_cpas_intf {

static struct cam_cpas_intf *g_cpas_intf;

const char *cam_cpas_axi_util_path_type_to_string(
	uint32_t path_data_type)
{
	switch (path_data_type) {
	/* IFE Paths */
	case CAM_AXI_PATH_DATA_IFE_LINEAR:
		return "IFE_LINEAR";
	case CAM_AXI_PATH_DATA_IFE_VID:
		return "IFE_VID";
	case CAM_AXI_PATH_DATA_IFE_DISP:
		return "IFE_DISP";
	case CAM_AXI_PATH_DATA_IFE_STATS:
		return "IFE_STATS";
	case CAM_AXI_PATH_DATA_IFE_RDI0:
		return "IFE_RDI0";
	case CAM_AXI_PATH_DATA_IFE_RDI1:
		return "IFE_RDI1";
	case CAM_AXI_PATH_DATA_IFE_RDI2:
		return "IFE_RDI2";
	case CAM_AXI_PATH_DATA_IFE_RDI3:
		return "IFE_RDI3";
	case CAM_AXI_PATH_DATA_IFE_PDAF:
		return "IFE_PDAF";
	case CAM_AXI_PATH_DATA_IFE_PIXEL_RAW:
		return "IFE_PIXEL_RAW";

	/* IPE Paths */
	case CAM_AXI_PATH_DATA_IPE_RD_IN:
		return "IPE_RD_IN";
	case CAM_AXI_PATH_DATA_IPE_RD_REF:
		return "IPE_RD_REF";
	case CAM_AXI_PATH_DATA_IPE_WR_VID:
		return "IPE_WR_VID";
	case CAM_AXI_PATH_DATA_IPE_WR_DISP:
		return "IPE_WR_DISP";
	case CAM_AXI_PATH_DATA_IPE_WR_REF:
		return "IPE_WR_REF";

	/* Common Paths */
	case CAM_AXI_PATH_DATA_ALL:
		return "DATA_ALL";
	default:
		return "IFE_PATH_INVALID";
	}
}
EXPORT_SYMBOL(cam_cpas_axi_util_path_type_to_string);

const char *cam_cpas_axi_util_trans_type_to_string(
	uint32_t transac_type)
{
	switch (transac_type) {
	case CAM_AXI_TRANSACTION_READ:
		return "TRANSAC_READ";
	case CAM_AXI_TRANSACTION_WRITE:
		return "TRANSAC_WRITE";
	default:
		return "TRANSAC_INVALID";
	}
}
EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string);

int cam_cpas_get_cpas_hw_version(uint32_t *hw_version)
{
	struct cam_hw_info *cpas_hw = NULL;
@@ -69,7 +130,6 @@ int cam_cpas_get_cpas_hw_version(uint32_t *hw_version)
	return 0;
}


int cam_cpas_get_hw_info(uint32_t *camera_family,
	struct cam_hw_version *camera_version,
	struct cam_hw_version *cpas_version,
@@ -184,6 +244,11 @@ int cam_cpas_update_axi_vote(uint32_t client_handle,
		return -ENODEV;
	}

	if (!axi_vote) {
		CAM_ERR(CAM_CPAS, "NULL axi vote");
		return -EINVAL;
	}

	if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
		struct cam_cpas_hw_cmd_axi_vote cmd_axi_vote;

@@ -274,6 +339,11 @@ int cam_cpas_start(uint32_t client_handle,
		return -ENODEV;
	}

	if (!axi_vote) {
		CAM_ERR(CAM_CPAS, "NULL axi vote");
		return -EINVAL;
	}

	if (g_cpas_intf->hw_intf->hw_ops.start) {
		struct cam_cpas_hw_cmd_start cmd_hw_start;

Loading