msm: camera: resource manager related changes.

Make changes to support dynamic selection
of subdevs through the resource manager. Instead of
choosing the subdevs to be used by the current mctl
session statically during open, the VFE, AXI and VPE
subdevs are now selected and initialized later as per
session requirements.

Change-Id: I8df951b81f0ccc77e5b4f64bf5cf620822cf0175
Signed-off-by: Ankit Premrajka <ankitp@codeaurora.org>
diff --git a/drivers/media/video/msm/csi/msm_csi2_register.c b/drivers/media/video/msm/csi/msm_csi2_register.c
index 7b85ded..aa539ff 100644
--- a/drivers/media/video/msm/csi/msm_csi2_register.c
+++ b/drivers/media/video/msm/csi/msm_csi2_register.c
@@ -16,48 +16,28 @@
 #include "msm_csi_register.h"
 
 int msm_csi_register_subdevs(struct msm_cam_media_controller *p_mctl,
-	int core_index,
-	int (*msm_mctl_subdev_match_core)(struct device *, void *))
+	int core_index, struct msm_cam_server_dev *server_dev)
 {
 	int rc = -ENODEV;
-	struct device_driver *driver;
-	struct device *dev;
 
 	/* register csiphy subdev */
-	driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
-	if (!driver)
+	p_mctl->csiphy_sdev = server_dev->csiphy_device[core_index];
+	if (!p_mctl->csiphy_sdev)
 		goto out;
-
-	dev = driver_find_device(driver, NULL, (void *)core_index,
-			msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out;
-
-	p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+	v4l2_set_subdev_hostdata(p_mctl->csiphy_sdev, p_mctl);
 
 	/* register csid subdev */
-	driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
-	if (!driver)
+	p_mctl->csid_sdev = server_dev->csid_device[core_index];
+	if (!p_mctl->csid_sdev)
 		goto out;
-
-	dev = driver_find_device(driver, NULL, (void *)core_index,
-			msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out;
-
-	p_mctl->csid_sdev = dev_get_drvdata(dev);
+	v4l2_set_subdev_hostdata(p_mctl->csid_sdev, p_mctl);
 
 	/* register ispif subdev */
-	driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
-	if (!driver)
+	p_mctl->ispif_sdev = server_dev->ispif_device[0];
+	if (!p_mctl->ispif_sdev)
 		goto out;
+	v4l2_set_subdev_hostdata(p_mctl->ispif_sdev, p_mctl);
 
-	dev = driver_find_device(driver, NULL, 0,
-			msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out;
-
-	p_mctl->ispif_sdev = dev_get_drvdata(dev);
 	rc = 0;
 	return rc;
 out:
diff --git a/drivers/media/video/msm/csi/msm_csi_register.h b/drivers/media/video/msm/csi/msm_csi_register.h
index 578b609..ebb001c 100644
--- a/drivers/media/video/msm/csi/msm_csi_register.h
+++ b/drivers/media/video/msm/csi/msm_csi_register.h
@@ -13,4 +13,4 @@
 
 int msm_csi_register_subdevs(struct msm_cam_media_controller *p_mctl,
 	int core_index,
-	int (*msm_mctl_subdev_match_core)(struct device *, void *));
+	struct msm_cam_server_dev *server_dev);
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index dbb4f32..bcb7bb3 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -463,6 +463,12 @@
 	msm_cam_register_subdev_node(
 		&new_csic_dev->subdev, &sd_info);
 
+	media_entity_init(&new_csic_dev->subdev.entity, 0, NULL, 0);
+	new_csic_dev->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	new_csic_dev->subdev.entity.group_id = CSIC_DEV;
+	new_csic_dev->subdev.entity.name = pdev->name;
+	new_csic_dev->subdev.entity.revision =
+		new_csic_dev->subdev.devnode->num;
 	return 0;
 
 csic_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csic_register.c b/drivers/media/video/msm/csi/msm_csic_register.c
index 7ccaff2..dc3641a 100644
--- a/drivers/media/video/msm/csi/msm_csic_register.c
+++ b/drivers/media/video/msm/csi/msm_csic_register.c
@@ -16,23 +16,14 @@
 #include "msm_csi_register.h"
 
 int msm_csi_register_subdevs(struct msm_cam_media_controller *p_mctl,
-	int core_index,
-	int (*msm_mctl_subdev_match_core)(struct device *, void *))
+	int core_index, struct msm_cam_server_dev *server_dev)
 {
 	int rc = -ENODEV;
-	struct device_driver *driver;
-	struct device *dev;
 
-	driver = driver_find(MSM_CSIC_DRV_NAME, &platform_bus_type);
-	if (!driver)
+	p_mctl->csic_sdev = server_dev->csic_device[core_index];
+	if (!p_mctl->csic_sdev)
 		goto out;
-
-	dev = driver_find_device(driver, NULL, (void *)core_index,
-			msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out;
-
-	p_mctl->csic_sdev = dev_get_drvdata(dev);
+	v4l2_set_subdev_hostdata(p_mctl->csic_sdev, p_mctl);
 
 	rc = 0;
 	p_mctl->ispif_sdev = NULL;
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 962c60e..6ee87b7 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -320,6 +320,13 @@
 	sd_info.sd_index = pdev->id;
 	sd_info.irq_num = new_csid_dev->irq->start;
 	msm_cam_register_subdev_node(&new_csid_dev->subdev, &sd_info);
+
+	media_entity_init(&new_csid_dev->subdev.entity, 0, NULL, 0);
+	new_csid_dev->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	new_csid_dev->subdev.entity.group_id = CSID_DEV;
+	new_csid_dev->subdev.entity.name = pdev->name;
+	new_csid_dev->subdev.entity.revision =
+		new_csid_dev->subdev.devnode->num;
 	return 0;
 
 csid_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index c524884..bec7ae3 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -341,6 +341,13 @@
 	sd_info.irq_num = new_csiphy_dev->irq->start;
 	msm_cam_register_subdev_node(
 		&new_csiphy_dev->subdev, &sd_info);
+
+	media_entity_init(&new_csiphy_dev->subdev.entity, 0, NULL, 0);
+	new_csiphy_dev->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	new_csiphy_dev->subdev.entity.group_id = CSIPHY_DEV;
+	new_csiphy_dev->subdev.entity.name = pdev->name;
+	new_csiphy_dev->subdev.entity.revision =
+		new_csiphy_dev->subdev.devnode->num;
 	return 0;
 
 csiphy_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index 0f16bbf..1494644 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -517,7 +517,6 @@
 		if (rc < 0)
 			return rc;
 	}
-
 	rc = msm_ispif_reset();
 	return rc;
 }
@@ -693,6 +692,12 @@
 	sd_info.sd_index = pdev->id;
 	sd_info.irq_num = ispif->irq->start;
 	msm_cam_register_subdev_node(&ispif->subdev, &sd_info);
+
+	media_entity_init(&ispif->subdev.entity, 0, NULL, 0);
+	ispif->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	ispif->subdev.entity.group_id = ISPIF_DEV;
+	ispif->subdev.entity.name = pdev->name;
+	ispif->subdev.entity.revision = ispif->subdev.devnode->num;
 	return 0;
 
 ispif_no_mem:
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index b67af4f..d9ede7a 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1201,7 +1201,7 @@
 	pvdev->fops	     = &g_msm_fops;
 	pvdev->ioctl_ops = &g_msm_ioctl_ops;
 	pvdev->minor	 = -1;
-	pvdev->vfl_type  = 1;
+	pvdev->vfl_type  = VFL_TYPE_GRABBER;
 
 	media_entity_init(&pvdev->entity, 0, NULL, 0);
 	pvdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 08278ff..5fc2f68 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -61,6 +61,7 @@
 #define MSM_IRQ_ROUTER_DRV_NAME "msm_cam_irq_router"
 #define MSM_CPP_DRV_NAME "msm_cpp"
 
+#define MAX_NUM_SENSOR_DEV 3
 #define MAX_NUM_CSIPHY_DEV 3
 #define MAX_NUM_CSID_DEV 4
 #define MAX_NUM_CSIC_DEV 3
@@ -71,22 +72,6 @@
 #define MAX_NUM_JPEG_DEV 3
 #define MAX_NUM_CPP_DEV 1
 
-enum msm_cam_subdev_type {
-	CSIPHY_DEV,
-	CSID_DEV,
-	CSIC_DEV,
-	ISPIF_DEV,
-	VFE_DEV,
-	AXI_DEV,
-	VPE_DEV,
-	SENSOR_DEV,
-	ACTUATOR_DEV,
-	EEPROM_DEV,
-	GESTURE_DEV,
-	IRQ_ROUTER_DEV,
-	CPP_DEV,
-};
-
 /* msm queue management APIs*/
 
 #define msm_dequeue(queue, member) ({	   \
@@ -315,7 +300,6 @@
 
 	/* vfe subdevice */
 	struct v4l2_subdev *sd;
-	struct v4l2_subdev *sd_vpe;
 };
 
 struct msm_isp_buf_info {
@@ -540,10 +524,11 @@
 	struct mutex server_lock;
 	struct mutex server_queue_lock;
 	/*v4l2 subdevs*/
+	struct v4l2_subdev *sensor_device[MAX_NUM_SENSOR_DEV];
 	struct v4l2_subdev *csiphy_device[MAX_NUM_CSIPHY_DEV];
 	struct v4l2_subdev *csid_device[MAX_NUM_CSID_DEV];
 	struct v4l2_subdev *csic_device[MAX_NUM_CSIC_DEV];
-	struct v4l2_subdev *ispif_device;
+	struct v4l2_subdev *ispif_device[MAX_NUM_ISPIF_DEV];
 	struct v4l2_subdev *vfe_device[MAX_NUM_VFE_DEV];
 	struct v4l2_subdev *axi_device[MAX_NUM_AXI_DEV];
 	struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
@@ -608,14 +593,12 @@
 	struct msm_cam_media_controller *mctl,
 	unsigned long addr, int *fd);
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl);
+int msm_vfe_subdev_init(struct v4l2_subdev *sd);
 void msm_vfe_subdev_release(struct v4l2_subdev *sd);
 
 int msm_isp_subdev_ioctl(struct v4l2_subdev *sd,
 	struct msm_vfe_cfg_cmd *cfgcmd, void *data);
-int msm_vpe_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl);
+int msm_vpe_subdev_init(struct v4l2_subdev *sd);
 int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
 void msm_vpe_subdev_release(void);
 void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
@@ -676,6 +659,8 @@
 void msm_release_ion_client(struct kref *ref);
 int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
 	struct msm_cam_subdev_info *sd_info);
+int msm_mctl_find_sensor_subdevs(struct msm_cam_media_controller *p_mctl,
+	int core_index);
 int msm_server_open_client(int *p_qidx);
 int msm_server_send_ctrl(struct msm_ctrl_cmd *out, int ctrl_id);
 int msm_server_close_client(int idx);
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 5fcb62b..9e1d9c1 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -498,32 +498,8 @@
 		return -EINVAL;
 	}
 
-	rc = msm_iommu_map_contig_buffer(
-		(unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
-		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
-		SZ_4K, IOMMU_WRITE | IOMMU_READ,
-		(unsigned long *)&mctl->ping_imem_y);
-	mctl->ping_imem_cbcr = mctl->ping_imem_y + IMEM_Y_SIZE;
-	if (rc < 0) {
-		pr_err("%s: ping iommu mapping returned error %d\n",
-			__func__, rc);
-		mctl->ping_imem_y = 0;
-		mctl->ping_imem_cbcr = 0;
-	}
-	msm_iommu_map_contig_buffer(
-		(unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
-		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
-		SZ_4K, IOMMU_WRITE | IOMMU_READ,
-		(unsigned long *)&mctl->pong_imem_y);
-	mctl->pong_imem_cbcr = mctl->pong_imem_y + IMEM_Y_SIZE;
-	if (rc < 0) {
-		pr_err("%s: pong iommu mapping returned error %d\n",
-			 __func__, rc);
-		mctl->pong_imem_y = 0;
-		mctl->pong_imem_cbcr = 0;
-	}
-
-	rc = msm_vfe_subdev_init(sd, mctl);
+	rc = v4l2_subdev_call(sd, core, ioctl,
+				VIDIOC_MSM_VFE_INIT, NULL);
 	if (rc < 0) {
 		pr_err("%s: vfe_init failed at %d\n",
 			__func__, rc);
@@ -535,17 +511,8 @@
 	struct v4l2_subdev *sd)
 {
 	D("%s\n", __func__);
-	msm_vfe_subdev_release(sd);
-	msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
-		CAMERA_DOMAIN, GEN_POOL,
-		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
-	msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
-		CAMERA_DOMAIN, GEN_POOL,
-		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
-	mctl->ping_imem_y = 0;
-	mctl->ping_imem_cbcr = 0;
-	mctl->pong_imem_y = 0;
-	mctl->pong_imem_cbcr = 0;
+	v4l2_subdev_call(sd, core, ioctl,
+				VIDIOC_MSM_VFE_RELEASE, NULL);
 }
 
 static int msm_config_vfe(struct v4l2_subdev *sd,
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index be4cb41..0a61b69 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -418,94 +418,6 @@
 	return rc;
 }
 
-static int msm_mctl_subdev_match_core(struct device *dev, void *data)
-{
-	int core_index = (int)data;
-	struct platform_device *pdev = to_platform_device(dev);
-
-	if (pdev->id == core_index)
-		return 1;
-	else
-		return 0;
-}
-
-static int msm_mctl_register_subdevs(struct msm_cam_media_controller *p_mctl,
-	int core_index)
-{
-	struct device_driver *driver;
-	struct device *dev;
-	int rc = -ENODEV;
-
-	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
-	struct msm_camera_sensor_info *sinfo =
-		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
-	struct msm_camera_device_platform_data *pdata = sinfo->pdata;
-
-	rc = msm_csi_register_subdevs(p_mctl, core_index,
-				msm_mctl_subdev_match_core);
-
-	if (rc < 0)
-			goto out;
-
-	/* register vfe subdev */
-	driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
-	if (!driver)
-		goto out;
-
-	dev = driver_find_device(driver, NULL, 0,
-				msm_mctl_subdev_match_core);
-	if (!dev)
-		goto out;
-
-	p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
-
-	if (pdata->is_vpe) {
-		/* register vfe subdev */
-		driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
-		if (!driver)
-			goto out;
-
-		dev = driver_find_device(driver, NULL, 0,
-				msm_mctl_subdev_match_core);
-		if (!dev)
-			goto out;
-
-		p_mctl->vpe_sdev = dev_get_drvdata(dev);
-	}
-
-	rc = 0;
-
-
-	/* register gemini subdev */
-	driver = driver_find(MSM_GEMINI_DRV_NAME, &platform_bus_type);
-	if (!driver) {
-		pr_err("%s:%d:Gemini: Failure: goto out\n",
-			__func__, __LINE__);
-		goto out;
-	}
-	pr_debug("%s:%d:Gemini: driver_find_device Gemini driver 0x%x\n",
-		__func__, __LINE__, (uint32_t)driver);
-	dev = driver_find_device(driver, NULL, NULL,
-				msm_mctl_subdev_match_core);
-	if (!dev) {
-		pr_err("%s:%d:Gemini: Failure goto out\n",
-			__func__, __LINE__);
-		goto out;
-	}
-	p_mctl->gemini_sdev = dev_get_drvdata(dev);
-	pr_debug("%s:%d:Gemini: After dev_get_drvdata gemini_sdev=0x%x\n",
-		__func__, __LINE__, (uint32_t)p_mctl->gemini_sdev);
-
-	if (p_mctl->gemini_sdev == NULL) {
-		pr_err("%s:%d:Gemini: Failure gemini_sdev is null\n",
-			__func__, __LINE__);
-		goto out;
-	}
-	rc = 0;
-out:
-	return rc;
-}
-
 static int msm_mctl_open(struct msm_cam_media_controller *p_mctl,
 				 const char *const apps_id)
 {
@@ -529,9 +441,9 @@
 		wake_lock(&p_mctl->wake_lock);
 
 		csid_core = camdev->csid_core;
-		rc = msm_mctl_register_subdevs(p_mctl, csid_core);
+		rc = msm_mctl_find_sensor_subdevs(p_mctl, csid_core);
 		if (rc < 0) {
-			pr_err("%s: msm_mctl_register_subdevs failed:%d\n",
+			pr_err("%s: msm_mctl_find_sensor_subdevs failed:%d\n",
 				__func__, rc);
 			goto register_sdev_failed;
 		}
@@ -592,38 +504,6 @@
 			goto msm_csi_version;
 		}
 
-		/* ISP first*/
-		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open) {
-			rc = p_mctl->isp_sdev->isp_open(
-				p_mctl->isp_sdev->sd, p_mctl);
-			if (rc < 0) {
-				pr_err("%s: isp init failed: %d\n",
-					__func__, rc);
-				goto isp_open_failed;
-			}
-		}
-
-		if (p_mctl->axi_sdev) {
-			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
-				VIDIOC_MSM_AXI_INIT, p_mctl);
-			if (rc < 0) {
-				pr_err("%s: axi initialization failed %d\n",
-					__func__, rc);
-				goto axi_init_failed;
-			}
-		}
-
-		if (camdev->is_vpe) {
-			rc = v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
-				VIDIOC_MSM_VPE_INIT, p_mctl);
-			if (rc < 0) {
-				pr_err("%s: vpe initialization failed %d\n",
-				__func__, rc);
-				goto vpe_init_failed;
-			}
-		}
-
-
 		pm_qos_add_request(&p_mctl->pm_qos_req_list,
 			PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 		pm_qos_update_request(&p_mctl->pm_qos_req_list,
@@ -635,19 +515,9 @@
 		D("%s: camera is already open", __func__);
 	}
 	mutex_unlock(&p_mctl->lock);
-
 	return rc;
 
-vpe_init_failed:
-	if (p_mctl->axi_sdev)
-		if (v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
-			VIDIOC_MSM_AXI_RELEASE, NULL) < 0)
-			pr_err("%s: axi release failed %d\n", __func__, rc);
-axi_init_failed:
-	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
-		p_mctl->isp_sdev->isp_release(p_mctl, p_mctl->isp_sdev->sd);
 msm_csi_version:
-isp_open_failed:
 	if (p_mctl->csic_sdev)
 		if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
 			VIDIOC_MSM_CSIC_RELEASE, NULL) < 0)
@@ -684,7 +554,6 @@
 	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
 	struct msm_camera_sensor_info *sinfo =
 		(struct msm_camera_sensor_info *) s_ctrl->sensordata;
-	struct msm_camera_device_platform_data *camdev = sinfo->pdata;
 
 	v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
 		VIDIOC_MSM_SENSOR_RELEASE, NULL);
@@ -694,7 +563,7 @@
 			VIDIOC_MSM_CSIC_RELEASE, NULL);
 	}
 
-	if (camdev->is_vpe) {
+	if (p_mctl->vpe_sdev) {
 		v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
 			VIDIOC_MSM_VPE_RELEASE, NULL);
 	}
@@ -704,7 +573,8 @@
 			VIDIOC_MSM_AXI_RELEASE, NULL);
 	}
 
-	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
+	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release
+		&& p_mctl->isp_sdev->sd)
 		p_mctl->isp_sdev->isp_release(p_mctl,
 			p_mctl->isp_sdev->sd);
 
@@ -832,6 +702,7 @@
 	pmctl->eeprom_sdev = pcam->eeprom_sdev;
 	pmctl->sensor_sdev = pcam->sensor_sdev;
 	pmctl->sdata = pcam->sdata;
+	v4l2_set_subdev_hostdata(pcam->sensor_sdev, pmctl);
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	pmctl->client = msm_ion_client_create(-1, "camera");
@@ -855,6 +726,8 @@
 
 	mutex_destroy(&pmctl->lock);
 	wake_lock_destroy(&pmctl->wake_lock);
+	/*clear out mctl fields*/
+	memset(pmctl, 0, sizeof(struct msm_cam_media_controller));
 	msm_cam_server_free_mctl(pcam->mctl_handle);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index b520a92..71bce67 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -3541,15 +3541,25 @@
 	struct msm_cam_media_controller *pmctl =
 		(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
 	struct msm_isp_cmd vfecmd;
-	struct msm_camvfe_params *vfe_params =
-		(struct msm_camvfe_params *)arg;
-	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
-	void *data = vfe_params->data;
+	struct msm_camvfe_params *vfe_params;
+	struct msm_vfe_cfg_cmd *cmd;
+	void *data;
 
 	long rc = 0;
 	struct vfe_cmd_stats_buf *scfg = NULL;
 	struct vfe_cmd_stats_ack *sack = NULL;
 
+	if (subdev_cmd == VIDIOC_MSM_VFE_INIT) {
+		CDBG("%s init\n", __func__);
+		return msm_vfe_subdev_init(sd);
+	} else if (subdev_cmd == VIDIOC_MSM_VFE_RELEASE) {
+		msm_vfe_subdev_release(sd);
+		return 0;
+	}
+	vfe_params = (struct msm_camvfe_params *)arg;
+	cmd = vfe_params->vfe_cfg;
+	data = vfe_params->data;
+
 	switch (cmd->cmd_type) {
 	case VFE_CMD_STATS_REQBUF:
 	case VFE_CMD_STATS_ENQUEUEBUF:
@@ -3575,186 +3585,190 @@
 					return -EFAULT;
 				}
 		} else {
-		/* here eith stats release or frame release. */
-		if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
-			cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
-			cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR) {
-			/* then must be stats release. */
-			if (!data) {
-				pr_err("%s: data = NULL, cmd->cmd_type = %d",
-					__func__, cmd->cmd_type);
-				return -EFAULT;
-			}
-			sack = kmalloc(sizeof(struct vfe_cmd_stats_ack),
+			/* here eith stats release or frame release. */
+			if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+				cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+				cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR) {
+				/* then must be stats release. */
+				if (!data) {
+					pr_err("%s: data = NULL," \
+						"cmd->cmd_type = %d\n",
+						__func__, cmd->cmd_type);
+					return -EFAULT;
+				}
+				sack = kmalloc(sizeof(struct vfe_cmd_stats_ack),
 							GFP_ATOMIC);
-			if (!sack) {
-				pr_err("%s: no mem for cmd->cmd_type = %d",
-					 __func__, cmd->cmd_type);
-				return -ENOMEM;
+				if (!sack) {
+					pr_err("%s: no mem for" \
+						"cmd->cmd_type = %d\n",
+						__func__, cmd->cmd_type);
+					return -ENOMEM;
+				}
+
+				sack->nextStatsBuf = *(uint32_t *)data;
+			}
+		}
+
+		CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
+
+		if ((cmd->cmd_type == CMD_STATS_AF_ENABLE)    ||
+			(cmd->cmd_type == CMD_STATS_AWB_ENABLE)   ||
+			(cmd->cmd_type == CMD_STATS_IHIST_ENABLE) ||
+			(cmd->cmd_type == CMD_STATS_RS_ENABLE)    ||
+			(cmd->cmd_type == CMD_STATS_CS_ENABLE)    ||
+			(cmd->cmd_type == CMD_STATS_AEC_ENABLE)) {
+			scfg = NULL;
+			goto vfe31_config_done;
+		}
+		switch (cmd->cmd_type) {
+		case CMD_GENERAL: {
+			rc = vfe31_proc_general(pmctl, &vfecmd);
+			}
+			break;
+		case CMD_CONFIG_PING_ADDR: {
+			int path = *((int *)cmd->value);
+			struct vfe31_output_ch *outch = vfe31_get_ch(path);
+			outch->ping = *((struct msm_free_buf *)data);
+			}
+			break;
+
+		case CMD_CONFIG_PONG_ADDR: {
+			int path = *((int *)cmd->value);
+			struct vfe31_output_ch *outch = vfe31_get_ch(path);
+			outch->pong = *((struct msm_free_buf *)data);
+			}
+			break;
+
+		case CMD_CONFIG_FREE_BUF_ADDR: {
+			int path = *((int *)cmd->value);
+			struct vfe31_output_ch *outch = vfe31_get_ch(path);
+			outch->free_buf = *((struct msm_free_buf *)data);
+			}
+			break;
+
+		case CMD_SNAP_BUF_RELEASE:
+			break;
+
+		case CMD_AXI_CFG_PRIM: {
+			uint32_t *axio = NULL;
+			axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+				GFP_ATOMIC);
+			if (!axio) {
+				rc = -ENOMEM;
+				break;
 			}
 
-			sack->nextStatsBuf = *(uint32_t *)data;
-		}
-	  }
-
-	CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
-
-	if ((cmd->cmd_type == CMD_STATS_AF_ENABLE)    ||
-		(cmd->cmd_type == CMD_STATS_AWB_ENABLE)   ||
-		(cmd->cmd_type == CMD_STATS_IHIST_ENABLE) ||
-		(cmd->cmd_type == CMD_STATS_RS_ENABLE)    ||
-		(cmd->cmd_type == CMD_STATS_CS_ENABLE)    ||
-		(cmd->cmd_type == CMD_STATS_AEC_ENABLE)) {
-		scfg = NULL;
-		goto vfe31_config_done;
-	}
-	switch (cmd->cmd_type) {
-	case CMD_GENERAL: {
-		rc = vfe31_proc_general(pmctl, &vfecmd);
-		}
-		break;
-	case CMD_CONFIG_PING_ADDR: {
-		int path = *((int *)cmd->value);
-		struct vfe31_output_ch *outch = vfe31_get_ch(path);
-		outch->ping = *((struct msm_free_buf *)data);
-		}
-		break;
-
-	case CMD_CONFIG_PONG_ADDR: {
-		int path = *((int *)cmd->value);
-		struct vfe31_output_ch *outch = vfe31_get_ch(path);
-		outch->pong = *((struct msm_free_buf *)data);
-		}
-		break;
-
-	case CMD_CONFIG_FREE_BUF_ADDR: {
-		int path = *((int *)cmd->value);
-		struct vfe31_output_ch *outch = vfe31_get_ch(path);
-		outch->free_buf = *((struct msm_free_buf *)data);
-		}
-		break;
-
-	case CMD_SNAP_BUF_RELEASE:
-		break;
-
-	case CMD_AXI_CFG_PRIM: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
-				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
-
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+			if (copy_from_user(axio, (void __user *)(vfecmd.value),
 				vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+				kfree(axio);
+				rc = -EFAULT;
+				break;
+			}
+			vfe31_config_axi(OUTPUT_PRIM, axio);
 			kfree(axio);
-			rc = -EFAULT;
+			}
 			break;
-		}
-		vfe31_config_axi(OUTPUT_PRIM, axio);
-		kfree(axio);
-		}
-		break;
 
-	case CMD_AXI_CFG_PRIM_ALL_CHNLS: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
-				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
+		case CMD_AXI_CFG_PRIM_ALL_CHNLS: {
+			uint32_t *axio = NULL;
+			axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+					GFP_ATOMIC);
+			if (!axio) {
+				rc = -ENOMEM;
+				break;
+			}
 
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+			if (copy_from_user(axio, (void __user *)(vfecmd.value),
 				vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+				kfree(axio);
+				rc = -EFAULT;
+				break;
+			}
+			vfe31_config_axi(OUTPUT_PRIM_ALL_CHNLS, axio);
 			kfree(axio);
-			rc = -EFAULT;
+		}
 			break;
-		}
-		vfe31_config_axi(OUTPUT_PRIM_ALL_CHNLS, axio);
-		kfree(axio);
-		}
-		break;
 
-	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
-				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
+		case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC: {
+			uint32_t *axio = NULL;
+			axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+					GFP_ATOMIC);
+			if (!axio) {
+				rc = -ENOMEM;
+				break;
+			}
 
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+			if (copy_from_user(axio, (void __user *)(vfecmd.value),
 				vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+				kfree(axio);
+				rc = -EFAULT;
+				break;
+			}
+			vfe31_config_axi(OUTPUT_PRIM|OUTPUT_SEC, axio);
 			kfree(axio);
-			rc = -EFAULT;
+			}
 			break;
-		}
-		vfe31_config_axi(OUTPUT_PRIM|OUTPUT_SEC, axio);
-		kfree(axio);
-		}
-		break;
 
-	case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
-				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
+		case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS: {
+			uint32_t *axio = NULL;
+			axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+					GFP_ATOMIC);
+			if (!axio) {
+				rc = -ENOMEM;
+				break;
+			}
 
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+			if (copy_from_user(axio, (void __user *)(vfecmd.value),
 				vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+				kfree(axio);
+				rc = -EFAULT;
+				break;
+			}
+			vfe31_config_axi
+				(OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
 			kfree(axio);
-			rc = -EFAULT;
+			}
 			break;
-		}
-		vfe31_config_axi(OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
-		kfree(axio);
-		}
-		break;
 
-	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC: {
-		uint32_t *axio = NULL;
-		axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+		case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC: {
+			uint32_t *axio = NULL;
+			axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
 				GFP_ATOMIC);
-		if (!axio) {
-			rc = -ENOMEM;
-			break;
-		}
+			if (!axio) {
+				rc = -ENOMEM;
+				break;
+			}
 
-		if (copy_from_user(axio, (void __user *)(vfecmd.value),
+			if (copy_from_user(axio, (void __user *)(vfecmd.value),
 				vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+				kfree(axio);
+				rc = -EFAULT;
+				break;
+			}
+			vfe31_config_axi
+				(OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
 			kfree(axio);
-			rc = -EFAULT;
+			}
 			break;
-		}
-		vfe31_config_axi(OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
-		kfree(axio);
-		}
-		break;
 
-	case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS: {
-		pr_err("%s Invalid/Unsupported AXI configuration %x",
-			__func__, cmd->cmd_type);
-		}
-		break;
+		case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS: {
+			pr_err("%s Invalid/Unsupported AXI configuration %x",
+				__func__, cmd->cmd_type);
+			}
+			break;
 
-	case CMD_AXI_START:
-		/* No need to decouple AXI/VFE for VFE3.1*/
-		break;
+		case CMD_AXI_START:
+			/* No need to decouple AXI/VFE for VFE3.1*/
+			break;
 
-	case CMD_AXI_STOP:
-		/* No need to decouple AXI/VFE for VFE3.1*/
-		break;
+		case CMD_AXI_STOP:
+			/* No need to decouple AXI/VFE for VFE3.1*/
+			break;
 
-	default:
-		pr_err("%s Unsupported AXI configuration %x ", __func__,
-			cmd->cmd_type);
-		break;
+		default:
+			pr_err("%s Unsupported AXI configuration %x ", __func__,
+				cmd->cmd_type);
+			break;
 		}
 	}
 vfe31_config_done:
@@ -3855,11 +3869,15 @@
 	usleep_range(10000, 15000);
 }
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
-		struct msm_cam_media_controller *mctl)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
-	v4l2_set_subdev_hostdata(sd, mctl);
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
+	if (mctl == NULL) {
+		rc = -EINVAL;
+		goto mctl_failed;
+	}
 
 	spin_lock_init(&vfe31_ctrl->stop_flag_lock);
 	spin_lock_init(&vfe31_ctrl->state_lock);
@@ -3939,6 +3957,7 @@
 	iounmap(vfe31_ctrl->vfebase);
 vfe_remap_failed:
 	disable_irq(vfe31_ctrl->vfeirq->start);
+mctl_failed:
 	return rc;
 }
 
@@ -4064,6 +4083,12 @@
 	sd_info.sd_index = 0;
 	sd_info.irq_num = vfe31_ctrl->vfeirq->start;
 	msm_cam_register_subdev_node(&vfe31_ctrl->subdev, &sd_info);
+
+	media_entity_init(&vfe31_ctrl->subdev.entity, 0, NULL, 0);
+	vfe31_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	vfe31_ctrl->subdev.entity.group_id = VFE_DEV;
+	vfe31_ctrl->subdev.entity.name = pdev->name;
+	vfe31_ctrl->subdev.entity.revision = vfe31_ctrl->subdev.devnode->num;
 	return 0;
 
 vfe31_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 9343c21..cbe1f15 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4519,10 +4519,9 @@
 	struct vfe32_ctrl_type *vfe32_ctrl =
 		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
 	struct msm_isp_cmd vfecmd;
-	struct msm_camvfe_params *vfe_params =
-		(struct msm_camvfe_params *)arg;
-	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
-	void *data = vfe_params->data;
+	struct msm_camvfe_params *vfe_params;
+	struct msm_vfe_cfg_cmd *cmd;
+	void *data;
 
 	long rc = 0;
 	struct vfe_cmd_stats_buf *scfg = NULL;
@@ -4533,6 +4532,17 @@
 		return -EFAULT;
 	}
 
+	CDBG("%s\n", __func__);
+	if (subdev_cmd == VIDIOC_MSM_VFE_INIT) {
+		CDBG("%s init\n", __func__);
+		return msm_vfe_subdev_init(sd);
+	} else if (subdev_cmd == VIDIOC_MSM_VFE_RELEASE) {
+		msm_vfe_subdev_release(sd);
+		return 0;
+	}
+	vfe_params = (struct msm_camvfe_params *)arg;
+	cmd = vfe_params->vfe_cfg;
+	data = vfe_params->data;
 	switch (cmd->cmd_type) {
 	case CMD_VFE_PROCESS_IRQ:
 		vfe32_process_irq(vfe32_ctrl, (uint32_t) data);
@@ -4672,12 +4682,17 @@
 	.core = &msm_vfe_subdev_core_ops,
 };
 
-int msm_axi_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl)
+int msm_axi_subdev_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
 	struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
-	v4l2_set_subdev_hostdata(sd, mctl);
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
+	if (mctl == NULL) {
+		pr_err("%s: mctl is NULL\n", __func__);
+		rc = -EINVAL;
+		goto mctl_failed;
+	}
 	spin_lock_init(&axi_ctrl->tasklet_lock);
 	INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
 	spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
@@ -4725,16 +4740,15 @@
 	axi_ctrl->share_ctrl->vfebase = NULL;
 remap_failed:
 	disable_irq(axi_ctrl->vfeirq->start);
+mctl_failed:
 	return rc;
 }
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
 	struct vfe32_ctrl_type *vfe32_ctrl =
 		(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
-	v4l2_set_subdev_hostdata(sd, mctl);
 
 	spin_lock_init(&vfe32_ctrl->share_ctrl->stop_flag_lock);
 	spin_lock_init(&vfe32_ctrl->state_lock);
@@ -5202,8 +5216,7 @@
 	int rc = -ENOIOCTLCMD;
 	switch (cmd) {
 	case VIDIOC_MSM_AXI_INIT:
-		rc = msm_axi_subdev_init(sd,
-			(struct msm_cam_media_controller *)arg);
+		rc = msm_axi_subdev_init(sd);
 		break;
 	case VIDIOC_MSM_AXI_CFG:
 		rc = msm_axi_config(sd, arg);
@@ -5292,6 +5305,12 @@
 	sd_info.irq_num = 0;
 	msm_cam_register_subdev_node(&axi_ctrl->subdev, &sd_info);
 
+	media_entity_init(&axi_ctrl->subdev.entity, 0, NULL, 0);
+	axi_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	axi_ctrl->subdev.entity.group_id = AXI_DEV;
+	axi_ctrl->subdev.entity.name = pdev->name;
+	axi_ctrl->subdev.entity.revision = axi_ctrl->subdev.devnode->num;
+
 	v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
 	vfe32_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
 	vfe32_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -5337,6 +5356,12 @@
 	sd_info.irq_num = axi_ctrl->vfeirq->start;
 	msm_cam_register_subdev_node(&vfe32_ctrl->subdev, &sd_info);
 
+	media_entity_init(&vfe32_ctrl->subdev.entity, 0, NULL, 0);
+	vfe32_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	vfe32_ctrl->subdev.entity.group_id = VFE_DEV;
+	vfe32_ctrl->subdev.entity.name = pdev->name;
+	vfe32_ctrl->subdev.entity.revision = vfe32_ctrl->subdev.devnode->num;
+
 	/* Request for this device irq from the camera server. If the
 	 * IRQ Router is present on this target, the interrupt will be
 	 * handled by the camera server and the interrupt service
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 2c528da..3196eda 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -1028,19 +1028,4 @@
 	uint32_t statsBuf[VFE_STATS_BUFFER_COUNT];
 };
 
-#define VIDIOC_MSM_AXI_INIT \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 18, struct msm_cam_media_controller *)
-
-#define VIDIOC_MSM_AXI_RELEASE \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 19, struct msm_cam_media_controller *)
-
-#define VIDIOC_MSM_AXI_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 20, void *)
-
-#define VIDIOC_MSM_AXI_IRQ \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 21, void *)
-
-#define VIDIOC_MSM_AXI_BUF_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 22, void *)
-
 #endif /* __MSM_VFE32_H__ */
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 96047d5..3701331 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -1182,12 +1182,11 @@
 			unsigned int subdev_cmd, void *arg)
 {
 	struct msm_isp_cmd vfecmd;
-	struct msm_camvfe_params *vfe_params =
-		(struct msm_camvfe_params *)arg;
-	struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+	struct msm_camvfe_params *vfe_params;
+	struct msm_vfe_cfg_cmd *cmd;
 	struct table_cmd *table_pending;
 	long rc = 0;
-	void *data = vfe_params->data;
+	void *data;
 
 	struct msm_pmem_region *regptr;
 	unsigned char buf[256];
@@ -1208,6 +1207,18 @@
 	struct vfe_outputack fack;
 
 	CDBG("msm_vfe_subdev_ioctl is called\n");
+	if (subdev_cmd == VIDIOC_MSM_VFE_INIT) {
+		CDBG("%s init\n", __func__);
+		return msm_vfe_subdev_init(sd);
+	} else if (subdev_cmd == VIDIOC_MSM_VFE_RELEASE) {
+		msm_vfe_subdev_release(sd);
+		return 0;
+	}
+
+	vfe_params = (struct msm_camvfe_params *)arg;
+	cmd = vfe_params->vfe_cfg;
+	data = vfe_params->data;
+
 	if (cmd->cmd_type != CMD_FRAME_BUF_RELEASE &&
 		cmd->cmd_type != CMD_STATS_BUF_RELEASE &&
 		cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE &&
@@ -1954,11 +1965,16 @@
 	{"vfe_clk", 192000000},
 };
 
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
-		struct msm_cam_media_controller *mctl)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
-	v4l2_set_subdev_hostdata(sd, mctl);
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
+	if (mctl == NULL) {
+		pr_err("%s: mctl is NULL\n", __func__);
+		rc = -EINVAL;
+		goto mctl_failed;
+	}
 
 	spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
 	spin_lock_init(&vfe2x_ctrl->table_lock);
@@ -2011,11 +2027,11 @@
 	kfree(extdata);
 init_fail:
 	extlen = 0;
+mctl_failed:
 	return rc;
 }
 
-int msm_vpe_subdev_init(struct v4l2_subdev *sd,
-			struct msm_cam_media_controller *mctl)
+int msm_vpe_subdev_init(struct v4l2_subdev *sd)
 {
 	return 0;
 }
@@ -2101,6 +2117,12 @@
 	sd_info.sd_index = 0;
 	sd_info.irq_num = 0;
 	msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, &sd_info);
+
+	media_entity_init(&vfe2x_ctrl->subdev.entity, 0, NULL, 0);
+	vfe2x_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	vfe2x_ctrl->subdev.entity.group_id = VFE_DEV;
+	vfe2x_ctrl->subdev.entity.name = pdev->name;
+	vfe2x_ctrl->subdev.entity.revision = vfe2x_ctrl->subdev.devnode->num;
 	return 0;
 }
 
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 2b58f44..58fc153 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -603,10 +603,11 @@
 
 static int msm_vpe_resource_init(void);
 
-int msm_vpe_subdev_init(struct v4l2_subdev *sd,
-		struct msm_cam_media_controller *mctl)
+int msm_vpe_subdev_init(struct v4l2_subdev *sd)
 {
 	int rc = 0;
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	D("%s:begin", __func__);
 	if (atomic_read(&vpe_init_done)) {
 		pr_err("%s: VPE has been initialized", __func__);
@@ -619,7 +620,6 @@
 		atomic_set(&vpe_init_done, 0);
 		return rc;
 	}
-	v4l2_set_subdev_hostdata(sd, mctl);
 	spin_lock_init(&vpe_ctrl->lock);
 	D("%s:end", __func__);
 	return rc;
@@ -843,9 +843,7 @@
 
 	switch (cmd) {
 	case VIDIOC_MSM_VPE_INIT: {
-		struct msm_cam_media_controller *mctl =
-			(struct msm_cam_media_controller *)arg;
-		msm_vpe_subdev_init(sd, mctl);
+		msm_vpe_subdev_init(sd);
 		break;
 		}
 
@@ -980,7 +978,7 @@
 	platform_set_drvdata(pdev, &vpe_ctrl->subdev);
 
 	media_entity_init(&vpe_ctrl->subdev.entity, 0, NULL, 0);
-	vpe_ctrl->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+	vpe_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
 	vpe_ctrl->subdev.entity.group_id = VPE_DEV;
 	vpe_ctrl->subdev.entity.name = vpe_ctrl->subdev.name;
 
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 5cf0309..6516ea1 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -180,14 +180,5 @@
 	int32_t phase_step_y;
 };
 
-#define VIDIOC_MSM_VPE_INIT \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 15, struct msm_cam_media_controller *)
-
-#define VIDIOC_MSM_VPE_RELEASE \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 16, struct msm_cam_media_controller *)
-
-#define VIDIOC_MSM_VPE_CFG \
-	_IOWR('V', BASE_VIDIOC_PRIVATE + 17, struct msm_mctl_pp_params *)
-
 #endif /*_MSM_VPE_H_*/
 
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index be1efe0..72f3f3d 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -284,7 +284,6 @@
 			int update_type, int res)
 {
 	int32_t rc = 0;
-
 	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 	msleep(30);
 	if (update_type == MSM_SENSOR_REG_INIT) {
@@ -792,8 +791,15 @@
 		sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
 	v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
 		s_ctrl->sensor_v4l2_subdev_ops);
-
+	s_ctrl->sensor_v4l2_subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	media_entity_init(&s_ctrl->sensor_v4l2_subdev.entity, 0, NULL, 0);
+	s_ctrl->sensor_v4l2_subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	s_ctrl->sensor_v4l2_subdev.entity.group_id = SENSOR_DEV;
+	s_ctrl->sensor_v4l2_subdev.entity.name =
+		s_ctrl->sensor_v4l2_subdev.name;
 	msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
+	s_ctrl->sensor_v4l2_subdev.entity.revision =
+		s_ctrl->sensor_v4l2_subdev.devnode->num;
 	goto power_down;
 probe_fail:
 	pr_err("%s %s_i2c_probe failed\n", __func__, client->name);
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 2d3022f..2dfdd7e 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -19,6 +19,7 @@
 #include "msm_sensor.h"
 #include "msm_actuator.h"
 #include "msm_vfe32.h"
+#include "msm_csi_register.h"
 
 #ifdef CONFIG_MSM_CAMERA_DEBUG
 #define D(fmt, args...) pr_debug("msm: " fmt, ##args)
@@ -880,7 +881,6 @@
 	struct msm_cam_v4l2_device *pcam)
 {
 	int rc = 0;
-	struct msm_cam_media_controller *pmctl;
 
 	D("%s\n", __func__);
 
@@ -906,17 +906,6 @@
 	/* initialization the media controller module*/
 	msm_mctl_init(pcam);
 
-	/*for single VFE msms (8660, 8960v1), just populate the session
-	with our VFE devices that registered*/
-	pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
-	if (pmctl == NULL) {
-		pr_err("%s: cannot find mctl\n", __func__);
-		msm_mctl_free(pcam);
-		atomic_dec(&ps->number_pcam_active);
-		return -ENODEV;
-	}
-	pmctl->axi_sdev = ps->axi_device[0];
-	pmctl->isp_sdev = ps->isp_subdev[0];
 	return rc;
 }
 
@@ -940,6 +929,50 @@
 	return rc;
 }
 
+static int map_imem_addresses(struct msm_cam_media_controller *mctl)
+{
+	int rc = 0;
+	rc = msm_iommu_map_contig_buffer(
+		(unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
+		SZ_4K, IOMMU_WRITE | IOMMU_READ,
+		(unsigned long *)&mctl->ping_imem_y);
+	mctl->ping_imem_cbcr = mctl->ping_imem_y + IMEM_Y_SIZE;
+	if (rc < 0) {
+		pr_err("%s: ping iommu mapping returned error %d\n",
+			__func__, rc);
+		mctl->ping_imem_y = 0;
+		mctl->ping_imem_cbcr = 0;
+	}
+	msm_iommu_map_contig_buffer(
+		(unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
+		SZ_4K, IOMMU_WRITE | IOMMU_READ,
+		(unsigned long *)&mctl->pong_imem_y);
+	mctl->pong_imem_cbcr = mctl->pong_imem_y + IMEM_Y_SIZE;
+	if (rc < 0) {
+		pr_err("%s: pong iommu mapping returned error %d\n",
+			 __func__, rc);
+		mctl->pong_imem_y = 0;
+		mctl->pong_imem_cbcr = 0;
+	}
+	return rc;
+}
+
+static void unmap_imem_addresses(struct msm_cam_media_controller *mctl)
+{
+	msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
+		CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
+	msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
+		CAMERA_DOMAIN, GEN_POOL,
+		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
+	mctl->ping_imem_y = 0;
+	mctl->ping_imem_cbcr = 0;
+	mctl->pong_imem_y = 0;
+	mctl->pong_imem_cbcr = 0;
+}
+
 static long msm_ioctl_server(struct file *file, void *fh,
 		bool valid_prio, int cmd, void *arg)
 {
@@ -1283,6 +1316,7 @@
 {
 	int rc = -EINVAL, ges_evt;
 	struct msm_cam_server_queue *queue;
+	struct msm_cam_media_controller *pmctl;
 
 	if (!pcam) {
 		pr_err("%s pcam passed is null ", __func__);
@@ -1301,7 +1335,6 @@
 	msm_queue_init(&queue->ctrl_q, "control");
 	msm_queue_init(&queue->eventData_q, "eventdata");
 	queue->queue_active = 1;
-
 	rc = msm_cam_server_open_session(&g_server_dev, pcam);
 	if (rc < 0) {
 		pr_err("%s: cam_server_open_session failed %d\n",
@@ -1309,6 +1342,17 @@
 		goto error;
 	}
 
+	pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s: invalid mctl controller", __func__);
+		goto error;
+	}
+	rc = map_imem_addresses(pmctl);
+	if (rc < 0) {
+		pr_err("%sFailed to map imem addresses %d\n", __func__, rc);
+		goto error;
+	}
+
 	return rc;
 error:
 	ges_evt = MSM_V4L2_GES_CAM_CLOSE;
@@ -1328,6 +1372,7 @@
 {
 	int rc = -EINVAL, ges_evt;
 	struct msm_cam_server_queue *queue;
+	struct msm_cam_media_controller *pmctl;
 
 	mutex_lock(&g_server_dev.server_queue_lock);
 	queue = &g_server_dev.server_queue[pcam->server_queue_idx];
@@ -1338,6 +1383,13 @@
 	msm_drain_eventq(&queue->eventData_q);
 	mutex_unlock(&g_server_dev.server_queue_lock);
 
+	pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s: invalid mctl controller", __func__);
+		return -EINVAL;
+	}
+	unmap_imem_addresses(pmctl);
+
 	rc = msm_cam_server_close_session(&g_server_dev, pcam);
 	if (rc < 0)
 		pr_err("msm_cam_server_close_session fails %d\n", rc);
@@ -1374,6 +1426,7 @@
 	struct msm_camera_sensor_info *sinfo;
 	struct msm_camera_device_platform_data *camdev;
 	uint8_t csid_core = 0;
+	struct msm_cam_media_controller *p_mctl;
 
 	if (notification == NOTIFY_PCLK_CHANGE ||
 		notification == NOTIFY_CSIPHY_CFG ||
@@ -1384,7 +1437,14 @@
 		camdev = sinfo->pdata;
 		csid_core = camdev->csid_core;
 	}
-
+	if (notification != NOTIFY_GESTURE_CAM_EVT) {
+		p_mctl = v4l2_get_subdev_hostdata(sd);
+		if (p_mctl == NULL) {
+			pr_err("%s: cannot find mctl, %d\n",
+				__func__, notification);
+			return;
+		}
+	}
 	switch (notification) {
 	case NOTIFY_ISP_MSG_EVT:
 	case NOTIFY_VFE_MSG_OUT:
@@ -1393,10 +1453,10 @@
 	case NOTIFY_VFE_BUF_EVT:
 	case NOTIFY_VFE_BUF_FREE_EVT:
 		if (g_server_dev.isp_subdev[0] &&
-			g_server_dev.isp_subdev[0]->isp_notify) {
+			g_server_dev.isp_subdev[0]->isp_notify
+			&& p_mctl->isp_sdev->sd)
 			rc = g_server_dev.isp_subdev[0]->isp_notify(
-				g_server_dev.vfe_device[0], notification, arg);
-		}
+				p_mctl->isp_sdev->sd, notification, arg);
 		break;
 	case NOTIFY_VFE_IRQ:{
 		struct msm_vfe_cfg_cmd cfg_cmd;
@@ -1404,32 +1464,32 @@
 		cfg_cmd.cmd_type = CMD_VFE_PROCESS_IRQ;
 		vfe_params.vfe_cfg = &cfg_cmd;
 		vfe_params.data = arg;
-		rc = v4l2_subdev_call(g_server_dev.vfe_device[0],
+		rc = v4l2_subdev_call(p_mctl->isp_sdev->sd,
 			core, ioctl, 0, &vfe_params);
 	}
 		break;
 	case NOTIFY_AXI_IRQ:
-		rc = v4l2_subdev_call(g_server_dev.axi_device[0],
+		rc = v4l2_subdev_call(p_mctl->axi_sdev,
 			core, ioctl, VIDIOC_MSM_AXI_IRQ, arg);
 		break;
 	case NOTIFY_PCLK_CHANGE:
-		if (g_server_dev.axi_device[0])
-			rc = v4l2_subdev_call(g_server_dev.axi_device[0], video,
+		if (p_mctl->axi_sdev)
+			rc = v4l2_subdev_call(p_mctl->axi_sdev, video,
 			s_crystal_freq, *(uint32_t *)arg, 0);
 		else
-			rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
+			rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
 			s_crystal_freq, *(uint32_t *)arg, 0);
 		break;
 	case NOTIFY_CSIPHY_CFG:
-		rc = v4l2_subdev_call(g_server_dev.csiphy_device[csid_core],
+		rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
 			core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
 		break;
 	case NOTIFY_CSID_CFG:
-		rc = v4l2_subdev_call(g_server_dev.csid_device[csid_core],
+		rc = v4l2_subdev_call(p_mctl->csid_sdev,
 			core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
 		break;
 	case NOTIFY_CSIC_CFG:
-		rc = v4l2_subdev_call(g_server_dev.csic_device[csid_core],
+		rc = v4l2_subdev_call(p_mctl->csic_sdev,
 			core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
 		break;
 	case NOTIFY_GESTURE_EVT:
@@ -1471,6 +1531,33 @@
 	return -EINVAL;
 }
 
+static struct v4l2_subdev  *msm_cam_find_subdev_node(
+	struct v4l2_subdev **sd_list, u32 revision_num)
+{
+	int i = 0;
+	for (i = 0; sd_list[i] != NULL; i++) {
+		if (sd_list[i]->entity.revision == revision_num) {
+			return sd_list[i];
+			break;
+		}
+	}
+	return NULL;
+}
+
+int msm_mctl_find_sensor_subdevs(struct msm_cam_media_controller *p_mctl,
+	int core_index)
+{
+	int rc = -ENODEV;
+
+	v4l2_set_subdev_hostdata(p_mctl->sensor_sdev, p_mctl);
+
+	rc = msm_csi_register_subdevs(p_mctl, core_index, &g_server_dev);
+	if (rc < 0)
+		pr_err("%s: Could not find sensor subdevs\n", __func__);
+
+	return rc;
+}
+
 static irqreturn_t msm_camera_server_parse_irq(int irq_num, void *data)
 {
 	unsigned long flags;
@@ -1825,6 +1912,15 @@
 	index     = sd_info->sd_index;
 
 	switch (sdev_type) {
+	case SENSOR_DEV:
+		if (index >= MAX_NUM_SENSOR_DEV) {
+			pr_err("%s Invalid sensor idx %d", __func__, index);
+			err = -EINVAL;
+			break;
+		}
+		g_server_dev.sensor_device[index] = sd;
+		break;
+
 	case CSIPHY_DEV:
 		if (index >= MAX_NUM_CSIPHY_DEV) {
 			pr_err("%s Invalid CSIPHY idx %d", __func__, index);
@@ -1865,7 +1961,7 @@
 			break;
 		}
 		cam_hw_idx = MSM_CAM_HW_ISPIF + index;
-		g_server_dev.ispif_device = sd;
+		g_server_dev.ispif_device[index] = sd;
 		if (g_server_dev.irqr_device) {
 			g_server_dev.subdev_table[cam_hw_idx] = sd;
 			err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
@@ -1881,6 +1977,7 @@
 		}
 		cam_hw_idx = MSM_CAM_HW_VFE0 + index;
 		g_server_dev.vfe_device[index] = sd;
+		g_server_dev.isp_subdev[index]->sd = sd;
 		if (g_server_dev.irqr_device) {
 			g_server_dev.subdev_table[cam_hw_idx] = sd;
 			err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
@@ -1960,19 +2057,25 @@
 	g_server_dev.video_dev->ioctl_ops = &msm_ioctl_ops_server;
 	g_server_dev.video_dev->release   = video_device_release;
 	g_server_dev.video_dev->minor = 100;
-	g_server_dev.video_dev->vfl_type = 1;
+	g_server_dev.video_dev->vfl_type = VFL_TYPE_GRABBER;
 
 	video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
 
-	strlcpy(g_server_dev.media_dev.model, "qcamera",
+	strlcpy(g_server_dev.media_dev.model, QCAMERA_SERVER_NAME,
 		sizeof(g_server_dev.media_dev.model));
 	g_server_dev.media_dev.dev = &pdev->dev;
 	rc = media_device_register(&g_server_dev.media_dev);
 	g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
+	media_entity_init(&g_server_dev.video_dev->entity, 0, NULL, 0);
+	g_server_dev.video_dev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+	g_server_dev.video_dev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
 
 	rc = video_register_device(g_server_dev.video_dev,
 		VFL_TYPE_GRABBER, 100);
 
+	g_server_dev.video_dev->entity.name =
+		video_device_node_name(g_server_dev.video_dev);
+
 	mutex_init(&g_server_dev.server_lock);
 	mutex_init(&g_server_dev.server_queue_lock);
 	spin_lock_init(&g_server_dev.intr_table_lock);
@@ -2342,6 +2445,104 @@
 	return rc;
 }
 
+static struct msm_isp_ops *find_isp_op(struct v4l2_subdev *sdev)
+{
+	int i;
+	for (i = 0; i < g_server_dev.config_info.num_config_nodes; i++) {
+		if (g_server_dev.isp_subdev[i]->sd == sdev)
+			return g_server_dev.isp_subdev[i];
+	}
+	return NULL;
+}
+
+static int msm_set_mctl_subdev(struct msm_cam_media_controller *pmctl,
+	struct msm_mctl_set_sdev_data *set_data)
+{
+	int rc = 0;
+	struct v4l2_subdev *vfe_sdev = NULL;
+	struct v4l2_subdev *temp_sdev = NULL;
+	switch (set_data->sdev_type) {
+	case CSIPHY_DEV:
+		pmctl->csiphy_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.csiphy_device[0], set_data->revision);
+		temp_sdev = pmctl->csiphy_sdev;
+		break;
+	case CSID_DEV:
+		pmctl->csid_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.csid_device[0], set_data->revision);
+		temp_sdev = pmctl->csid_sdev;
+		break;
+	case CSIC_DEV:
+		pmctl->csic_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.csic_device[0], set_data->revision);
+		temp_sdev = pmctl->csic_sdev;
+		break;
+	case ISPIF_DEV:
+		pmctl->ispif_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.ispif_device[0], set_data->revision);
+		temp_sdev = pmctl->ispif_sdev;
+		break;
+	case VFE_DEV:
+		vfe_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.vfe_device[0], set_data->revision);
+		temp_sdev = vfe_sdev;
+		pmctl->isp_sdev = find_isp_op(vfe_sdev);
+		pmctl->isp_sdev->sd = vfe_sdev;
+		break;
+	case AXI_DEV:
+		pmctl->axi_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.axi_device[0], set_data->revision);
+		temp_sdev = pmctl->axi_sdev;
+		break;
+	case VPE_DEV:
+		pmctl->vpe_sdev = msm_cam_find_subdev_node
+			(&g_server_dev.vpe_device[0], set_data->revision);
+		temp_sdev = pmctl->vpe_sdev;
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	if (temp_sdev != NULL)
+		v4l2_set_subdev_hostdata(temp_sdev, pmctl);
+	else
+		pr_err("%s: Could not find subdev\n", __func__);
+	return rc;
+}
+
+static int msm_unset_mctl_subdev(struct msm_cam_media_controller *pmctl,
+	struct msm_mctl_set_sdev_data *set_data)
+{
+	int rc = 0;
+	switch (set_data->sdev_type) {
+	case CSIPHY_DEV:
+		pmctl->csiphy_sdev = NULL;
+		break;
+	case CSID_DEV:
+		pmctl->csid_sdev = NULL;
+		break;
+	case CSIC_DEV:
+		pmctl->csic_sdev = NULL;
+		break;
+	case ISPIF_DEV:
+		pmctl->ispif_sdev = NULL;
+		break;
+	case VFE_DEV:
+		pmctl->isp_sdev = NULL;
+		break;
+	case AXI_DEV:
+		pmctl->axi_sdev = NULL;
+		break;
+	case VPE_DEV:
+		pmctl->vpe_sdev = NULL;
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	return rc;
+}
+
 static long msm_ioctl_config(struct file *fp, unsigned int cmd,
 	unsigned long arg)
 {
@@ -2497,6 +2698,30 @@
 			rc = -EINVAL;
 		break;
 
+	case MSM_CAM_IOCTL_SET_MCTL_SDEV:{
+		struct msm_mctl_set_sdev_data set_data;
+		if (copy_from_user(&set_data, (void __user *)arg,
+			sizeof(struct msm_mctl_set_sdev_data))) {
+			ERR_COPY_FROM_USER();
+			rc = -EINVAL;
+			break;
+		}
+		rc = msm_set_mctl_subdev(config_cam->p_mctl, &set_data);
+		break;
+	}
+
+	case MSM_CAM_IOCTL_UNSET_MCTL_SDEV:{
+		struct msm_mctl_set_sdev_data set_data;
+		if (copy_from_user(&set_data, (void __user *)arg,
+			sizeof(struct msm_mctl_set_sdev_data))) {
+			ERR_COPY_FROM_USER();
+			rc = -EINVAL;
+			break;
+		}
+		rc = msm_unset_mctl_subdev(config_cam->p_mctl, &set_data);
+		break;
+	}
+
 	default:{
 		/* For the rest of config command, forward to media controller*/
 		struct msm_cam_media_controller *p_mctl = config_cam->p_mctl;
@@ -2622,6 +2847,7 @@
 static int __devinit msm_camera_probe(struct platform_device *pdev)
 {
 	int rc = 0, i;
+	memset(&g_server_dev, 0, sizeof(struct msm_cam_server_dev));
 	/*for now just create a config 0 node
 	  put logic here later to know how many configs to create*/
 	g_server_dev.config_info.num_config_nodes = 1;
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 48058e6..80e1bf8 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -204,6 +204,12 @@
 #define MSM_CAM_IOCTL_STATS_FLUSH_BUFQ \
 	_IOR(MSM_CAM_IOCTL_MAGIC, 57, struct msm_stats_flush_bufq *)
 
+#define MSM_CAM_IOCTL_SET_MCTL_SDEV \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 58, struct msm_mctl_set_sdev_data *)
+
+#define MSM_CAM_IOCTL_UNSET_MCTL_SDEV \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 59, struct msm_mctl_set_sdev_data *)
+
 struct msm_stats_reqbuf {
 	int num_buf;		/* how many buffers requested */
 	int stats_type;	/* stats type */
@@ -1627,9 +1633,31 @@
 };
 
 #define QCAMERA_NAME "qcamera"
+#define QCAMERA_SERVER_NAME "qcamera_server"
 #define QCAMERA_DEVICE_GROUP_ID 1
 #define QCAMERA_VNODE_GROUP_ID 2
 
+enum msm_cam_subdev_type {
+	CSIPHY_DEV,
+	CSID_DEV,
+	CSIC_DEV,
+	ISPIF_DEV,
+	VFE_DEV,
+	AXI_DEV,
+	VPE_DEV,
+	SENSOR_DEV,
+	ACTUATOR_DEV,
+	EEPROM_DEV,
+	GESTURE_DEV,
+	IRQ_ROUTER_DEV,
+	CPP_DEV,
+};
+
+struct msm_mctl_set_sdev_data {
+	uint32_t revision;
+	enum msm_cam_subdev_type sdev_type;
+};
+
 #define MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t)
 
@@ -1654,6 +1682,36 @@
 #define MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_camera_v4l2_ioctl_t)
 
+#define VIDIOC_MSM_VPE_INIT \
+	_IO('V', BASE_VIDIOC_PRIVATE + 15)
+
+#define VIDIOC_MSM_VPE_RELEASE \
+	_IO('V', BASE_VIDIOC_PRIVATE + 16)
+
+#define VIDIOC_MSM_VPE_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 17, struct msm_mctl_pp_params *)
+
+#define VIDIOC_MSM_AXI_INIT \
+	_IO('V', BASE_VIDIOC_PRIVATE + 18)
+
+#define VIDIOC_MSM_AXI_RELEASE \
+	_IO('V', BASE_VIDIOC_PRIVATE + 19)
+
+#define VIDIOC_MSM_AXI_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 20, void *)
+
+#define VIDIOC_MSM_AXI_IRQ \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 21, void *)
+
+#define VIDIOC_MSM_AXI_BUF_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 22, void *)
+
+#define VIDIOC_MSM_VFE_INIT \
+	_IO('V', BASE_VIDIOC_PRIVATE + 22)
+
+#define VIDIOC_MSM_VFE_RELEASE \
+	_IO('V', BASE_VIDIOC_PRIVATE + 23)
+
 struct msm_camera_v4l2_ioctl_t {
 	uint32_t id;
 	void __user *ioctl_ptr;