msm: camera: isp: Add support for BUS IRQ controller

Initialize BUS IRQ controller. Remove hard code subscribe of IRQ mask
and add independent subscribe/unsubscribe for each WM/composite_group.

Change-Id: I02983ae9811c33ec353b2d1caecbd5c84f7177ae
Signed-off-by: Harsh Shah <harshs@codeaurora.org>
Signed-off-by: Soundrapandian Jeyaprakash <jsoundra@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 9203ee6..07a7612 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -17,8 +17,10 @@
 #include "cam_io_util.h"
 #include "cam_cdm_util.h"
 #include "cam_hw_intf.h"
+#include "cam_ife_hw_mgr.h"
 #include "cam_vfe_hw_intf.h"
 #include "cam_irq_controller.h"
+#include "cam_tasklet_util.h"
 #include "cam_vfe_bus.h"
 #include "cam_vfe_bus_ver2.h"
 #include "cam_vfe_core.h"
@@ -26,28 +28,25 @@
 #undef CDBG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
 
-#define FRAME_BASED_EN 0
+static const char drv_name[] = "vfe_bus";
+
+#define CAM_VFE_BUS_IRQ_REG0                     0
+#define CAM_VFE_BUS_IRQ_REG1                     1
+#define CAM_VFE_BUS_IRQ_REG2                     2
+#define CAM_VFE_BUS_IRQ_MAX                      3
+
+#define CAM_VFE_BUS_VER2_PAYLOAD_MAX             256
 
 #define MAX_BUF_UPDATE_REG_NUM   \
 	(sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
 #define MAX_REG_VAL_PAIR_SIZE    \
-		(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
+	(MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
 
 #define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val)    \
-		do {                                               \
-			buf_array[index++] = offset;               \
-			buf_array[index++] = val;                  \
-		} while (0)
-
-static uint32_t irq_reg_offset[CAM_IFE_BUS_IRQ_REGISTERS_MAX] = {
-	0x0000205C,
-	0x00002060,
-	0x00002064,
-	0x0000206C,
-	0x00002070,
-	0x00002074,
-	0x00002078,
-};
+	do {                                               \
+		buf_array[index++] = offset;               \
+		buf_array[index++] = val;                  \
+	} while (0)
 
 enum cam_vfe_bus_packer_format {
 	PACKER_FMT_PLAIN_128                   = 0x0,
@@ -70,23 +69,29 @@
 };
 
 struct cam_vfe_bus_ver2_common_data {
+	uint32_t                                    core_index;
 	void __iomem                               *mem_base;
 	struct cam_hw_intf                         *hw_intf;
 	void                                       *bus_irq_controller;
 	void                                       *vfe_irq_controller;
 	struct cam_vfe_bus_ver2_reg_offset_common  *common_reg;
 	uint32_t                                    io_buf_update[
-							MAX_REG_VAL_PAIR_SIZE];
+		MAX_REG_VAL_PAIR_SIZE];
+
+	struct cam_vfe_bus_irq_evt_payload          evt_payload[
+		CAM_VFE_BUS_VER2_PAYLOAD_MAX];
+	struct list_head                            free_payload_list;
 };
 
 struct cam_vfe_bus_ver2_wm_resource_data {
 	uint32_t             index;
 	struct cam_vfe_bus_ver2_common_data            *common_data;
 	struct cam_vfe_bus_ver2_reg_offset_bus_client  *hw_regs;
+	void                                *ctx;
 
 	uint32_t             irq_enabled;
-
 	uint32_t             init_cfg_done;
+
 	uint32_t             offset;
 	uint32_t             width;
 	uint32_t             height;
@@ -127,6 +132,8 @@
 	uint32_t                         dual_slave_core;
 	uint32_t                         intra_client_mask;
 	uint32_t                         composite_mask;
+
+	void                            *ctx;
 };
 
 struct cam_vfe_bus_ver2_vfe_out_data {
@@ -147,7 +154,6 @@
 	struct cam_cdm_utils_ops        *cdm_util_ops;
 };
 
-
 struct cam_vfe_bus_ver2_priv {
 	struct cam_vfe_bus_ver2_common_data common_data;
 
@@ -159,12 +165,59 @@
 	struct list_head                    free_dual_comp_grp;
 	struct list_head                    used_comp_grp;
 
-	struct cam_vfe_bus_irq_evt_payload  evt_payload[128];
-	struct list_head                    free_payload_list;
+	uint32_t                            irq_handle;
 };
 
+static int cam_vfe_bus_get_evt_payload(
+	struct cam_vfe_bus_ver2_common_data  *common_data,
+	struct cam_vfe_bus_irq_evt_payload  **evt_payload)
+{
+	if (list_empty(&common_data->free_payload_list)) {
+		*evt_payload = NULL;
+		pr_err("No free payload\n");
+		return -ENODEV;
+	}
+
+	*evt_payload = list_first_entry(&common_data->free_payload_list,
+		struct cam_vfe_bus_irq_evt_payload, list);
+	list_del_init(&(*evt_payload)->list);
+	return 0;
+}
+
 static int cam_vfe_bus_put_evt_payload(void     *core_info,
-	struct cam_vfe_bus_irq_evt_payload     **evt_payload);
+	struct cam_vfe_bus_irq_evt_payload     **evt_payload)
+{
+	struct cam_vfe_bus_ver2_common_data *common_data = NULL;
+	uint32_t  *ife_irq_regs = NULL;
+	uint32_t   status_reg0, status_reg1, status_reg2;
+
+	if (!core_info) {
+		pr_err("Invalid param core_info NULL");
+		return -EINVAL;
+	}
+	if (*evt_payload == NULL) {
+		pr_err("No payload to put\n");
+		return -EINVAL;
+	}
+
+	ife_irq_regs = (*evt_payload)->irq_reg_val;
+	status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
+	status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
+	status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
+
+	if (status_reg0 || status_reg1 || status_reg2) {
+		CDBG("status0 0x%x status1 0x%x status2 0x%x\n",
+			status_reg0, status_reg1, status_reg2);
+		return 0;
+	}
+
+	common_data = core_info;
+	list_add_tail(&(*evt_payload)->list,
+		&common_data->free_payload_list);
+	*evt_payload = NULL;
+
+	return 0;
+}
 
 static int cam_vfe_bus_ver2_get_intra_client_mask(
 	enum cam_vfe_bus_ver2_vfe_core_id  dual_slave_core,
@@ -592,6 +645,8 @@
 static int cam_vfe_bus_acquire_wm(
 	struct cam_vfe_bus_ver2_priv          *ver2_bus_priv,
 	struct cam_isp_out_port_info          *out_port_info,
+	void                                  *tasklet,
+	void                                  *ctx,
 	enum cam_vfe_bus_ver2_vfe_out_type     vfe_out_res_id,
 	enum cam_vfe_bus_plane_type            plane,
 	enum cam_isp_hw_split_id               split_id,
@@ -615,10 +670,12 @@
 	}
 
 	wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
+	wm_res_local->tasklet_info = tasklet;
 	wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 
 	rsrc_data = wm_res_local->res_priv;
 	rsrc_data->irq_enabled = subscribe_irq;
+	rsrc_data->ctx = ctx;
 	rsrc_data->format = out_port_info->format;
 	rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
 
@@ -718,6 +775,8 @@
 	rsrc_data->ubwc_meta_offset = 0;
 	rsrc_data->init_cfg_done = 0;
 	rsrc_data->en_cfg = 0;
+
+	wm_res->tasklet_info = NULL;
 	wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
 
 	return 0;
@@ -730,6 +789,7 @@
 		wm_res->res_priv;
 	struct cam_vfe_bus_ver2_common_data        *common_data =
 		rsrc_data->common_data;
+	uint32_t                   bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
 
 	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
 	cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
@@ -753,6 +813,28 @@
 	cam_io_w(0x0,
 		common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
 
+	/* Subscribe IRQ */
+	if (rsrc_data->irq_enabled) {
+		CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
+		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
+			(1 << rsrc_data->index);
+		wm_res->irq_handle = cam_irq_controller_subscribe_irq(
+			common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
+			bus_irq_reg_mask, wm_res,
+			wm_res->top_half_handler,
+			cam_ife_mgr_do_tasklet_buf_done,
+			wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
+		if (wm_res->irq_handle < 0) {
+			pr_err("Subscribe IRQ failed for WM %d\n",
+				rsrc_data->index);
+			return -EFAULT;
+		}
+	}
+
+	/* Enable WM */
+	cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
+		rsrc_data->hw_regs->cfg);
+
 	CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
 		rsrc_data->width, rsrc_data->height);
 	CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
@@ -781,12 +863,10 @@
 
 	CDBG("irq_enabled %d", rsrc_data->irq_enabled);
 	/* Unsubscribe IRQ */
-	if (rsrc_data->irq_enabled) {
-		/*
-		 * Currently all WM IRQ are unsubscribed in one place. Need to
-		 * make it dynamic.
-		 */
-	}
+	if (rsrc_data->irq_enabled)
+		rc = cam_irq_controller_unsubscribe_irq(
+			common_data->bus_irq_controller,
+			wm_res->irq_handle);
 
 	/* Halt & Reset WM */
 	cam_io_w_mb(BIT(rsrc_data->index),
@@ -800,7 +880,42 @@
 static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
 	struct cam_irq_th_payload *th_payload)
 {
-	return -EPERM;
+	int32_t                                     rc;
+	int                                         i;
+	struct cam_isp_resource_node               *wm_res = NULL;
+	struct cam_vfe_bus_ver2_wm_resource_data   *rsrc_data = NULL;
+	struct cam_vfe_bus_irq_evt_payload         *evt_payload;
+
+	wm_res = th_payload->handler_priv;
+	if (!wm_res) {
+		pr_err_ratelimited("Error! No resource\n");
+		return -ENODEV;
+	}
+
+	rsrc_data = wm_res->res_priv;
+
+	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
+	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+
+	rc  = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
+	if (rc) {
+		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		return rc;
+	}
+
+	cam_isp_hw_get_timestamp(&evt_payload->ts);
+
+	evt_payload->ctx = rsrc_data->ctx;
+	evt_payload->core_index = rsrc_data->common_data->core_index;
+	evt_payload->evt_id  = evt_id;
+
+	for (i = 0; i < th_payload->num_registers; i++)
+		evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
+
+	th_payload->evt_payload_priv = evt_payload;
+
+	CDBG("Exit\n");
+	return rc;
 }
 
 static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
@@ -825,9 +940,10 @@
 			~BIT(rsrc_data->index);
 		rc = CAM_VFE_IRQ_STATUS_SUCCESS;
 	}
+	CDBG("status_reg %x rc %d\n", status_reg, rc);
 
 	if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
-		cam_vfe_bus_put_evt_payload(evt_payload->core_info,
+		cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
 			&evt_payload);
 
 	return rc;
@@ -924,6 +1040,8 @@
 static int cam_vfe_bus_acquire_comp_grp(
 	struct cam_vfe_bus_ver2_priv        *ver2_bus_priv,
 	struct cam_isp_out_port_info        *out_port_info,
+	void                                *tasklet,
+	void                                *ctx,
 	uint32_t                             unique_id,
 	uint32_t                             is_dual,
 	uint32_t                             is_master,
@@ -965,6 +1083,7 @@
 		}
 
 		list_del(&comp_grp_local->list);
+		comp_grp_local->tasklet_info = tasklet;
 		comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 
 		rsrc_data->is_master = is_master;
@@ -987,6 +1106,7 @@
 		}
 	}
 
+	rsrc_data->ctx = ctx;
 	*comp_grp = comp_grp_local;
 
 	return rc;
@@ -1040,6 +1160,7 @@
 	in_rsrc_data->composite_mask = 0;
 	in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
 
+	comp_grp->tasklet_info = NULL;
 	comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
 
 	return 0;
@@ -1052,11 +1173,7 @@
 		comp_grp->res_priv;
 	struct cam_vfe_bus_ver2_common_data        *common_data =
 		rsrc_data->common_data;
-
-	/*
-	 * Individual Comp_Grp Subscribe IRQ can be done here once
-	 * dynamic IRQ enable support is added.
-	 */
+	uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
 
 	cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
 		rsrc_data->hw_regs->comp_mask);
@@ -1078,9 +1195,30 @@
 
 		cam_io_w_mb(intra_client_en, common_data->mem_base +
 			common_data->common_reg->dual_master_comp_cfg);
+
+		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
+	} else {
+		/* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
+		bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
+			(1 << (rsrc_data->comp_grp_type + 5));
+	}
+
+	/* Subscribe IRQ */
+	CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
+	comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
+		common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
+		bus_irq_reg_mask, comp_grp,
+		comp_grp->top_half_handler,
+		cam_ife_mgr_do_tasklet_buf_done,
+		comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
+	if (comp_grp->irq_handle < 0) {
+		pr_err("Subscribe IRQ failed for comp_grp %d\n",
+			rsrc_data->comp_grp_type);
+		return -EFAULT;
 	}
 
 	comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+
 	return rc;
 }
 
@@ -1093,6 +1231,9 @@
 		rsrc_data->common_data;
 
 	/* Unsubscribe IRQ */
+	rc = cam_irq_controller_unsubscribe_irq(
+		common_data->bus_irq_controller,
+		comp_grp->irq_handle);
 
 	cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
 		rsrc_data->hw_regs->comp_mask);
@@ -1120,7 +1261,42 @@
 static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
 	struct cam_irq_th_payload *th_payload)
 {
-	return -EPERM;
+	int32_t                                     rc;
+	int                                         i;
+	struct cam_isp_resource_node               *comp_grp = NULL;
+	struct cam_vfe_bus_ver2_comp_grp_data      *rsrc_data = NULL;
+	struct cam_vfe_bus_irq_evt_payload         *evt_payload;
+
+	comp_grp = th_payload->handler_priv;
+	if (!comp_grp) {
+		pr_err_ratelimited("Error! No resource\n");
+		return -ENODEV;
+	}
+
+	rsrc_data = comp_grp->res_priv;
+
+	CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
+	CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+
+	rc  = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
+	if (rc) {
+		pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+		return rc;
+	}
+
+	cam_isp_hw_get_timestamp(&evt_payload->ts);
+
+	evt_payload->ctx = rsrc_data->ctx;
+	evt_payload->core_index = rsrc_data->common_data->core_index;
+	evt_payload->evt_id  = evt_id;
+
+	for (i = 0; i < th_payload->num_registers; i++)
+		evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
+
+	th_payload->evt_payload_priv = evt_payload;
+
+	CDBG("Exit\n");
+	return rc;
 }
 
 static int cam_vfe_bus_handle_comp_done_bottom_half(
@@ -1136,12 +1312,13 @@
 	uint32_t                               comp_err_reg;
 	uint32_t                               comp_grp_id;
 
+	CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
+
 	if (!evt_payload)
 		return rc;
 
 	cam_ife_irq_regs = evt_payload->irq_reg_val;
 
-	CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
 	switch (rsrc_data->comp_grp_type) {
 	case CAM_VFE_BUS_VER2_COMP_GRP_0:
 	case CAM_VFE_BUS_VER2_COMP_GRP_1:
@@ -1178,8 +1355,8 @@
 			rc = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 
-		CDBG("status reg = 0x%x, bit index = %d\n",
-			status_reg, (comp_grp_id + 5));
+		CDBG("status reg = 0x%x, bit index = %d rc %d\n",
+			status_reg, (comp_grp_id + 5), rc);
 		break;
 
 	case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
@@ -1220,11 +1397,13 @@
 		break;
 	default:
 		rc = CAM_VFE_IRQ_STATUS_ERR;
+		pr_err("Error! Invalid comp_grp_type %u\n",
+			rsrc_data->comp_grp_type);
 		break;
 	}
 
 	if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
-		cam_vfe_bus_put_evt_payload(evt_payload->core_info,
+		cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
 			&evt_payload);
 
 	return rc;
@@ -1297,7 +1476,8 @@
 	return 0;
 }
 
-static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
+static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
+	uint32_t args_size)
 {
 	int                                     rc = -ENODEV;
 	int                                     i;
@@ -1353,30 +1533,43 @@
 		CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
 		rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
 			out_acquire_args->out_port_info,
+			acq_args->tasklet,
+			out_acquire_args->ctx,
 			out_acquire_args->unique_id,
 			out_acquire_args->is_dual,
 			out_acquire_args->is_master,
 			out_acquire_args->dual_slave_core,
 			&rsrc_data->comp_grp);
-		if (rc < 0)
+		if (rc) {
+			pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
+				rsrc_data->common_data->core_index,
+				vfe_out_res_id, rc);
 			return rc;
+		}
 
 		subscribe_irq = 0;
-	} else
+	} else {
 		subscribe_irq = 1;
+	}
 
 	/* Reserve WM */
 	for (i = 0; i < num_wm; i++) {
 		rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
 			out_acquire_args->out_port_info,
+			acq_args->tasklet,
+			out_acquire_args->ctx,
 			vfe_out_res_id,
 			i,
 			out_acquire_args->split_id,
 			subscribe_irq,
 			&rsrc_data->wm_res[i],
 			&client_done_mask);
-		if (rc < 0)
+		if (rc) {
+			pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
+				rsrc_data->common_data->core_index,
+				vfe_out_res_id, rc);
 			goto release_wm;
+		}
 
 		if (rsrc_data->comp_grp)
 			cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
@@ -1399,11 +1592,21 @@
 	return rc;
 }
 
-static int cam_vfe_bus_release_vfe_out(void *bus_priv,
-	struct cam_isp_resource_node        *vfe_out)
+static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
+	uint32_t args_size)
 {
 	uint32_t i;
-	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = vfe_out->res_priv;
+	struct cam_isp_resource_node          *vfe_out = NULL;
+	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
+
+	if (!bus_priv || !release_args) {
+		pr_err("Invalid input bus_priv %pK release_args %pK\n",
+			bus_priv, release_args);
+		return -EINVAL;
+	}
+
+	vfe_out = release_args;
+	rsrc_data = vfe_out->res_priv;
 
 	if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
 		pr_err("Error! Invalid resource state:%d\n",
@@ -1428,12 +1631,20 @@
 	return 0;
 }
 
-static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_start_vfe_out(
+	struct cam_isp_resource_node          *vfe_out)
 {
 	int rc = 0, i;
-	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = vfe_out->res_priv;
-	struct cam_vfe_bus_ver2_common_data   *common_data =
-		rsrc_data->common_data;
+	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
+	struct cam_vfe_bus_ver2_common_data   *common_data = NULL;
+
+	if (!vfe_out) {
+		pr_err("Invalid input\n");
+		return -EINVAL;
+	}
+
+	rsrc_data = vfe_out->res_priv;
+	common_data = rsrc_data->common_data;
 
 	CDBG("Start resource index %d\n", rsrc_data->out_type);
 
@@ -1443,28 +1654,12 @@
 		return -EACCES;
 	}
 
-	/* Enable IRQ Mask */
-	cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
-	cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
-	cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
-
 	for (i = 0; i < rsrc_data->num_wm; i++)
 		rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
 
 	if (rsrc_data->comp_grp)
 		rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
 
-	/* VFE_MODULE_BUS_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
-	/* VFE_MODULE_COLOR_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
-	/* VFE_MODULE_ZOOM_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
-	/* VFE_MODULE_LENS_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
-	/* VFE_MODULE_STATS_CGC_OVERRIDE */
-	cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
-
 	/* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
 	cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
 	/*  BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
@@ -1490,10 +1685,18 @@
 	return rc;
 }
 
-static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_stop_vfe_out(
+	struct cam_isp_resource_node          *vfe_out)
 {
 	int rc = 0, i;
-	struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
+	struct cam_vfe_bus_ver2_vfe_out_data  *rsrc_data = NULL;
+
+	if (!vfe_out) {
+		pr_err("Invalid input\n");
+		return -EINVAL;
+	}
+
+	rsrc_data = vfe_out->res_priv;
 
 	if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
 		vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
@@ -1604,122 +1807,15 @@
 	return 0;
 }
 
-static int cam_vfe_bus_get_evt_payload(
-	struct cam_vfe_bus_ver2_priv         *bus_priv,
-	struct cam_vfe_bus_irq_evt_payload  **evt_payload)
-{
-	if (list_empty(&bus_priv->free_payload_list)) {
-		*evt_payload = NULL;
-		pr_err("No free payload\n");
-		return -ENODEV;
-	}
-
-	*evt_payload = list_first_entry(&bus_priv->free_payload_list,
-		struct cam_vfe_bus_irq_evt_payload, list);
-	list_del_init(&(*evt_payload)->list);
-	return 0;
-}
-
-static int cam_vfe_bus_put_evt_payload(void     *core_info,
-	struct cam_vfe_bus_irq_evt_payload     **evt_payload)
-{
-	struct cam_vfe_bus_ver2_priv         *bus_priv = NULL;
-	uint32_t  *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
-	uint32_t   status_reg0, status_reg1;
-
-	status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
-	status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
-
-	if (status_reg0 || status_reg1) {
-		CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
-		return 0;
-	}
-
-	if (!core_info) {
-		pr_err("Invalid param core_info NULL");
-		return -EINVAL;
-	}
-	if (*evt_payload == NULL) {
-		pr_err("No payload to put\n");
-		return -EINVAL;
-	}
-	bus_priv = (*evt_payload)->bus_priv;
-	list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
-	*evt_payload = NULL;
-	return 0;
-}
-
 static int cam_vfe_bus_ver2_handle_irq(uint32_t    evt_id,
 	struct cam_irq_th_payload                 *th_payload)
 {
-	int32_t                                rc;
-	int                                    i;
-	struct cam_vfe_irq_handler_priv       *handler_priv;
-	struct cam_vfe_hw_core_info           *core_info;
-	struct cam_vfe_bus_irq_evt_payload    *evt_payload;
-	struct cam_vfe_bus                    *bus_info;
 	struct cam_vfe_bus_ver2_priv          *bus_priv;
-	struct cam_irq_controller_reg_info    *reg_info;
-	uint32_t                               irq_mask;
-	int                                    found = 0;
 
-	handler_priv = th_payload->handler_priv;
-	core_info    = handler_priv->core_info;
-	bus_info     = core_info->vfe_bus;
-	bus_priv     = bus_info->bus_priv;
-	reg_info     = &bus_priv->common_data.common_reg->irq_reg_info;
-
-	/*
-	 *  add reset ack handling here once supported.
-	 *  Just clear all the bus irq status registers and ignore the reset.
-	 */
-
+	bus_priv     = th_payload->handler_priv;
 	CDBG("Enter\n");
-	rc  = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
-	if (rc) {
-		pr_err("No tasklet_cmd is free in queue\n");
-		return rc;
-	}
-
-	cam_isp_hw_get_timestamp(&evt_payload->ts);
-
-	evt_payload->core_index = handler_priv->core_index;
-	evt_payload->core_info  = handler_priv->core_info;
-	evt_payload->bus_priv   = bus_priv;
-	CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
-			(uint64_t)handler_priv->core_info);
-
-	for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
-		irq_mask = cam_io_r(handler_priv->mem_base +
-			irq_reg_offset[i] - (0xC * 2));
-		evt_payload->irq_reg_val[i] = irq_mask &
-			cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
-		if (evt_payload->irq_reg_val[i])
-			found = 1;
-		CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
-	}
-	for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
-		cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
-			reg_info->irq_reg_set[i].clear_reg_offset);
-		CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
-			evt_payload->irq_reg_val[i],
-			reg_info->irq_reg_set[i].clear_reg_offset);
-	}
-	cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
-		reg_info->global_clear_offset);
-	CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
-			reg_info->global_clear_bitmask,
-			reg_info->global_clear_offset);
-
-	if (found)
-		th_payload->evt_payload_priv = evt_payload;
-	else {
-		cam_vfe_bus_put_evt_payload(evt_payload->core_info,
-			&evt_payload);
-		rc = -ENOMSG;
-	}
-
-	return rc;
+	return cam_irq_controller_handle_irq(evt_id,
+		bus_priv->common_data.bus_irq_controller);
 }
 
 static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
@@ -1953,6 +2049,69 @@
 	return 0;
 }
 
+static int cam_vfe_bus_start_hw(void *hw_priv,
+	void *start_hw_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_start_vfe_out(hw_priv);
+}
+
+static int cam_vfe_bus_stop_hw(void *hw_priv,
+	void *stop_hw_args, uint32_t arg_size)
+{
+	return cam_vfe_bus_stop_vfe_out(hw_priv);
+}
+
+static int cam_vfe_bus_init_hw(void *hw_priv,
+	void *init_hw_args, uint32_t arg_size)
+{
+	struct cam_vfe_bus_ver2_priv    *bus_priv = hw_priv;
+	uint32_t                         top_irq_reg_mask[2] = {0};
+
+	if (!bus_priv) {
+		pr_err("Error! Invalid args\n");
+		return -EINVAL;
+	}
+
+	top_irq_reg_mask[0] = (1 << 9);
+
+	bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
+		bus_priv->common_data.vfe_irq_controller,
+		CAM_IRQ_PRIORITY_2,
+		top_irq_reg_mask,
+		bus_priv,
+		cam_vfe_bus_ver2_handle_irq,
+		NULL,
+		NULL,
+		NULL);
+
+	if (bus_priv->irq_handle <= 0) {
+		pr_err("Failed to subscribe BUS IRQ\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int cam_vfe_bus_deinit_hw(void *hw_priv,
+	void *deinit_hw_args, uint32_t arg_size)
+{
+	struct cam_vfe_bus_ver2_priv    *bus_priv = hw_priv;
+	int                              rc;
+
+	if (!bus_priv || (bus_priv->irq_handle <= 0)) {
+		pr_err("Error! Invalid args\n");
+		return -EINVAL;
+	}
+
+	rc = cam_irq_controller_unsubscribe_irq(
+		bus_priv->common_data.vfe_irq_controller,
+		bus_priv->irq_handle);
+	if (rc)
+		pr_err("Failed to unsubscribe irq rc=%d\n", rc);
+
+	return rc;
+}
+
 static int cam_vfe_bus_process_cmd(void *priv,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
@@ -1977,7 +2136,7 @@
 }
 
 int cam_vfe_bus_ver2_init(
-	void __iomem                         *mem_base,
+	struct cam_hw_soc_info               *soc_info,
 	struct cam_hw_intf                   *hw_intf,
 	void                                 *bus_hw_info,
 	void                                 *vfe_irq_controller,
@@ -1990,6 +2149,13 @@
 
 	CDBG("Enter\n");
 
+	if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
+		pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
+			soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
+		rc = -EINVAL;
+		goto end;
+	}
+
 	vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
 	if (!vfe_bus_local) {
 		CDBG("Failed to alloc for vfe_bus\n");
@@ -2006,11 +2172,21 @@
 	}
 	vfe_bus_local->bus_priv = bus_priv;
 
-	bus_priv->common_data.mem_base           = mem_base;
+	bus_priv->common_data.core_index         = soc_info->index;
+	bus_priv->common_data.mem_base           =
+		CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
 	bus_priv->common_data.hw_intf            = hw_intf;
 	bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
 	bus_priv->common_data.common_reg         = &ver2_hw_info->common_reg;
 
+	rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
+		&ver2_hw_info->common_reg.irq_reg_info,
+		&bus_priv->common_data.bus_irq_controller);
+	if (rc) {
+		pr_err("Error! cam_irq_controller_init failed\n");
+		goto free_bus_priv;
+	}
+
 	INIT_LIST_HEAD(&bus_priv->free_comp_grp);
 	INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
 	INIT_LIST_HEAD(&bus_priv->used_comp_grp);
@@ -2042,20 +2218,22 @@
 		}
 	}
 
-	INIT_LIST_HEAD(&bus_priv->free_payload_list);
-	for (i = 0; i < 128; i++) {
-		INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
-		list_add_tail(&bus_priv->evt_payload[i].list,
-			&bus_priv->free_payload_list);
+	INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
+	for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
+		INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
+		list_add_tail(&bus_priv->common_data.evt_payload[i].list,
+			&bus_priv->common_data.free_payload_list);
 	}
 
-	vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
-	vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
-	vfe_bus_local->start_resource   = cam_vfe_bus_start_vfe_out;
-	vfe_bus_local->stop_resource    = cam_vfe_bus_stop_vfe_out;
-	vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
+	vfe_bus_local->hw_ops.reserve      = cam_vfe_bus_acquire_vfe_out;
+	vfe_bus_local->hw_ops.release      = cam_vfe_bus_release_vfe_out;
+	vfe_bus_local->hw_ops.start        = cam_vfe_bus_start_hw;
+	vfe_bus_local->hw_ops.stop         = cam_vfe_bus_stop_hw;
+	vfe_bus_local->hw_ops.init         = cam_vfe_bus_init_hw;
+	vfe_bus_local->hw_ops.deinit       = cam_vfe_bus_deinit_hw;
+	vfe_bus_local->top_half_handler    = cam_vfe_bus_ver2_handle_irq;
 	vfe_bus_local->bottom_half_handler = NULL;
-	vfe_bus_local->process_cmd      = cam_vfe_bus_process_cmd;
+	vfe_bus_local->hw_ops.process_cmd  = cam_vfe_bus_process_cmd;
 
 	*vfe_bus = vfe_bus_local;
 
@@ -2080,6 +2258,7 @@
 	for (--i; i >= 0; i--)
 		cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
 
+free_bus_priv:
 	kfree(vfe_bus_local->bus_priv);
 
 free_bus_local:
@@ -2109,9 +2288,9 @@
 		goto free_bus_local;
 	}
 
-	INIT_LIST_HEAD(&bus_priv->free_payload_list);
-	for (i = 0; i < 128; i++)
-		INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
+	INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
+	for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
+		INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
 
 	for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
 		rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
@@ -2135,6 +2314,11 @@
 	INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
 	INIT_LIST_HEAD(&bus_priv->used_comp_grp);
 
+	rc = cam_irq_controller_deinit(
+		&bus_priv->common_data.bus_irq_controller);
+	if (rc)
+		pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
+
 	kfree(vfe_bus_local->bus_priv);
 
 free_bus_local: