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

Commit 00314afe authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: isp: Add support to display additional stats via debugfs"

parents 403906a6 8325e80f
Loading
Loading
Loading
Loading
+234 −25
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/videodev2.h>
#include <linux/of_device.h>
#include <linux/qcom_iommu.h>
#include <linux/sched_clock.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
@@ -67,13 +68,16 @@ static const struct platform_device_id msm_vfe_dev_id[] = {
	{"msm_vfe32", (kernel_ulong_t) &vfe32_hw_info},
	{}
};
#define MAX_OVERFLOW_COUNTERS  16
#define OVERFLOW_LENGTH 512
#define OVERFLOW_BUFFER_LENGTH 32
#define MAX_OVERFLOW_COUNTERS  29
#define OVERFLOW_LENGTH 1024
#define OVERFLOW_BUFFER_LENGTH 64
static char stat_line[OVERFLOW_LENGTH];

static struct msm_isp_buf_mgr vfe_buf_mgr;
struct msm_isp_statistics stats;
static int msm_isp_enable_debugfs(struct msm_isp_statistics *stats);
struct msm_isp_ub_info ub_info;
static int msm_isp_enable_debugfs(struct vfe_device *vfe_dev,
				  struct msm_isp_bw_req_info *isp_req_hist);
static char *stats_str[MAX_OVERFLOW_COUNTERS] = {
	"imgmaster0_overflow_cnt",
	"imgmaster1_overflow_cnt",
@@ -91,7 +95,34 @@ static char *stats_str[MAX_OVERFLOW_COUNTERS] = {
	"ihist_overflow_cnt",
	"skinbhist_overflow_cnt",
	"bfscale_overflow_cnt",
	"ISP_VFE0_client_info.active",
	"ISP_VFE0_client_info.ab",
	"ISP_VFE0_client_info.ib",
	"ISP_VFE1_client_info.active",
	"ISP_VFE1_client_info.ab",
	"ISP_VFE1_client_info.ib",
	"ISP_CPP_client_info.active",
	"ISP_CPP_client_info.ab",
	"ISP_CPP_client_info.ib",
	"ISP_last_overflow.ab",
	"ISP_last_overflow.ib",
	"ISP_VFE_CLK_RATE",
	"ISP_CPP_CLK_RATE",
};

#define MAX_DEPTH_BW_REQ_HISTORY 25
#define MAX_BW_HISTORY_BUFF_LEN  6144
#define MAX_BW_HISTORY_LINE_BUFF_LEN 512

#define MAX_UB_INFO_BUFF_LEN  1024
#define MAX_UB_INFO_LINE_BUFF_LEN 256

static struct msm_isp_bw_req_info
		msm_isp_bw_request_history[MAX_DEPTH_BW_REQ_HISTORY];
static int msm_isp_bw_request_history_idx;
static char bw_request_history_buff[MAX_BW_HISTORY_BUFF_LEN];
static char ub_info_buffer[MAX_UB_INFO_BUFF_LEN];
static spinlock_t req_history_lock;
static int vfe_debugfs_statistics_open(struct inode *inode, struct file *file)
{
	file->private_data = inode->i_private;
@@ -102,51 +133,219 @@ static ssize_t vfe_debugfs_statistics_read(struct file *t_file, char *t_char,
	size_t t_size_t, loff_t *t_loff_t)
{
	int i;
	char name[OVERFLOW_LENGTH] = {0};
	int *ptr;
	uint64_t *ptr;
	char buffer[OVERFLOW_BUFFER_LENGTH] = {0};
	struct msm_isp_statistics  *stats = (struct msm_isp_statistics *)
	struct vfe_device *vfe_dev = (struct vfe_device *)
		t_file->private_data;
	ptr = (int *)(stats);
	struct msm_isp_statistics *stats = vfe_dev->stats;

	memset(stat_line, 0, sizeof(stat_line));
	msm_isp_util_get_bandwidth_stats(vfe_dev, stats);
	ptr = (uint64_t *)(stats);
	for (i = 0; i < MAX_OVERFLOW_COUNTERS; i++) {
		strlcat(name, stats_str[i], sizeof(name));
		strlcat(name, "     ", sizeof(name));
		snprintf(buffer, sizeof(buffer), "%d", ptr[i]);
		strlcat(name, buffer, sizeof(name));
		strlcat(name, "\r\n", sizeof(name));
		strlcat(stat_line, stats_str[i], sizeof(stat_line));
		strlcat(stat_line, "     ", sizeof(stat_line));
		snprintf(buffer, sizeof(buffer), "%llu", ptr[i]);
		strlcat(stat_line, buffer, sizeof(stat_line));
		strlcat(stat_line, "\r\n", sizeof(stat_line));
	}
	return simple_read_from_buffer(t_char, t_size_t,
		t_loff_t, name, strlen(name));
		t_loff_t, stat_line, strlen(stat_line));
}

static ssize_t vfe_debugfs_statistics_write(struct file *t_file,
	const char *t_char, size_t t_size_t, loff_t *t_loff_t)
{
	struct msm_isp_statistics *stats = (struct msm_isp_statistics *)
	struct vfe_device *vfe_dev = (struct vfe_device *)
		t_file->private_data;
	struct msm_isp_statistics *stats = vfe_dev->stats;
	memset(stats, 0, sizeof(struct msm_isp_statistics));

	return sizeof(struct msm_isp_statistics);
}

static int bw_history_open(struct inode *inode, struct file *file)
{
	file->private_data = inode->i_private;
	return 0;
}

static ssize_t bw_history_read(struct file *t_file, char *t_char,
	size_t t_size_t, loff_t *t_loff_t)
{
	int i;
	char *out_buffer = bw_request_history_buff;
	char line_buffer[MAX_BW_HISTORY_LINE_BUFF_LEN] = {0};
	struct msm_isp_bw_req_info *isp_req_hist =
		(struct msm_isp_bw_req_info *) t_file->private_data;

	memset(out_buffer, 0, MAX_BW_HISTORY_BUFF_LEN);

	snprintf(line_buffer, sizeof(line_buffer),
		"Bus bandwidth request history in chronological order:\n");
	strlcat(out_buffer, line_buffer, sizeof(bw_request_history_buff));

	snprintf(line_buffer, sizeof(line_buffer),
		"MSM_ISP_MIN_AB = %u, MSM_ISP_MIN_IB = %u\n\n",
		MSM_ISP_MIN_AB, MSM_ISP_MIN_IB);
	strlcat(out_buffer, line_buffer, sizeof(bw_request_history_buff));

	for (i = 0; i < MAX_DEPTH_BW_REQ_HISTORY; i++) {
		snprintf(line_buffer, sizeof(line_buffer),
		 "idx = %d, client = %u, timestamp = %llu, ab = %llu, ib = %llu\n"
		 "ISP0.active = %x, ISP0.ab = %llu, ISP0.ib = %llu\n"
		 "ISP1.active = %x, ISP1.ab = %llu, ISP1.ib = %llu\n"
		 "CPP.active = %x, CPP.ab = %llu, CPP.ib = %llu\n\n",
		 i, isp_req_hist[i].client, isp_req_hist[i].timestamp,
		 isp_req_hist[i].total_ab, isp_req_hist[i].total_ib,
		 isp_req_hist[i].client_info[0].active,
		 isp_req_hist[i].client_info[0].ab,
		 isp_req_hist[i].client_info[0].ib,
		 isp_req_hist[i].client_info[1].active,
		 isp_req_hist[i].client_info[1].ab,
		 isp_req_hist[i].client_info[1].ib,
		 isp_req_hist[i].client_info[2].active,
		 isp_req_hist[i].client_info[2].ab,
		 isp_req_hist[i].client_info[2].ib);
		strlcat(out_buffer, line_buffer,
		sizeof(bw_request_history_buff));
	}
	return simple_read_from_buffer(t_char, t_size_t,
		t_loff_t, out_buffer, strlen(out_buffer));
}

static ssize_t bw_history_write(struct file *t_file,
	const char *t_char, size_t t_size_t, loff_t *t_loff_t)
{
	struct msm_isp_bw_req_info *isp_req_hist =
		(struct msm_isp_bw_req_info *) t_file->private_data;

	memset(isp_req_hist, 0, sizeof(msm_isp_bw_request_history));
	msm_isp_bw_request_history_idx = 0;
	return sizeof(msm_isp_bw_request_history);
}

static int ub_info_open(struct inode *inode, struct file *file)
{
	file->private_data = inode->i_private;
	return 0;
}

static ssize_t ub_info_read(struct file *t_file, char *t_char,
	size_t t_size_t, loff_t *t_loff_t)
{
	int i;
	char *out_buffer = ub_info_buffer;
	char line_buffer[MAX_UB_INFO_LINE_BUFF_LEN] = {0};
	struct vfe_device *vfe_dev =
		(struct vfe_device *) t_file->private_data;
	struct msm_isp_ub_info *ub_info = vfe_dev->ub_info;

	memset(out_buffer, 0, MAX_UB_INFO_LINE_BUFF_LEN);
	snprintf(line_buffer, sizeof(line_buffer),
		"wm_ub_policy_type = %d\n"
		"num_wm = %d\n"
		"wm_ub = %d\n",
		ub_info->policy, ub_info->num_wm, ub_info->wm_ub);
	strlcat(out_buffer, line_buffer,
	    sizeof(ub_info_buffer));
	for (i = 0; i < ub_info->num_wm; i++) {
		snprintf(line_buffer, sizeof(line_buffer),
			"data[%d] = 0x%x, addr[%d] = 0x%llx\n",
			i, ub_info->data[i], i, ub_info->addr[i]);
		strlcat(out_buffer, line_buffer,
			sizeof(ub_info_buffer));
	}

	return simple_read_from_buffer(t_char, t_size_t,
		t_loff_t, out_buffer, strlen(out_buffer));
}

static ssize_t ub_info_write(struct file *t_file,
	const char *t_char, size_t t_size_t, loff_t *t_loff_t)
{
	struct vfe_device *vfe_dev =
		(struct vfe_device *) t_file->private_data;
	struct msm_isp_ub_info *ub_info = vfe_dev->ub_info;

	memset(ub_info, 0, sizeof(struct msm_isp_ub_info));

	return sizeof(struct msm_isp_ub_info);
}

static const struct file_operations vfe_debugfs_error = {
	.open = vfe_debugfs_statistics_open,
	.read = vfe_debugfs_statistics_read,
	.write = vfe_debugfs_statistics_write,
};

static int msm_isp_enable_debugfs(struct msm_isp_statistics *stats)
static const struct file_operations bw_history_ops = {
	.open = bw_history_open,
	.read = bw_history_read,
	.write = bw_history_write,
};

static const struct file_operations ub_info_ops = {
	.open = ub_info_open,
	.read = ub_info_read,
	.write = ub_info_write,
};

static int msm_isp_enable_debugfs(struct vfe_device *vfe_dev,
				  struct msm_isp_bw_req_info *isp_req_hist)
{
	struct dentry *debugfs_base;
	debugfs_base = debugfs_create_dir("msm_isp", NULL);
	char dirname[32] = {0};

	snprintf(dirname, sizeof(dirname), "msm_isp%d", vfe_dev->pdev->id);
	debugfs_base = debugfs_create_dir(dirname, NULL);
	if (!debugfs_base)
		return -ENOMEM;
	if (!debugfs_create_file("stats", S_IRUGO | S_IWUSR, debugfs_base,
		stats, &vfe_debugfs_error))
		vfe_dev, &vfe_debugfs_error))
		return -ENOMEM;

	if (!debugfs_create_file("bw_req_history", S_IRUGO | S_IWUSR,
		debugfs_base, isp_req_hist, &bw_history_ops))
		return -ENOMEM;

	if (!debugfs_create_file("ub_info", S_IRUGO | S_IWUSR,
		debugfs_base, vfe_dev, &ub_info_ops))
		return -ENOMEM;

	return 0;
}

void msm_isp_update_req_history(uint32_t client, uint64_t ab,
				 uint64_t ib,
				 struct msm_isp_bandwidth_info *client_info,
				 unsigned long long ts)
{
	int i;

	spin_lock(&req_history_lock);
	msm_isp_bw_request_history[msm_isp_bw_request_history_idx].client =
		client;
	msm_isp_bw_request_history[msm_isp_bw_request_history_idx].timestamp =
		ts;
	msm_isp_bw_request_history[msm_isp_bw_request_history_idx].total_ab =
		ab;
	msm_isp_bw_request_history[msm_isp_bw_request_history_idx].total_ib =
		ib;

	for (i = 0; i < MAX_ISP_CLIENT; i++) {
		msm_isp_bw_request_history[msm_isp_bw_request_history_idx].
			client_info[i].active = client_info[i].active;
		msm_isp_bw_request_history[msm_isp_bw_request_history_idx].
			client_info[i].ab = client_info[i].ab;
		msm_isp_bw_request_history[msm_isp_bw_request_history_idx].
			client_info[i].ib = client_info[i].ib;
	}

	msm_isp_bw_request_history_idx = (msm_isp_bw_request_history_idx + 1)
			 % MAX_DEPTH_BW_REQ_HISTORY;
	spin_unlock(&req_history_lock);
}

#ifdef CONFIG_COMPAT
struct msm_isp_event_data32 {
@@ -276,6 +475,13 @@ static int vfe_probe(struct platform_device *pdev)
		rc = -ENOMEM;
		goto probe_fail1;
	}

	vfe_dev->ub_info = kzalloc(sizeof(struct msm_isp_ub_info), GFP_KERNEL);
	if (!vfe_dev->ub_info) {
		pr_err("%s: no enough memory\n", __func__);
		rc = -ENOMEM;
		goto probe_fail2;
	}
	if (pdev->dev.of_node) {
		of_property_read_u32((&pdev->dev)->of_node,
			"cell-index", &pdev->id);
@@ -283,7 +489,7 @@ static int vfe_probe(struct platform_device *pdev)
		if (!match_dev) {
			pr_err("%s: No vfe hardware info\n", __func__);
			rc = -EINVAL;
			goto probe_fail2;
			goto probe_fail3;
		}
		vfe_dev->hw_info =
			(struct msm_vfe_hardware_info *) match_dev->data;
@@ -295,7 +501,7 @@ static int vfe_probe(struct platform_device *pdev)
	if (!vfe_dev->hw_info) {
		pr_err("%s: No vfe hardware info\n", __func__);
		rc = -EINVAL;
		goto probe_fail2;
		goto probe_fail3;
	}
	ISP_DBG("%s: device id = %d\n", __func__, pdev->id);

@@ -304,7 +510,7 @@ static int vfe_probe(struct platform_device *pdev)
	if (rc < 0) {
		pr_err("%s: failed to get platform resources\n", __func__);
		rc = -ENOMEM;
		goto probe_fail2;
		goto probe_fail3;
	}

	INIT_LIST_HEAD(&vfe_dev->tasklet_q);
@@ -325,6 +531,7 @@ static int vfe_probe(struct platform_device *pdev)
	mutex_init(&vfe_dev->core_mutex);
	spin_lock_init(&vfe_dev->tasklet_lock);
	spin_lock_init(&vfe_dev->shared_data_lock);
	spin_lock_init(&req_history_lock);
	media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
	vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
	vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
@@ -333,7 +540,7 @@ static int vfe_probe(struct platform_device *pdev)
	rc = msm_sd_register(&vfe_dev->subdev);
	if (rc != 0) {
		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
		goto probe_fail2;
		goto probe_fail3;
	}

	msm_isp_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner;
@@ -351,7 +558,7 @@ static int vfe_probe(struct platform_device *pdev)
	if (rc < 0) {
		pr_err("%s: Unable to create buffer manager\n", __func__);
		rc = -EINVAL;
		goto probe_fail2;
		goto probe_fail3;
	}
	/* create secure context banks*/
	if (vfe_dev->hw_info->num_iommu_secure_ctx) {
@@ -369,10 +576,10 @@ static int vfe_probe(struct platform_device *pdev)
			pr_err("%s: fail to create secure domain\n", __func__);
			msm_sd_unregister(&vfe_dev->subdev);
			rc = -EINVAL;
			goto probe_fail2;
			goto probe_fail3;
		}
	}
	msm_isp_enable_debugfs(vfe_dev->stats);
	msm_isp_enable_debugfs(vfe_dev, msm_isp_bw_request_history);
	vfe_dev->buf_mgr->ops->register_ctx(vfe_dev->buf_mgr,
		&vfe_dev->iommu_ctx[0], &vfe_dev->iommu_secure_ctx[0],
		vfe_dev->hw_info->num_iommu_ctx,
@@ -382,6 +589,8 @@ static int vfe_probe(struct platform_device *pdev)
	vfe_dev->vfe_open_cnt = 0;
	return rc;

probe_fail3:
	kfree(vfe_dev->ub_info);
probe_fail2:
	kfree(vfe_dev->stats);
probe_fail1:
+72 −17
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@
#define VFE_CLK_INFO_MAX 16
#define STATS_COMP_BIT_MASK 0xFF0000

#define MSM_ISP_MIN_AB 450000000
#define MSM_ISP_MIN_IB 900000000

struct vfe_device;
struct msm_vfe_axi_stream;
struct msm_vfe_stats_stream;
@@ -448,22 +451,70 @@ struct msm_vfe_error_info {
};

struct msm_isp_statistics {
	int32_t imagemaster0_overflow;
	int32_t imagemaster1_overflow;
	int32_t imagemaster2_overflow;
	int32_t imagemaster3_overflow;
	int32_t imagemaster4_overflow;
	int32_t imagemaster5_overflow;
	int32_t imagemaster6_overflow;
	int32_t be_overflow;
	int32_t bg_overflow;
	int32_t bf_overflow;
	int32_t awb_overflow;
	int32_t rs_overflow;
	int32_t cs_overflow;
	int32_t ihist_overflow;
	int32_t skinbhist_overflow;
	int32_t bfscale_overflow;
	int64_t imagemaster0_overflow;
	int64_t imagemaster1_overflow;
	int64_t imagemaster2_overflow;
	int64_t imagemaster3_overflow;
	int64_t imagemaster4_overflow;
	int64_t imagemaster5_overflow;
	int64_t imagemaster6_overflow;
	int64_t be_overflow;
	int64_t bg_overflow;
	int64_t bf_overflow;
	int64_t awb_overflow;
	int64_t rs_overflow;
	int64_t cs_overflow;
	int64_t ihist_overflow;
	int64_t skinbhist_overflow;
	int64_t bfscale_overflow;

	int64_t isp_vfe0_active;
	int64_t isp_vfe0_ab;
	int64_t isp_vfe0_ib;

	int64_t isp_vfe1_active;
	int64_t isp_vfe1_ab;
	int64_t isp_vfe1_ib;

	int64_t isp_cpp_active;
	int64_t isp_cpp_ab;
	int64_t isp_cpp_ib;

	int64_t last_overflow_ab;
	int64_t last_overflow_ib;

	int64_t vfe_clk_rate;
	int64_t cpp_clk_rate;
};

enum msm_isp_hw_client {
	ISP_VFE0,
	ISP_VFE1,
	ISP_CPP,
	MAX_ISP_CLIENT,
};

struct msm_isp_bandwidth_info {
	uint32_t active;
	uint64_t ab;
	uint64_t ib;
};

struct msm_isp_bw_req_info {
	uint32_t client;
	unsigned long long timestamp;
	uint64_t total_ab;
	uint64_t total_ib;
	struct msm_isp_bandwidth_info client_info[MAX_ISP_CLIENT];
};

#define MSM_ISP_MAX_WM 7
struct msm_isp_ub_info {
	enum msm_wm_ub_cfg_type policy;
	uint8_t num_wm;
	uint32_t wm_ub;
	uint32_t data[MSM_ISP_MAX_WM];
	uint64_t addr[MSM_ISP_MAX_WM];
};

struct msm_vfe_hw_init_parms {
@@ -522,6 +573,10 @@ struct vfe_device {
	uint8_t ignore_error;
	struct msm_isp_statistics *stats;
	struct msm_vfe_fetch_engine_info fetch_engine_info;
	uint64_t msm_isp_last_overflow_ab;
	uint64_t msm_isp_last_overflow_ib;
	uint64_t msm_isp_vfe_clk_rate;
	struct msm_isp_ub_info *ub_info;
};

#endif
+33 −8
Original line number Diff line number Diff line
@@ -592,6 +592,11 @@ static void msm_vfe40_process_error_status(struct vfe_device *vfe_dev)
		pr_err_ratelimited("%s: status skin bhist bus overflow\n",
			__func__);
	}

	/* Update ab/ib values for any overflow that may have occured*/
	if ((error_status1 >> 9) & 0x7FFF) {
		msm_isp_util_update_last_overflow_ab_ib(vfe_dev);
	}
}

static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
@@ -1209,11 +1214,14 @@ static void msm_vfe40_cfg_axi_ub_equal_default(
		}
	}

	if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION)
	if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION) {
		vfe_dev->ub_info->wm_ub = VFE40_TOTAL_WM_UB_8916;
		total_wm_ub = VFE40_TOTAL_WM_UB_8916;
	else
	} else {
		vfe_dev->ub_info->wm_ub = VFE40_TOTAL_WM_UB;
		total_wm_ub = VFE40_TOTAL_WM_UB;

	}
	vfe_dev->ub_info->num_wm = axi_data->hw_info->num_wm;
	prop_size = total_wm_ub -
		axi_data->hw_info->min_wm_ub * num_used_wms;
	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
@@ -1226,10 +1234,17 @@ static void msm_vfe40_cfg_axi_ub_equal_default(
			wm_ub_size = axi_data->hw_info->min_wm_ub + delta;
			msm_camera_io_w(ub_offset << 16 | (wm_ub_size - 1),
				vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);

			vfe_dev->ub_info->data[i] =
				ub_offset << 16 | (wm_ub_size - 1);
			vfe_dev->ub_info->addr[i] =  VFE40_WM_BASE(i) + 0x10;
			ub_offset += wm_ub_size;
		} else
		} else {
			msm_camera_io_w(0,
				vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);
			vfe_dev->ub_info->data[i] = 0;
			vfe_dev->ub_info->addr[i] = VFE40_WM_BASE(i) + 0x10;
		}
	}
}

@@ -1241,14 +1256,21 @@ static void msm_vfe40_cfg_axi_ub_equal_slicing(
	uint32_t equal_slice_ub;
	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;

	if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION)
	if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION) {
		vfe_dev->ub_info->wm_ub = VFE40_EQUAL_SLICE_UB_8916;
		equal_slice_ub = VFE40_EQUAL_SLICE_UB_8916;
	else
	} else {
		vfe_dev->ub_info->wm_ub = VFE40_EQUAL_SLICE_UB;
		equal_slice_ub = VFE40_EQUAL_SLICE_UB;
	}

	vfe_dev->ub_info->num_wm = axi_data->hw_info->num_wm;
	for (i = 0; i < axi_data->hw_info->num_wm; i++) {
		msm_camera_io_w(ub_offset << 16 | (equal_slice_ub - 1),
			vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);
		vfe_dev->ub_info->data[i] =
			ub_offset << 16 | (equal_slice_ub - 1);
		vfe_dev->ub_info->addr[i] = VFE40_WM_BASE(i) + 0x10;
		ub_offset += equal_slice_ub;
	}
}
@@ -1257,11 +1279,14 @@ static void msm_vfe40_cfg_axi_ub(struct vfe_device *vfe_dev)
{
	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
	axi_data->wm_ub_cfg_policy = MSM_WM_UB_CFG_DEFAULT;
	if (axi_data->wm_ub_cfg_policy == MSM_WM_UB_EQUAL_SLICING)
	if (axi_data->wm_ub_cfg_policy == MSM_WM_UB_EQUAL_SLICING) {
		vfe_dev->ub_info->policy = MSM_WM_UB_EQUAL_SLICING;
		msm_vfe40_cfg_axi_ub_equal_slicing(vfe_dev);
	else
	} else {
		vfe_dev->ub_info->policy = MSM_WM_UB_CFG_DEFAULT;
		msm_vfe40_cfg_axi_ub_equal_default(vfe_dev);
	}
}

static void msm_vfe40_update_ping_pong_addr(
	struct vfe_device *vfe_dev,
+42 −2
Original line number Diff line number Diff line
@@ -24,8 +24,7 @@
static DEFINE_MUTEX(bandwidth_mgr_mutex);
static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;

#define MSM_ISP_MIN_AB 450000000
#define MSM_ISP_MIN_IB 900000000
static uint64_t msm_isp_cpp_clk_rate;

#define VFE40_8974V2_VERSION 0x1001001A
static struct msm_bus_vectors msm_isp_init_vectors[] = {
@@ -186,6 +185,12 @@ int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
	}
	msm_bus_scale_client_update_request(isp_bandwidth_mgr.bus_client,
		isp_bandwidth_mgr.bus_vector_active_idx);
	/* Insert into circular buffer */
	msm_isp_update_req_history(isp_bandwidth_mgr.bus_client,
		path->vectors[0].ab,
		path->vectors[0].ib,
		isp_bandwidth_mgr.client_info,
		sched_clock());
	mutex_unlock(&bandwidth_mgr_mutex);
	return 0;
}
@@ -217,6 +222,40 @@ void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client)
	mutex_unlock(&bandwidth_mgr_mutex);
}

void msm_isp_util_get_bandwidth_stats(struct vfe_device *vfe_dev,
				      struct msm_isp_statistics *stats)
{
	stats->isp_vfe0_active = isp_bandwidth_mgr.client_info[ISP_VFE0].active;
	stats->isp_vfe0_ab = isp_bandwidth_mgr.client_info[ISP_VFE0].ab;
	stats->isp_vfe0_ib = isp_bandwidth_mgr.client_info[ISP_VFE0].ib;

	stats->isp_vfe1_active = isp_bandwidth_mgr.client_info[ISP_VFE1].active;
	stats->isp_vfe1_ab = isp_bandwidth_mgr.client_info[ISP_VFE1].ab;
	stats->isp_vfe1_ib = isp_bandwidth_mgr.client_info[ISP_VFE1].ib;

	stats->isp_cpp_active = isp_bandwidth_mgr.client_info[ISP_CPP].active;
	stats->isp_cpp_ab = isp_bandwidth_mgr.client_info[ISP_CPP].ab;
	stats->isp_cpp_ib = isp_bandwidth_mgr.client_info[ISP_CPP].ib;
	stats->last_overflow_ab = vfe_dev->msm_isp_last_overflow_ab;
	stats->last_overflow_ib = vfe_dev->msm_isp_last_overflow_ib;
	stats->vfe_clk_rate = vfe_dev->msm_isp_vfe_clk_rate;
	stats->cpp_clk_rate = msm_isp_cpp_clk_rate;
}

void msm_isp_util_update_last_overflow_ab_ib(struct vfe_device *vfe_dev)
{
	struct msm_bus_paths *path;
	 path = &(msm_isp_bus_client_pdata.usecase[
		  isp_bandwidth_mgr.bus_vector_active_idx]);
	vfe_dev->msm_isp_last_overflow_ab = path->vectors[0].ab;
	vfe_dev->msm_isp_last_overflow_ib = path->vectors[0].ib;
}

void msm_isp_util_update_clk_rate(long clock_rate)
{
	msm_isp_cpp_clk_rate = clock_rate;
}

uint32_t msm_isp_get_framedrop_period(
	enum msm_vfe_frame_skip_pattern frame_skip_pattern)
{
@@ -394,6 +433,7 @@ static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, long *rate)
		return rc;
	}
	*rate = round_rate;
	vfe_dev->msm_isp_vfe_clk_rate = round_rate;
	return 0;
}

+8 −12
Original line number Diff line number Diff line
@@ -24,18 +24,6 @@
#endif

#define ALT_VECTOR_IDX(x) {x = 3 - x; }
struct msm_isp_bandwidth_info {
	uint32_t active;
	uint64_t ab;
	uint64_t ib;
};

enum msm_isp_hw_client {
	ISP_VFE0,
	ISP_VFE1,
	ISP_CPP,
	MAX_ISP_CLIENT,
};

struct msm_isp_bandwidth_mgr {
	uint32_t bus_client;
@@ -52,6 +40,14 @@ void msm_isp_reset_burst_count_and_frame_drop(
int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client);
int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
	uint64_t ab, uint64_t ib);
void msm_isp_util_get_bandwidth_stats(struct vfe_device *vfe_dev,
				      struct msm_isp_statistics *stats);
void msm_isp_util_update_last_overflow_ab_ib(struct vfe_device *vfe_dev);
void msm_isp_util_update_clk_rate(long clock_rate);
void msm_isp_update_req_history(uint32_t client, uint64_t ab,
				uint64_t ib,
				struct msm_isp_bandwidth_info *client_info,
				unsigned long long ts);
void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client);

int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
Loading