msm: camera: Add support for dynamic bus scaling

ISP bus vector should be calculated based on input
data rate and output dimensions. The vectors will
be dynamically changed based on the ISP output
enabled.

Change-Id: I7cbbf8fc5231b64a91c61cc7a2136bf8c09a730a
Signed-off-by: Kevin Chan <ktchan@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 6059e09..1b762ea 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -33,7 +33,7 @@
 #define MAX_NUM_COMPOSITE_MASK 4
 #define MAX_NUM_STATS_COMP_MASK 2
 #define MAX_INIT_FRAME_DROP 31
-#define ISP_SUB(a) ((a > 0) ? a-1 : 0)
+#define ISP_Q2 (1 << 2)
 
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
@@ -248,6 +248,12 @@
 	uint32_t burst_frame_count;/*number of sof before burst stop*/
 	uint8_t framedrop_update;
 
+	/*Bandwidth calculation info*/
+	uint32_t max_width;
+	/*Based on format plane size in Q2. e.g NV12 = 1.5*/
+	uint32_t format_factor;
+	uint32_t bandwidth;
+
 	/*Run time update variables*/
 	uint32_t runtime_init_frame_drop;
 	uint32_t runtime_burst_frame_count;/*number of sof before burst stop*/
@@ -266,7 +272,8 @@
 	uint8_t pix_stream_count;
 	uint8_t raw_stream_count;
 	enum msm_vfe_inputmux input_mux;
-	uint32_t pixel_clock;
+	uint32_t width;
+	long pixel_clock;
 };
 
 enum msm_wm_ub_cfg_type {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 173f11f..31fa39e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -39,42 +39,6 @@
 	(VFE32_STATS_BASE(idx) + 0x4 * \
 	(~(ping_pong >> (idx + VFE32_STATS_PING_PONG_OFFSET)) & 0x1))
 
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe32_init_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 0,
-		.ib  = 0,
-	},
-};
-
-static struct msm_bus_vectors msm_vfe32_preview_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 1027648000,
-		.ib  = 1105920000,
-	},
-};
-
-static struct msm_bus_paths msm_vfe32_bus_client_config[] = {
-	{
-		ARRAY_SIZE(msm_vfe32_init_vectors),
-		msm_vfe32_init_vectors,
-	},
-	{
-		ARRAY_SIZE(msm_vfe32_preview_vectors),
-		msm_vfe32_preview_vectors,
-	},
-};
-
-static struct msm_bus_scale_pdata msm_vfe32_bus_client_pdata = {
-		msm_vfe32_bus_client_config,
-		ARRAY_SIZE(msm_vfe32_bus_client_config),
-		.name = "msm_camera_vfe",
-};
-
 #define VFE32_CLK_IDX 0
 static struct msm_cam_clk_info msm_vfe32_clk_info[] = {
 	{"vfe_clk", 266667000},
@@ -85,15 +49,11 @@
 static int msm_vfe32_init_hardware(struct vfe_device *vfe_dev)
 {
 	int rc = -1;
-
-	vfe_dev->bus_perf_client =
-		msm_bus_scale_register_client(&msm_vfe32_bus_client_pdata);
-	if (!vfe_dev->bus_perf_client) {
-		pr_err("%s: Registration Failed!\n", __func__);
-		vfe_dev->bus_perf_client = 0;
+	rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+	if (rc < 0) {
+		pr_err("%s: Bandwidth registration Failed!\n", __func__);
 		goto bus_scale_register_failed;
 	}
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 1);
 
 	if (vfe_dev->fs_vfe) {
 		rc = regulator_enable(vfe_dev->fs_vfe);
@@ -132,8 +92,7 @@
 clk_enable_failed:
 	regulator_disable(vfe_dev->fs_vfe);
 fs_failed:
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 bus_scale_register_failed:
 	return rc;
 }
@@ -146,8 +105,7 @@
 	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
 		 vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 0);
 	regulator_disable(vfe_dev->fs_vfe);
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 }
 
 static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 30af3a1..256d136 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -77,42 +77,6 @@
 #define VFE40_BUS_BDG_QOS_CFG_6     0x000002DC
 #define VFE40_BUS_BDG_QOS_CFG_7     0x000002E0
 
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe40_init_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 0,
-		.ib  = 0,
-	},
-};
-
-static struct msm_bus_vectors msm_vfe40_preview_vectors[] = {
-	{
-		.src = MSM_BUS_MASTER_VFE,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab  = 2027648000U,
-		.ib  = 2805920000U,
-	},
-};
-
-static struct msm_bus_paths msm_vfe40_bus_client_config[] = {
-	{
-		ARRAY_SIZE(msm_vfe40_init_vectors),
-		msm_vfe40_init_vectors,
-	},
-	{
-		ARRAY_SIZE(msm_vfe40_preview_vectors),
-		msm_vfe40_preview_vectors,
-	},
-};
-
-static struct msm_bus_scale_pdata msm_vfe40_bus_client_pdata = {
-	msm_vfe40_bus_client_config,
-	ARRAY_SIZE(msm_vfe40_bus_client_config),
-	.name = "msm_camera_vfe",
-};
-
 #define VFE40_CLK_IDX 1
 static struct msm_cam_clk_info msm_vfe40_clk_info[] = {
 	{"camss_top_ahb_clk", -1},
@@ -224,16 +188,11 @@
 static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
 {
 	int rc = -1;
-
-	vfe_dev->bus_perf_client =
-		msm_bus_scale_register_client(&msm_vfe40_bus_client_pdata);
-	if (!vfe_dev->bus_perf_client) {
-		pr_err("%s: Registration Failed!\n", __func__);
-		vfe_dev->bus_perf_client = 0;
+	rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+	if (rc < 0) {
+		pr_err("%s: Bandwidth registration Failed!\n", __func__);
 		goto bus_scale_register_failed;
 	}
-	msm_bus_scale_client_update_request(
-		vfe_dev->bus_perf_client, 1);
 
 	if (vfe_dev->fs_vfe) {
 		rc = regulator_enable(vfe_dev->fs_vfe);
@@ -281,8 +240,7 @@
 clk_enable_failed:
 	regulator_disable(vfe_dev->fs_vfe);
 fs_failed:
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 bus_scale_register_failed:
 	return rc;
 }
@@ -296,8 +254,7 @@
 	msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
 		vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 0);
 	regulator_disable(vfe_dev->fs_vfe);
-	msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
-	msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+	msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
 }
 
 static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 2a2284e..477985d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -97,12 +97,14 @@
 	case V4L2_PIX_FMT_QGRBG12:
 	case V4L2_PIX_FMT_QRGGB12:
 		stream_info->num_planes = 1;
+		stream_info->format_factor = ISP_Q2;
 		break;
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
 		stream_info->num_planes = 2;
+		stream_info->format_factor = 1.5 * ISP_Q2;
 		break;
 	/*TD: Add more image format*/
 	default:
@@ -133,9 +135,12 @@
 		return rc;
 	}
 
-	for (i = 0; i < stream_info->num_planes; i++)
+	for (i = 0; i < stream_info->num_planes; i++) {
 		stream_info->plane_offset[i] =
 			stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+		stream_info->max_width = max(stream_info->max_width,
+			stream_cfg_cmd->plane_cfg[i].output_width);
+	}
 
 	stream_info->stream_src = stream_cfg_cmd->stream_src;
 	stream_info->frame_based = stream_cfg_cmd->frame_base;
@@ -447,6 +452,23 @@
 	}
 }
 
+void msm_isp_calculate_bandwidth(
+	struct msm_vfe_axi_shared_data *axi_data,
+	struct msm_vfe_axi_stream *stream_info)
+{
+	if (stream_info->stream_src < RDI_INTF_0) {
+		stream_info->bandwidth =
+			(axi_data->src_info[VFE_PIX_0].pixel_clock /
+			axi_data->src_info[VFE_PIX_0].width) *
+			stream_info->max_width;
+		stream_info->bandwidth = stream_info->bandwidth *
+			stream_info->format_factor / ISP_Q2;
+	} else {
+		int rdi = SRC_TO_INTF(stream_info->stream_src);
+		stream_info->bandwidth = axi_data->src_info[rdi].pixel_clock;
+	}
+}
+
 int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
 {
 	int rc = 0, i;
@@ -787,6 +809,46 @@
 		ISP_DBG("%s\n", line_str);
 }
 
+/*Factor in Q2 format*/
+#define ISP_DEFAULT_FORMAT_FACTOR 6
+#define ISP_BUS_UTILIZATION_FACTOR 6
+static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
+{
+	int i, rc = 0;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	uint32_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
+	uint32_t num_pix_streams = 0;
+	uint64_t total_bandwidth = 0;
+
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		stream_info = &axi_data->stream_info[i];
+		if (stream_info->state == ACTIVE ||
+			stream_info->state == START_PENDING) {
+			if (stream_info->stream_src < RDI_INTF_0) {
+				total_pix_bandwidth += stream_info->bandwidth;
+				num_pix_streams++;
+			} else {
+				total_rdi_bandwidth += stream_info->bandwidth;
+			}
+		}
+	}
+	if (num_pix_streams > 0)
+		total_pix_bandwidth = total_pix_bandwidth /
+			num_pix_streams * (num_pix_streams - 1) +
+			axi_data->src_info[VFE_PIX_0].pixel_clock *
+			ISP_DEFAULT_FORMAT_FACTOR / ISP_Q2;
+	total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
+
+	rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+		total_bandwidth, total_bandwidth *
+		ISP_BUS_UTILIZATION_FACTOR / ISP_Q2);
+	if (rc < 0)
+		pr_err("%s: update failed\n", __func__);
+
+	return rc;
+}
+
 static int msm_isp_axi_wait_for_cfg_done(struct vfe_device *vfe_dev)
 {
 	int rc;
@@ -864,6 +926,7 @@
 		src_state = axi_data->src_info[
 			SRC_TO_INTF(stream_info->stream_src)].active;
 
+		msm_isp_calculate_bandwidth(axi_data, stream_info);
 		msm_isp_reset_framedrop(vfe_dev, stream_info);
 		msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask);
 		rc = msm_isp_init_stream_ping_pong_reg(vfe_dev, stream_info);
@@ -886,7 +949,7 @@
 			stream_info->state = ACTIVE;
 		}
 	}
-
+	msm_isp_update_stream_bandwidth(vfe_dev);
 	vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask);
 	vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
 
@@ -918,7 +981,7 @@
 		pr_err("%s: wait for config done failed\n", __func__);
 		return rc;
 	}
-
+	msm_isp_update_stream_bandwidth(vfe_dev);
 	if (camif_update == DISABLE_CAMIF)
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, DISABLE_CAMIF);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 9e4a0a1..9fd87f3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -9,6 +9,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include <linux/mutex.h>
 #include <linux/io.h>
 #include <media/v4l2-subdev.h>
 
@@ -19,6 +20,139 @@
 #include "msm_camera_io_util.h"
 
 #define MAX_ISP_V4l2_EVENTS 100
+static DEFINE_MUTEX(bandwidth_mgr_mutex);
+static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;
+
+#define MSM_ISP_MIN_AB 300000000
+#define MSM_ISP_MIN_IB 450000000
+
+static struct msm_bus_vectors msm_isp_init_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = 0,
+		.ib  = 0,
+	},
+};
+
+static struct msm_bus_vectors msm_isp_ping_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = MSM_ISP_MIN_AB,
+		.ib  = MSM_ISP_MIN_IB,
+	},
+};
+
+static struct msm_bus_vectors msm_isp_pong_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_VFE,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab  = MSM_ISP_MIN_AB,
+		.ib  = MSM_ISP_MIN_IB,
+	},
+};
+
+static struct msm_bus_paths msm_isp_bus_client_config[] = {
+	{
+		ARRAY_SIZE(msm_isp_init_vectors),
+		msm_isp_init_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_isp_ping_vectors),
+		msm_isp_ping_vectors,
+	},
+	{
+		ARRAY_SIZE(msm_isp_pong_vectors),
+		msm_isp_pong_vectors,
+	},
+};
+
+static struct msm_bus_scale_pdata msm_isp_bus_client_pdata = {
+	msm_isp_bus_client_config,
+	ARRAY_SIZE(msm_isp_bus_client_config),
+	.name = "msm_camera_isp",
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+	int rc = 0;
+	mutex_lock(&bandwidth_mgr_mutex);
+	isp_bandwidth_mgr.client_info[client].active = 1;
+	if (isp_bandwidth_mgr.use_count++) {
+		mutex_unlock(&bandwidth_mgr_mutex);
+		return rc;
+	}
+	isp_bandwidth_mgr.bus_client =
+		msm_bus_scale_register_client(&msm_isp_bus_client_pdata);
+	if (!isp_bandwidth_mgr.bus_client) {
+		pr_err("%s: client register failed\n", __func__);
+		mutex_unlock(&bandwidth_mgr_mutex);
+		return -EINVAL;
+	}
+
+	isp_bandwidth_mgr.bus_vector_active_idx = 1;
+	msm_bus_scale_client_update_request(
+	   isp_bandwidth_mgr.bus_client,
+	   isp_bandwidth_mgr.bus_vector_active_idx);
+
+	mutex_unlock(&bandwidth_mgr_mutex);
+	return 0;
+}
+
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+	uint64_t ab, uint64_t ib)
+{
+	int i;
+	struct msm_bus_paths *path;
+	mutex_lock(&bandwidth_mgr_mutex);
+	if (!isp_bandwidth_mgr.use_count ||
+		!isp_bandwidth_mgr.bus_client) {
+		pr_err("%s: bandwidth manager inactive\n", __func__);
+		return -EINVAL;
+	}
+
+	isp_bandwidth_mgr.client_info[client].ab = ab;
+	isp_bandwidth_mgr.client_info[client].ib = ib;
+	ALT_VECTOR_IDX(isp_bandwidth_mgr.bus_vector_active_idx);
+	path =
+		&(msm_isp_bus_client_pdata.usecase[
+		  isp_bandwidth_mgr.bus_vector_active_idx]);
+	path->vectors[0].ab = MSM_ISP_MIN_AB;
+	path->vectors[0].ib = MSM_ISP_MIN_IB;
+	for (i = 0; i < MAX_ISP_CLIENT; i++) {
+		if (isp_bandwidth_mgr.client_info[client].active) {
+			path->vectors[0].ab +=
+				isp_bandwidth_mgr.client_info[i].ab;
+			path->vectors[0].ib +=
+				isp_bandwidth_mgr.client_info[i].ib;
+		}
+	}
+	msm_bus_scale_client_update_request(isp_bandwidth_mgr.bus_client,
+		isp_bandwidth_mgr.bus_vector_active_idx);
+	mutex_unlock(&bandwidth_mgr_mutex);
+	return 0;
+}
+
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+	mutex_lock(&bandwidth_mgr_mutex);
+	memset(&isp_bandwidth_mgr.client_info[client], 0,
+		   sizeof(struct msm_isp_bandwidth_info));
+	if (--isp_bandwidth_mgr.use_count) {
+		mutex_unlock(&bandwidth_mgr_mutex);
+		return;
+	}
+
+	if (!isp_bandwidth_mgr.bus_client)
+		return;
+
+	msm_bus_scale_client_update_request(
+	   isp_bandwidth_mgr.bus_client, 0);
+	msm_bus_scale_unregister_client(isp_bandwidth_mgr.bus_client);
+	isp_bandwidth_mgr.bus_client = 0;
+	mutex_unlock(&bandwidth_mgr_mutex);
+}
 
 static inline void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp)
 {
@@ -100,6 +234,8 @@
 		input_cfg->input_pix_clk;
 	vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux =
 		input_cfg->d.pix_cfg.input_mux;
+	vfe_dev->axi_data.src_info[VFE_PIX_0].width =
+		input_cfg->d.pix_cfg.camif_cfg.pixels_per_line;
 
 	rc = msm_isp_set_clk_rate(vfe_dev,
 		vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 3dac7e0..7934f26 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -22,6 +22,32 @@
 #define ISP_DBG(fmt, args...) pr_debug(fmt, ##args)
 #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;
+	uint32_t bus_vector_active_idx;
+	uint32_t use_count;
+	struct msm_isp_bandwidth_info client_info[MAX_ISP_CLIENT];
+};
+
+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_deinit_bandwidth_mgr(enum msm_isp_hw_client client);
+
 int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 	struct v4l2_event_subscription *sub);
 
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
index 2f969d2..c793ef6 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
@@ -1,3 +1,4 @@
 ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/isp/
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
 obj-$(CONFIG_MSM_CPP) += msm_cpp.o
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 2598b07..1203d17 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -34,6 +34,7 @@
 #include <media/msmb_pproc.h>
 #include <media/msmb_generic_buf_mgr.h>
 #include "msm_cpp.h"
+#include "msm_isp_util.h"
 #include "msm_camera_io_util.h"
 
 #define MSM_CPP_DRV_NAME "msm_cpp"
@@ -582,6 +583,12 @@
 static int cpp_init_hardware(struct cpp_device *cpp_dev)
 {
 	int rc = 0;
+	rc = msm_isp_init_bandwidth_mgr(ISP_CPP);
+	if (rc < 0) {
+		pr_err("%s: Bandwidth registration Failed!\n", __func__);
+		goto bus_scale_register_failed;
+	}
+	msm_isp_update_bandwidth(ISP_CPP, 981345600, 1600020000);
 
 	if (cpp_dev->fs_cpp == NULL) {
 		cpp_dev->fs_cpp =
@@ -667,6 +674,9 @@
 	regulator_disable(cpp_dev->fs_cpp);
 	regulator_put(cpp_dev->fs_cpp);
 fs_failed:
+	msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+	msm_isp_deinit_bandwidth_mgr(ISP_CPP);
+bus_scale_register_failed:
 	return rc;
 }
 
@@ -688,6 +698,8 @@
 		regulator_put(cpp_dev->fs_cpp);
 		cpp_dev->fs_cpp = NULL;
 	}
+	msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+	msm_isp_deinit_bandwidth_mgr(ISP_CPP);
 }
 
 static void cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)