msm: camera: Convert VPE into platform device

Make VPE platform devices as well as
v4l2 sub-devices. They are created at system boot-up,
and registered during camera open.

The subdevices are decoupled from the v4l2 devices by
using device model APIs to find and register them.

Change-Id: I884b38f714df6f101d48b38219d274bf91fef4c6
Signed-off-by: Kevin Chan <ktchan@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index a7cc933..8145d6b 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -1426,6 +1426,7 @@
 	platform_device_register(&msm8960_device_csid1);
 	platform_device_register(&msm8960_device_ispif);
 	platform_device_register(&msm8960_device_vfe);
+	platform_device_register(&msm8960_device_vpe);
 }
 #endif
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index e85b4ca..66c6436 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5428,7 +5428,7 @@
 	CLK_LOOKUP("mdp_tv_clk",	mdp_tv_clk.c,		NULL),
 	CLK_LOOKUP("hdmi_clk",		hdmi_tv_clk.c,		NULL),
 	CLK_LOOKUP("core_clk",		hdmi_app_clk.c,	"hdmi_msm.1"),
-	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		NULL),
+	CLK_LOOKUP("vpe_clk",		vpe_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("core_clk",		vpe_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("vfe_clk",		vfe_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("core_clk",		vfe_clk.c,	"footswitch-8x60.8"),
@@ -5469,7 +5469,7 @@
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
 	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		"msm_vfe.0"),
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
-	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		NULL),
+	CLK_LOOKUP("vpe_pclk",		vpe_p_clk.c,		"msm_vpe.0"),
 	CLK_LOOKUP("iface_clk",		vpe_p_clk.c,	"footswitch-8x60.9"),
 	CLK_LOOKUP("mi2s_bit_clk",	mi2s_bit_clk.c,		NULL),
 	CLK_LOOKUP("mi2s_osr_clk",	mi2s_osr_clk.c,		NULL),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index edaa008..0765251 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -983,18 +983,6 @@
 #ifdef CONFIG_MSM_CAMERA
 struct resource msm_camera_resources[] = {
 	{
-		.name	= "vpe",
-		.start	= 0x05300000,
-		.end	= 0x05300000 + SZ_1M - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "vpe",
-		.start	= VPE_IRQ,
-		.end	= VPE_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
 		.name	= "vid_buf",
 		.flags	= IORESOURCE_DMA,
 	},
@@ -1150,6 +1138,28 @@
 	.resource       = msm_vfe_resources,
 	.num_resources  = ARRAY_SIZE(msm_vfe_resources),
 };
+
+static struct resource msm_vpe_resources[] = {
+	{
+		.name	= "vpe",
+		.start	= 0x05300000,
+		.end	= 0x05300000 + SZ_1M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "vpe",
+		.start	= VPE_IRQ,
+		.end	= VPE_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device msm8960_device_vpe = {
+	.name           = "msm_vpe",
+	.id             = 0,
+	.resource       = msm_vpe_resources,
+	.num_resources  = ARRAY_SIZE(msm_vpe_resources),
+};
 #endif
 
 static struct resource resources_ssbi_pm8921[] = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 871a7d3..b5cadd3 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -64,6 +64,7 @@
 extern struct platform_device msm8960_device_csid1;
 extern struct platform_device msm8960_device_ispif;
 extern struct platform_device msm8960_device_vfe;
+extern struct platform_device msm8960_device_vpe;
 
 extern struct platform_device apq8064_device_uart_gsbi1;
 extern struct platform_device apq8064_device_uart_gsbi3;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c772e64..f7a1fa8 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1481,7 +1481,7 @@
 			return rc;
 		}
 		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
-					&pcam->mctl.isp_sdev->sd_vpe);
+					pcam->mctl.isp_sdev->sd_vpe);
 		if (rc < 0) {
 			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s: vpe v4l2_device_register_subdev failed rc = %d\n",
@@ -1614,7 +1614,7 @@
 
 	if (pcam->use_count == 0) {
 		v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd);
-		v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd_vpe);
+		v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd_vpe);
 		rc = msm_cam_server_close_session(&g_server_dev, pcam);
 		if (rc < 0)
 			pr_err("msm_cam_server_close_session fails %d\n", rc);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 563ab56..f11e43f 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -45,6 +45,7 @@
 #define MSM_CSID_DRV_NAME "msm_csid"
 #define MSM_ISPIF_DRV_NAME "msm_ispif"
 #define MSM_VFE_DRV_NAME "msm_vfe"
+#define MSM_VPE_DRV_NAME "msm_vpe"
 
 /* msm queue management APIs*/
 
@@ -249,7 +250,7 @@
 
 	/* vfe subdevice */
 	struct v4l2_subdev *sd;
-	struct v4l2_subdev sd_vpe;
+	struct v4l2_subdev *sd_vpe;
 };
 
 struct msm_isp_buf_info {
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index a280ab0..1293c7b 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -45,10 +45,7 @@
 
 static struct clk *camio_jpeg_clk;
 static struct clk *camio_jpeg_pclk;
-static struct clk *camio_vpe_clk;
-static struct clk *camio_vpe_pclk;
 static struct regulator *fs_ijpeg;
-static struct regulator *fs_vpe;
 static struct regulator *cam_vana;
 static struct regulator *cam_vio;
 static struct regulator *cam_vdig;
@@ -357,17 +354,6 @@
 		clk = clk_get(NULL, "ijpeg_pclk");
 		break;
 
-	case CAMIO_VPE_CLK:
-		camio_vpe_clk =
-		clk = clk_get(NULL, "vpe_clk");
-		msm_camio_clk_set_min_rate(clk, 150000000);
-		break;
-
-	case CAMIO_VPE_PCLK:
-		camio_vpe_pclk =
-		clk = clk_get(NULL, "vpe_pclk");
-		break;
-
 	default:
 		break;
 	}
@@ -401,14 +387,6 @@
 		clk = camio_jpeg_pclk;
 		break;
 
-	case CAMIO_VPE_CLK:
-		clk = camio_vpe_clk;
-		break;
-
-	case CAMIO_VPE_PCLK:
-		clk = camio_vpe_pclk;
-		break;
-
 	default:
 		break;
 	}
@@ -483,42 +461,6 @@
 	return rc;
 }
 
-int msm_camio_vpe_clk_disable(void)
-{
-	int rc = 0;
-	if (fs_vpe) {
-		regulator_disable(fs_vpe);
-		regulator_put(fs_vpe);
-	}
-
-	rc = msm_camio_clk_disable(CAMIO_VPE_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_disable(CAMIO_VPE_PCLK);
-	return rc;
-}
-
-int msm_camio_vpe_clk_enable(uint32_t clk_rate)
-{
-	int rc = 0;
-	(void)clk_rate;
-	fs_vpe = regulator_get(NULL, "fs_vpe");
-	if (IS_ERR(fs_vpe)) {
-		pr_err("%s: Regulator FS_VPE get failed %ld\n", __func__,
-			PTR_ERR(fs_vpe));
-		fs_vpe = NULL;
-	} else if (regulator_enable(fs_vpe)) {
-		pr_err("%s: Regulator FS_VPE enable failed\n", __func__);
-		regulator_put(fs_vpe);
-	}
-
-	rc = msm_camio_clk_enable(CAMIO_VPE_CLK);
-	if (rc < 0)
-		return rc;
-	rc = msm_camio_clk_enable(CAMIO_VPE_PCLK);
-	return rc;
-}
-
 static int config_gpio_table(int gpio_en)
 {
 	struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 8d2caba..a3cf004 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -215,7 +215,7 @@
 	case NOTIFY_VPE_MSG_EVT:
 		if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
 			rc = p_mctl->isp_sdev->isp_notify(
-				&p_mctl->isp_sdev->sd_vpe, notification, arg);
+				p_mctl->isp_sdev->sd_vpe, notification, arg);
 		}
 		break;
 	case NOTIFY_PCLK_CHANGE:
@@ -394,6 +394,19 @@
 	p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
 	put_driver(driver);
 
+	/* 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_put_driver;
+
+	p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+	put_driver(driver);
+
 	rc = 0;
 	return rc;
 out_put_driver:
@@ -465,7 +478,7 @@
 		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->isp_sdev->sd_vpe, sync);
+				p_mctl->isp_sdev->sd_vpe, sync);
 		if (rc < 0) {
 			pr_err("%s: isp init failed: %d\n", __func__, rc);
 			goto msm_open_done;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 2bf95a0..8236dae 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -300,12 +300,12 @@
 	case VPE_CMD_INIT:
 	case VPE_CMD_DEINIT:
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	case VPE_CMD_DISABLE:
 	case VPE_CMD_RESET:
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	case VPE_CMD_ENABLE: {
 		struct msm_vpe_clock_rate clk_rate;
@@ -325,7 +325,7 @@
 		}
 		pp_cmd->value = (void *)&clk_rate;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		pp_cmd->value = argp;
 		break;
 	}
@@ -344,7 +344,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&flush_buf;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		if (rc == 0) {
 			if (copy_to_user((void *)argp,
 						&flush_buf,
@@ -372,7 +372,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&op_mode_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_INPUT_PLANE_CFG: {
@@ -390,7 +390,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&input_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_OUTPUT_PLANE_CFG: {
@@ -411,7 +411,7 @@
 		}
 		pp_cmd->value = (void *)&output_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_INPUT_PLANE_UPDATE: {
@@ -429,7 +429,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&input_update_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_SCALE_CFG_TYPE: {
@@ -447,7 +447,7 @@
 			return -EFAULT;
 		pp_cmd->value = (void *)&scaler_cfg;
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
 		break;
 	}
 	case VPE_CMD_ZOOM: {
@@ -512,7 +512,7 @@
 			break;
 		}
 		rc = msm_isp_subdev_ioctl_vpe(
-			&p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
+			p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
 		if (rc) {
 			kfree(zoom);
 			break;
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index e4384f5..658f911 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/pm_qos_params.h>
+#include <linux/regulator/consumer.h>
 #include <linux/clk.h>
 #include <mach/clk.h>
 #include <asm/div64.h>
@@ -32,9 +33,7 @@
 static int vpe_enable(uint32_t);
 static int vpe_disable(void);
 static int vpe_update_scaler(struct msm_pp_crop *pcrop);
-static struct vpe_device_type *vpe_device;
 struct vpe_ctrl_type *vpe_ctrl;
-static void *vpe_syncdata;
 static atomic_t vpe_init_done = ATOMIC_INIT(0);
 
 static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
@@ -49,14 +48,14 @@
 static int vpe_start(void)
 {
 	/*  enable the frame irq, bit 0 = Display list 0 ROI done */
-	msm_io_w_mb(1, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
-	msm_io_dump(vpe_device->vpebase, 0x120);
-	msm_io_dump(vpe_device->vpebase + 0x10000, 0x250);
-	msm_io_dump(vpe_device->vpebase + 0x30000, 0x20);
-	msm_io_dump(vpe_device->vpebase + 0x50000, 0x30);
-	msm_io_dump(vpe_device->vpebase + 0x50400, 0x10);
+	msm_io_w_mb(1, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
+	msm_io_dump(vpe_ctrl->vpebase, 0x120);
+	msm_io_dump(vpe_ctrl->vpebase + 0x10000, 0x250);
+	msm_io_dump(vpe_ctrl->vpebase + 0x30000, 0x20);
+	msm_io_dump(vpe_ctrl->vpebase + 0x50000, 0x30);
+	msm_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10);
 	/* this triggers the operation. */
-	msm_io_w(1, vpe_device->vpebase + VPE_DL0_START_OFFSET);
+	msm_io_w(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
 	wmb();
 	return 0;
 }
@@ -70,16 +69,16 @@
 
 static void vpe_config_axi_default(void)
 {
-	msm_io_w(0x25, vpe_device->vpebase + VPE_AXI_ARB_2_OFFSET);
+	msm_io_w(0x25, vpe_ctrl->vpebase + VPE_AXI_ARB_2_OFFSET);
 	CDBG("%s: yaddr %ld cbcraddr %ld", __func__,
 		 vpe_ctrl->out_y_addr, vpe_ctrl->out_cbcr_addr);
 	if (!vpe_ctrl->out_y_addr || !vpe_ctrl->out_cbcr_addr)
 		return;
 	msm_io_w(vpe_ctrl->out_y_addr,
-		vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
+		vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
 	/* for video  CbCr address */
 	msm_io_w(vpe_ctrl->out_cbcr_addr,
-		vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
+		vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
 
 }
 
@@ -89,33 +88,33 @@
 	uint32_t rc = 0;
 
 	vpe_reset_state_variables();
-	vpe_version = msm_io_r(vpe_device->vpebase + VPE_HW_VERSION_OFFSET);
+	vpe_version = msm_io_r(vpe_ctrl->vpebase + VPE_HW_VERSION_OFFSET);
 	CDBG("vpe_version = 0x%x\n", vpe_version);
 	/* disable all interrupts.*/
-	msm_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
+	msm_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
 	/* clear all pending interrupts*/
-	msm_io_w(0x1fffff, vpe_device->vpebase + VPE_INTR_CLEAR_OFFSET);
+	msm_io_w(0x1fffff, vpe_ctrl->vpebase + VPE_INTR_CLEAR_OFFSET);
 	/* write sw_reset to reset the core. */
-	msm_io_w(0x10, vpe_device->vpebase + VPE_SW_RESET_OFFSET);
+	msm_io_w(0x10, vpe_ctrl->vpebase + VPE_SW_RESET_OFFSET);
 	/* then poll the reset bit, it should be self-cleared. */
 	while (1) {
 		rc =
-		msm_io_r(vpe_device->vpebase + VPE_SW_RESET_OFFSET) & 0x10;
+		msm_io_r(vpe_ctrl->vpebase + VPE_SW_RESET_OFFSET) & 0x10;
 		if (rc == 0)
 			break;
 	}
 	/*  at this point, hardware is reset. Then pogram to default
 		values. */
 	msm_io_w(VPE_AXI_RD_ARB_CONFIG_VALUE,
-			vpe_device->vpebase + VPE_AXI_RD_ARB_CONFIG_OFFSET);
+			vpe_ctrl->vpebase + VPE_AXI_RD_ARB_CONFIG_OFFSET);
 
 	msm_io_w(VPE_CGC_ENABLE_VALUE,
-			vpe_device->vpebase + VPE_CGC_EN_OFFSET);
-	msm_io_w(1, vpe_device->vpebase + VPE_CMD_MODE_OFFSET);
+			vpe_ctrl->vpebase + VPE_CGC_EN_OFFSET);
+	msm_io_w(1, vpe_ctrl->vpebase + VPE_CMD_MODE_OFFSET);
 	msm_io_w(VPE_DEFAULT_OP_MODE_VALUE,
-			vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+			vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 	msm_io_w(VPE_DEFAULT_SCALE_CONFIG,
-			vpe_device->vpebase + VPE_SCALE_CONFIG_OFFSET);
+			vpe_ctrl->vpebase + VPE_SCALE_CONFIG_OFFSET);
 	vpe_config_axi_default();
 	return rc;
 }
@@ -125,7 +124,7 @@
 	uint32_t  rot_flag, rc = 0;
 	struct msm_pp_crop *pcrop = (struct msm_pp_crop *)pinfo;
 
-	rot_flag = msm_io_r(vpe_device->vpebase +
+	rot_flag = msm_io_r(vpe_ctrl->vpebase +
 						VPE_OP_MODE_OFFSET) & 0xE00;
 	if (pinfo != NULL) {
 		pr_err("%s: Crop info in2_w = %d, in2_h = %d "
@@ -145,39 +144,39 @@
 	uint32_t i, offset;
 	offset = *p;
 	for (i = offset; i < (VPE_SCALE_COEFF_NUM + offset); i++) {
-		msm_io_w(*(++p), vpe_device->vpebase + VPE_SCALE_COEFF_LSBn(i));
-		msm_io_w(*(++p), vpe_device->vpebase + VPE_SCALE_COEFF_MSBn(i));
+		msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SCALE_COEFF_LSBn(i));
+		msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SCALE_COEFF_MSBn(i));
 	}
 }
 
 void vpe_input_plane_config(uint32_t *p)
 {
-	msm_io_w(*p, vpe_device->vpebase + VPE_SRC_FORMAT_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_UNPACK_PATTERN1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_SIZE_OFFSET);
+	msm_io_w(*p, vpe_ctrl->vpebase + VPE_SRC_FORMAT_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_UNPACK_PATTERN1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
 	vpe_ctrl->in_h_w = *p;
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_XY_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
 	CDBG("%s: in_h_w=0x%x", __func__, vpe_ctrl->in_h_w);
 }
 
 void vpe_output_plane_config(uint32_t *p)
 {
-	msm_io_w(*p, vpe_device->vpebase + VPE_OUT_FORMAT_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_PACK_PATTERN1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_SIZE_OFFSET);
-	msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_XY_OFFSET);
+	msm_io_w(*p, vpe_ctrl->vpebase + VPE_OUT_FORMAT_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_PACK_PATTERN1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
+	msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_XY_OFFSET);
 	vpe_ctrl->pcbcr_dis_offset = *(++p);
 }
 
 static int vpe_operation_config(uint32_t *p)
 {
 	uint32_t w, h, temp;
-	msm_io_w(*p, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+	msm_io_w(*p, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 
-	temp = msm_io_r(vpe_device->vpebase + VPE_OUT_SIZE_OFFSET);
+	temp = msm_io_r(vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
 	w = temp & 0xFFF;
 	h = (temp & 0xFFF0000) >> 16;
 	if (*p++ & 0xE00) {
@@ -221,15 +220,15 @@
 		(pcrop->src_h >= pcrop->dst_h)) {
 		CDBG(" =======VPE no zoom needed.\n");
 
-		temp = msm_io_r(vpe_device->vpebase + VPE_OP_MODE_OFFSET)
+		temp = msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET)
 		& 0xfffffffc;
-		msm_io_w(temp, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+		msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 
 
-		msm_io_w(0, vpe_device->vpebase + VPE_SRC_XY_OFFSET);
+		msm_io_w(0, vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
 
 		CDBG("vpe_ctrl->in_h_w = %d\n", vpe_ctrl->in_h_w);
-		msm_io_w(vpe_ctrl->in_h_w , vpe_device->vpebase +
+		msm_io_w(vpe_ctrl->in_h_w , vpe_ctrl->vpebase +
 				VPE_SRC_SIZE_OFFSET);
 
 		return rc;
@@ -240,8 +239,8 @@
 	/* assumption is both direction need zoom. this can be
 	improved. */
 	temp =
-		msm_io_r(vpe_device->vpebase + VPE_OP_MODE_OFFSET) | 0x3;
-	msm_io_w(temp, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+		msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET) | 0x3;
+	msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
 
 	src_ROI_width = pcrop->src_w;
 	src_ROI_height = pcrop->src_h;
@@ -253,7 +252,7 @@
 		out_ROI_height);
 	src_roi = (src_ROI_height << 16) + src_ROI_width;
 
-	msm_io_w(src_roi, vpe_device->vpebase + VPE_SRC_SIZE_OFFSET);
+	msm_io_w(src_roi, vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
 
 	src_x = pcrop->src_x;
 	src_y = pcrop->src_y;
@@ -261,7 +260,7 @@
 	CDBG("src_x = %d, src_y=%d.\n", src_x, src_y);
 
 	src_xy = src_y*(1<<16) + src_x;
-	msm_io_w(src_xy, vpe_device->vpebase +
+	msm_io_w(src_xy, vpe_ctrl->vpebase +
 			VPE_SRC_XY_OFFSET);
 	CDBG("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
 
@@ -401,15 +400,15 @@
 	CDBG("phase init x = %d, init y = %d.\n",
 		 phase_init_x, phase_init_y);
 
-	msm_io_w(phase_step_x, vpe_device->vpebase +
+	msm_io_w(phase_step_x, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEX_STEP_OFFSET);
-	msm_io_w(phase_step_y, vpe_device->vpebase +
+	msm_io_w(phase_step_y, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEY_STEP_OFFSET);
 
-	msm_io_w(phase_init_x, vpe_device->vpebase +
+	msm_io_w(phase_init_x, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEX_INIT_OFFSET);
 
-	msm_io_w(phase_init_y, vpe_device->vpebase +
+	msm_io_w(phase_init_y, vpe_ctrl->vpebase +
 			VPE_SCALE_PHASEY_INIT_OFFSET);
 
 	return 1;
@@ -445,16 +444,16 @@
 	spin_lock_irqsave(&vpe_ctrl->lock, flags);
 	msm_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->src_frame.sp.y_off),
-			vpe_device->vpebase + VPE_SRCP0_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
 	msm_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off),
-			vpe_device->vpebase + VPE_SRCP1_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
 	msm_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->dest_frame.sp.y_off),
-			vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
 	msm_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
 			  vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off),
-			vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
+			vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
 	vpe_ctrl->state = VPE_STATE_ACTIVE;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
 	vpe_start();
@@ -473,7 +472,7 @@
 	vpe_ctrl->state = VPE_STATE_INIT;   /* put it back to idle. */
 	vpe_ctrl->pp_frame_info = NULL;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	v4l2_subdev_notify(vpe_ctrl->subdev,
+	v4l2_subdev_notify(&vpe_ctrl->subdev,
 		NOTIFY_VPE_MSG_EVT, (void *)&rp);
 }
 
@@ -489,22 +488,20 @@
 
 static irqreturn_t vpe_parse_irq(int irq_num, void *data)
 {
-	vpe_ctrl->irq_status = msm_io_r_mb(vpe_device->vpebase +
+	vpe_ctrl->irq_status = msm_io_r_mb(vpe_ctrl->vpebase +
 							VPE_INTR_STATUS_OFFSET);
-	msm_io_w_mb(vpe_ctrl->irq_status, vpe_device->vpebase +
+	msm_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase +
 				VPE_INTR_CLEAR_OFFSET);
-	msm_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
+	msm_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
 	CDBG("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
 	tasklet_schedule(&vpe_tasklet);
 	return IRQ_HANDLED;
 }
 
-static int vpe_enable_irq(void)
-{
-	uint32_t rc = 0;
-	enable_irq(vpe_device->vpeirq);
-	return rc;
-}
+static struct msm_cam_clk_info vpe_clk_info[] = {
+	{"vpe_clk", 160000000},
+	{"vpe_pclk", -1},
+};
 
 int vpe_enable(uint32_t clk_rate)
 {
@@ -520,13 +517,32 @@
 	}
 	vpe_ctrl->state = VPE_STATE_INIT;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	rc = msm_camio_vpe_clk_enable(clk_rate);
-	if (rc < 0) {
-		pr_err("%s: msm_camio_vpe_clk_enable failed", __func__);
-		vpe_ctrl->state = VPE_STATE_IDLE;
-		return rc;
+	enable_irq(vpe_ctrl->vpeirq->start);
+	vpe_ctrl->fs_vpe = regulator_get(NULL, "fs_vpe");
+	if (IS_ERR(vpe_ctrl->fs_vpe)) {
+		pr_err("%s: Regulator FS_VPE get failed %ld\n", __func__,
+			PTR_ERR(vpe_ctrl->fs_vpe));
+		vpe_ctrl->fs_vpe = NULL;
+		goto vpe_fs_failed;
+	} else if (regulator_enable(vpe_ctrl->fs_vpe)) {
+		pr_err("%s: Regulator FS_VPE enable failed\n", __func__);
+		regulator_put(vpe_ctrl->fs_vpe);
+		goto vpe_fs_failed;
 	}
-	vpe_enable_irq();
+
+	rc = msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+			vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 1);
+	if (rc < 0)
+		goto vpe_clk_failed;
+
+	return rc;
+
+vpe_clk_failed:
+	regulator_disable(vpe_ctrl->fs_vpe);
+	regulator_put(vpe_ctrl->fs_vpe);
+	vpe_ctrl->fs_vpe = NULL;
+vpe_fs_failed:
+	disable_irq(vpe_ctrl->vpeirq->start);
 	return rc;
 }
 
@@ -543,9 +559,15 @@
 	}
 	vpe_ctrl->state = VPE_STATE_IDLE;
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-	disable_irq(vpe_device->vpeirq);
+
+	msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+			vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
+
+	regulator_disable(vpe_ctrl->fs_vpe);
+	regulator_put(vpe_ctrl->fs_vpe);
+	vpe_ctrl->fs_vpe = NULL;
+	disable_irq(vpe_ctrl->vpeirq->start);
 	tasklet_kill(&vpe_tasklet);
-	rc = msm_camio_vpe_clk_disable();
 	return rc;
 }
 
@@ -628,7 +650,7 @@
 	.core = &msm_vpe_subdev_core_ops,
 };
 
-static int msm_vpe_resource_init(struct platform_device *pdev, void *sdata);
+static int msm_vpe_resource_init(struct platform_device *pdev);
 
 int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
 	struct platform_device *pdev)
@@ -640,108 +662,122 @@
 		return -EBUSY;
 	}
 	atomic_set(&vpe_init_done, 1);
-	vpe_syncdata = data;
-	rc = msm_vpe_resource_init(pdev, vpe_syncdata);
+
+	rc = msm_vpe_resource_init(pdev);
 	if (rc < 0) {
 		atomic_set(&vpe_init_done, 0);
 		return rc;
 	}
-	vpe_ctrl->subdev = sd;
-	v4l2_subdev_init(sd, &msm_vpe_subdev_ops);
-	v4l2_set_subdev_hostdata(sd, data);
-	snprintf(sd->name, sizeof(sd->name), "vpe");
 	spin_lock_init(&vpe_ctrl->lock);
 	CDBG("%s:end", __func__);
 	return rc;
 }
 EXPORT_SYMBOL(msm_vpe_subdev_init);
 
-static int msm_vpe_resource_init(struct platform_device *pdev,
-				void *sdata)
+static int msm_vpe_resource_init(struct platform_device *pdev)
 {
 	int rc = 0;
-	struct resource   *vpemem, *vpeirq, *vpeio;
-	void __iomem      *vpebase;
-	/* first allocate */
-	vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
-	if (!vpe_ctrl) {
+
+	vpe_ctrl->vpebase = ioremap(vpe_ctrl->vpemem->start,
+		resource_size(vpe_ctrl->vpemem));
+
+	if (!vpe_ctrl->vpebase) {
 		rc = -ENOMEM;
-		goto vpe_free_device;
-	}
-	vpe_device = &vpe_ctrl->device_data;
-	/* does the device exist? */
-	vpeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!vpeirq) {
-		pr_err("%s: no vpe irq resource.\n", __func__);
-		rc = -ENODEV;
-		goto vpe_free_device;
-	}
-	vpemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!vpemem) {
-		pr_err("%s: no vpe mem resource!\n", __func__);
-		rc = -ENODEV;
-		goto vpe_free_device;
-	}
-	vpeio = request_mem_region(vpemem->start,
-			resource_size(vpemem), pdev->name);
-	if (!vpeio) {
-		pr_err("%s: VPE region already claimed.\n", __func__);
-		rc = -EBUSY;
-		goto vpe_release_mem_region;
-	}
-	vpebase =
-		ioremap(vpemem->start,
-				(vpemem->end - vpemem->start) + 1);
-	if (!vpebase) {
-		pr_err("%s: vpe ioremap failed.\n", __func__);
-		rc = -ENOMEM;
-		goto vpe_release_mem_region;
+		pr_err("%s: vpe ioremap failed\n", __func__);
+		goto vpe_unmap_mem_region;
 	}
 
-	/* Fall through, _probe is successful. */
-	vpe_device->vpeirq = vpeirq->start;
-	vpe_device->vpemem = vpemem;
-	vpe_device->vpeio = vpeio;
-	vpe_device->vpebase = vpebase;
-	rc = request_irq(vpe_device->vpeirq,
-				vpe_parse_irq,
-				IRQF_TRIGGER_HIGH, "vpe", 0);
-	disable_irq(vpe_device->vpeirq);
-	CDBG("%s:end: vpebase=0x%p", __func__, vpebase);
-	return rc;  /* this rc should be zero.*/
-
-	iounmap(vpe_device->vpebase);  /* this path should never occur */
-
+	return rc;
 /* from this part it is error handling. */
-vpe_release_mem_region:
-	release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
-vpe_free_device:
-	kfree(vpe_ctrl);
+vpe_unmap_mem_region:
+	iounmap(vpe_ctrl->vpebase);
 	return rc;  /* this rc should have error code. */
 }
 
 void msm_vpe_subdev_release(struct platform_device *pdev)
 {
-	struct resource	*vpemem, *vpeio;
 	if (!atomic_read(&vpe_init_done)) {
 		/* no VPE object created */
 		pr_err("%s: no VPE object to release", __func__);
 		return;
 	}
-	CDBG("%s, free_irq\n", __func__);
-	free_irq(vpe_ctrl->device_data.vpeirq, 0);
 
-	vpemem = vpe_ctrl->device_data.vpemem;
-	vpeio  = vpe_ctrl->device_data.vpeio;
-
-	kfree(vpe_ctrl->extdata);
-	iounmap(vpe_ctrl->device_data.vpebase);
-	kfree(vpe_ctrl);
-	vpe_ctrl = NULL;
-	release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
-	CDBG("%s, end\n", __func__);
-	vpe_syncdata = NULL;
+	iounmap(vpe_ctrl->vpebase);
 	atomic_set(&vpe_init_done, 0);
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
+static int __devinit vpe_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	CDBG("%s: device id = %d\n", __func__, pdev->id);
+	vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
+	if (!vpe_ctrl) {
+		pr_err("%s: no enough memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	v4l2_subdev_init(&vpe_ctrl->subdev, &msm_vpe_subdev_ops);
+	v4l2_set_subdevdata(&vpe_ctrl->subdev, vpe_ctrl);
+	snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
+	platform_set_drvdata(pdev, &vpe_ctrl->subdev);
+
+	vpe_ctrl->vpemem = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, "vpe");
+	if (!vpe_ctrl->vpemem) {
+		pr_err("%s: no mem resource?\n", __func__);
+		rc = -ENODEV;
+		goto vpe_no_resource;
+	}
+	vpe_ctrl->vpeirq = platform_get_resource_byname(pdev,
+					IORESOURCE_IRQ, "vpe");
+	if (!vpe_ctrl->vpeirq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto vpe_no_resource;
+	}
+
+	vpe_ctrl->vpeio = request_mem_region(vpe_ctrl->vpemem->start,
+		resource_size(vpe_ctrl->vpemem), pdev->name);
+	if (!vpe_ctrl->vpeio) {
+		pr_err("%s: no valid mem region\n", __func__);
+		rc = -EBUSY;
+		goto vpe_no_resource;
+	}
+
+	rc = request_irq(vpe_ctrl->vpeirq->start, vpe_parse_irq,
+		IRQF_TRIGGER_RISING, "vfe", 0);
+	if (rc < 0) {
+		release_mem_region(vpe_ctrl->vpemem->start,
+			resource_size(vpe_ctrl->vpemem));
+		pr_err("%s: irq request fail\n", __func__);
+		rc = -EBUSY;
+		goto vpe_no_resource;
+	}
+
+	disable_irq(vpe_ctrl->vpeirq->start);
+
+	vpe_ctrl->pdev = pdev;
+	return 0;
+
+vpe_no_resource:
+	kfree(vpe_ctrl);
+	return 0;
+}
+
+struct platform_driver vpe_driver = {
+	.probe = vpe_probe,
+	.driver = {
+		.name = MSM_VPE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_vpe_init_module(void)
+{
+	return platform_driver_register(&vpe_driver);
+}
+
+module_init(msm_vpe_init_module);
+MODULE_DESCRIPTION("VPE driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 40df0b0..6d84f4e 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -91,15 +91,6 @@
 	VPE_STATE_ACTIVE,
 };
 
-struct vpe_device_type {
-	/* device related. */
-	int   vpeirq;
-	void __iomem      *vpebase;
-	struct resource	  *vpemem;
-	struct resource   *vpeio;
-	void        *device_extdata;
-};
-
 struct dis_offset_type {
 	int32_t dis_offset_x;
 	int32_t dis_offset_y;
@@ -128,8 +119,15 @@
 	enum vpe_state    state;
 	unsigned long     out_y_addr;
 	unsigned long     out_cbcr_addr;
-	struct v4l2_subdev *subdev;
-	struct vpe_device_type device_data;
+	struct v4l2_subdev subdev;
+	struct platform_device *pdev;
+	struct resource   *vpeirq;
+	void __iomem      *vpebase;
+	struct resource	  *vpemem;
+	struct resource   *vpeio;
+	void        *device_extdata;
+	struct regulator *fs_vpe;
+	struct clk	*vpe_clk[2];
 	struct msm_mctl_pp_frame_info *pp_frame_info;
 };