Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.c +234 −25 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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", Loading @@ -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; Loading @@ -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 { Loading Loading @@ -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); Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading @@ -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, Loading @@ -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: Loading drivers/media/platform/msm/camera_v2/isp/msm_isp.h +72 −17 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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 drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +33 −8 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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++) { Loading @@ -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; } } } Loading @@ -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; } } Loading @@ -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, Loading drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +42 −2 Original line number Diff line number Diff line Loading @@ -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[] = { Loading Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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; } Loading drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h +8 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.c +234 −25 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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", Loading @@ -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; Loading @@ -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 { Loading Loading @@ -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); Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading @@ -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; Loading @@ -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; Loading @@ -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) { Loading @@ -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, Loading @@ -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: Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp.h +72 −17 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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
drivers/media/platform/msm/camera_v2/isp/msm_isp40.c +33 −8 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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++) { Loading @@ -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; } } } Loading @@ -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; } } Loading @@ -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, Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +42 −2 Original line number Diff line number Diff line Loading @@ -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[] = { Loading Loading @@ -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; } Loading Loading @@ -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) { Loading Loading @@ -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; } Loading
drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h +8 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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