msm: camera: Convert VFE into platform device
Make VFE 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: I91a7144794505af23a6f32de58f1c7cc340f4882
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 892921a..a7cc933 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -1425,6 +1425,7 @@
platform_device_register(&msm8960_device_csid0);
platform_device_register(&msm8960_device_csid1);
platform_device_register(&msm8960_device_ispif);
+ platform_device_register(&msm8960_device_vfe);
}
#endif
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 262c3b7..e85b4ca 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5430,9 +5430,9 @@
CLK_LOOKUP("core_clk", hdmi_app_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("vpe_clk", vpe_clk.c, NULL),
CLK_LOOKUP("core_clk", vpe_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("vfe_clk", vfe_clk.c, NULL),
+ CLK_LOOKUP("vfe_clk", vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("core_clk", vfe_clk.c, "footswitch-8x60.8"),
- CLK_LOOKUP("csi_vfe_clk", csi_vfe_clk.c, NULL),
+ CLK_LOOKUP("csi_vfe_clk", csi_vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("bus_clk", vfe_axi_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("bus_clk", mdp_axi_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("bus_clk", rot_axi_clk.c, "footswitch-8x60.6"),
@@ -5467,7 +5467,7 @@
CLK_LOOKUP("tv_enc_pclk", tv_enc_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "msm_vidc.0"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "footswitch-8x60.7"),
- CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, NULL),
+ 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("iface_clk", vpe_p_clk.c, "footswitch-8x60.9"),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 725e1c2..edaa008 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 = "vfe",
- .start = 0x04500000,
- .end = 0x04500000 + SZ_1M - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "vfe",
- .start = VFE_IRQ,
- .end = VFE_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
.name = "vpe",
.start = 0x05300000,
.end = 0x05300000 + SZ_1M - 1,
@@ -1140,6 +1128,28 @@
.resource = msm_ispif_resources,
.num_resources = ARRAY_SIZE(msm_ispif_resources),
};
+
+static struct resource msm_vfe_resources[] = {
+ {
+ .name = "vfe32",
+ .start = 0x04500000,
+ .end = 0x04500000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "vfe32",
+ .start = VFE_IRQ,
+ .end = VFE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_vfe = {
+ .name = "msm_vfe",
+ .id = 0,
+ .resource = msm_vfe_resources,
+ .num_resources = ARRAY_SIZE(msm_vfe_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 ff3cfce..871a7d3 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -63,6 +63,7 @@
extern struct platform_device msm8960_device_csid0;
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 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 8ef0de9..c772e64 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1473,7 +1473,7 @@
/* Register isp subdev */
rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
- &pcam->mctl.isp_sdev->sd);
+ pcam->mctl.isp_sdev->sd);
if (rc < 0) {
mutex_unlock(&pcam->vid_lock);
pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
@@ -1613,7 +1613,7 @@
f->private_data = NULL;
if (pcam->use_count == 0) {
- v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd);
+ v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd);
v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd_vpe);
rc = msm_cam_server_close_session(&g_server_dev, pcam);
if (rc < 0)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 1409903..563ab56 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -44,6 +44,7 @@
#define MSM_CSIPHY_DRV_NAME "msm_csiphy"
#define MSM_CSID_DRV_NAME "msm_csid"
#define MSM_ISPIF_DRV_NAME "msm_ispif"
+#define MSM_VFE_DRV_NAME "msm_vfe"
/* msm queue management APIs*/
@@ -247,7 +248,7 @@
struct msm_mctl_pp_cmd, void *data);
/* vfe subdevice */
- struct v4l2_subdev sd;
+ struct v4l2_subdev *sd;
struct v4l2_subdev sd_vpe;
};
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index b2b2c2f..a280ab0 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -42,16 +42,11 @@
#define CAM_CSI_LOAD_UA 20000
static struct clk *camio_cam_clk;
-static struct clk *camio_vfe_clk;
-static struct clk *camio_csi0_vfe_clk;
-static struct clk *camio_vfe_pclk;
-/*static struct clk *camio_vfe_pclk;*/
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_vfe;
static struct regulator *fs_ijpeg;
static struct regulator *fs_vpe;
static struct regulator *cam_vana;
@@ -255,18 +250,6 @@
goto cam_vaf_disable;
}
}
- if (fs_vfe == NULL) {
- fs_vfe = regulator_get(&pdev->dev, "fs_vfe");
- if (IS_ERR(fs_vfe)) {
- pr_err("%s: Regulator FS_VFE get failed %ld\n",
- __func__, PTR_ERR(fs_vfe));
- fs_vfe = NULL;
- } else if (regulator_enable(fs_vfe)) {
- pr_err("%s: Regulator FS_VFE enable failed\n",
- __func__);
- regulator_put(fs_vfe);
- }
- }
return 0;
cam_vaf_disable:
@@ -349,12 +332,6 @@
regulator_put(cam_vaf);
cam_vaf = NULL;
}
-
- if (fs_vfe) {
- regulator_disable(fs_vfe);
- regulator_put(fs_vfe);
- fs_vfe = NULL;
- }
}
int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
@@ -369,27 +346,6 @@
msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
break;
- case CAMIO_VFE_CLK:
- camio_vfe_clk =
- clk = clk_get(NULL, "vfe_clk");
- msm_camio_clk_rate_set_2(clk, camio_clk.vfe_clk_rate);
- break;
-
- case CAMIO_VFE_PCLK:
- camio_vfe_pclk =
- clk = clk_get(NULL, "vfe_pclk");
- break;
-
- case CAMIO_CSI0_VFE_CLK:
- camio_csi0_vfe_clk =
- clk = clk_get(NULL, "csi_vfe_clk");
- break;
-/*
- case CAMIO_CSI1_VFE_CLK:
- camio_csi1_vfe_clk =
- clk = clk_get(&camio_dev->dev, "csi_vfe_clk");
- break;
-*/
case CAMIO_JPEG_CLK:
camio_jpeg_clk =
clk = clk_get(NULL, "ijpeg_clk");
@@ -437,18 +393,6 @@
clk = camio_cam_clk;
break;
- case CAMIO_VFE_CLK:
- clk = camio_vfe_clk;
- break;
-
- case CAMIO_VFE_PCLK:
- clk = camio_vfe_pclk;
- break;
-
- case CAMIO_CSI0_VFE_CLK:
- clk = camio_csi0_vfe_clk;
- break;
-
case CAMIO_JPEG_CLK:
clk = camio_jpeg_clk;
break;
@@ -481,26 +425,6 @@
return rc;
}
-int msm_camio_vfe_clk_rate_set(int rate)
-{
- int rc = 0;
- int round_rate;
- struct clk *clk = camio_vfe_clk;
- round_rate = clk_round_rate(clk, rate);
- if (rc < 0) {
- pr_err("%s: clk_round_rate failed %d\n",
- __func__, rc);
- return rc;
- }
-
- rc = clk_set_rate(clk, round_rate);
- if (rc < 0)
- pr_err("%s: clk_set_rate failed %d\n",
- __func__, rc);
-
- return rc;
-}
-
void msm_camio_clk_rate_set(int rate)
{
struct clk *clk = camio_cam_clk;
@@ -517,37 +441,6 @@
clk_set_min_rate(clk, rate);
}
-static int msm_camio_enable_all_clks(uint8_t csid_core)
-{
- int rc = 0;
-
- rc = msm_camio_clk_enable(CAMIO_VFE_CLK);
- if (rc < 0)
- goto vfe_fail;
- rc = msm_camio_clk_enable(CAMIO_VFE_PCLK);
- if (rc < 0)
- goto vfep_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI0_VFE_CLK);
- if (rc < 0)
- goto csi0_vfe_fail;
-
- return rc;
-csi0_vfe_fail:
- msm_camio_clk_disable(CAMIO_VFE_PCLK);
-vfep_fail:
- msm_camio_clk_disable(CAMIO_VFE_CLK);
-vfe_fail:
- return rc;
-}
-
-static void msm_camio_disable_all_clks(uint8_t csid_core)
-{
- msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
- msm_camio_clk_disable(CAMIO_VFE_PCLK);
- msm_camio_clk_disable(CAMIO_VFE_CLK);
-}
-
int msm_camio_jpeg_clk_disable(void)
{
int rc = 0;
@@ -659,38 +552,6 @@
return rc;
}
-int msm_camio_enable(struct platform_device *pdev)
-{
- int rc = 0;
- struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- uint8_t csid_core = camdev->csid_core;
-
- camio_dev = pdev;
- camio_clk = camdev->ioclk;
- cam_bus_scale_table = camdev->cam_bus_scale_table;
-
- rc = msm_camio_enable_all_clks(csid_core);
- if (rc < 0)
- goto common_fail;
-
- CDBG("camio enable done\n");
- return 0;
-
-common_fail:
- msm_camera_vreg_disable();
- config_gpio_table(0);
- return rc;
-}
-
-void msm_camio_disable(struct platform_device *pdev)
-{
- struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- uint8_t csid_core = camdev->csid_core;
- msm_camio_disable_all_clks(csid_core);
-}
-
int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
{
int32_t val = 0, rc = 0;
@@ -858,9 +719,13 @@
void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
{
static uint32_t bus_perf_client;
+ struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
int rc = 0;
switch (perf_setting) {
case S_INIT:
+ cam_bus_scale_table = camdev->cam_bus_scale_table;
bus_perf_client =
msm_bus_scale_register_client(cam_bus_scale_table);
if (!bus_perf_client) {
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index e12d6b1..e4d4f27 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -638,7 +638,7 @@
int rc = -EINVAL;
void __user *argp = (void __user *)arg;
- struct v4l2_subdev *sd = &pmctl->isp_sdev->sd;
+ struct v4l2_subdev *sd = pmctl->isp_sdev->sd;
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index b23bba1..8d2caba 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -209,7 +209,7 @@
case NOTIFY_VFE_BUF_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
rc = p_mctl->isp_sdev->isp_notify(
- &p_mctl->isp_sdev->sd, notification, arg);
+ p_mctl->isp_sdev->sd, notification, arg);
}
break;
case NOTIFY_VPE_MSG_EVT:
@@ -219,7 +219,8 @@
}
break;
case NOTIFY_PCLK_CHANGE:
- rc = msm_camio_vfe_clk_rate_set(*(uint32_t *)arg);
+ 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(p_mctl->csiphy_sdev,
@@ -380,6 +381,19 @@
p_mctl->ispif_sdev = dev_get_drvdata(dev);
put_driver(driver);
+ /* 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_put_driver;
+
+ p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
+ put_driver(driver);
+
rc = 0;
return rc;
out_put_driver:
@@ -412,6 +426,8 @@
wake_lock(&sync->wake_lock);
sinfo = sync->pdev->dev.platform_data;
+ sync->pdev->resource = sinfo->resource;
+ sync->pdev->num_resources = sinfo->num_resources;
camdev = sinfo->pdata;
csid_core = camdev->csid_core;
rc = msm_mctl_register_subdevs(p_mctl, csid_core);
@@ -448,7 +464,7 @@
/* 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->isp_sdev->sd,
&p_mctl->isp_sdev->sd_vpe, sync);
if (rc < 0) {
pr_err("%s: isp init failed: %d\n", __func__, rc);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 4a3e49f..e8904e2 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -15,6 +15,8 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/atomic.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
#include <mach/irqs.h>
#include <mach/camera.h>
#include <media/v4l2-device.h>
@@ -23,7 +25,6 @@
#include "msm.h"
#include "msm_vfe32.h"
-#include "msm_ispif.h"
atomic_t irq_cnt;
@@ -54,8 +55,8 @@
vfe32_put_ch_ping_addr((chn), (addr)))
static struct vfe32_ctrl_type *vfe32_ctrl;
-static struct msm_camera_io_clk camio_clk;
static void *vfe_syncdata;
+static uint32_t vfe_clk_rate;
struct vfe32_isr_queue_cmd {
struct list_head list;
@@ -437,7 +438,7 @@
rp->evt_msg.type = MSM_CAMERA_MSG;
rp->evt_msg.msg_id = path;
rp->type = id;
- v4l2_subdev_notify(vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+ v4l2_subdev_notify(&vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
spin_unlock_irqrestore(&vfe32_ctrl->sd_notify_lock, flags);
}
@@ -1019,7 +1020,7 @@
8 + ((vfe32_ctrl->sync_timer_number) * 12));
/* Sync Timer Pixel Duration */
value = *tbl++;
- val = camio_clk.vfe_clk_rate / 10000;
+ val = vfe_clk_rate / 10000;
val = 10000000 / val;
val = value * 10000 / val;
CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
@@ -1205,7 +1206,7 @@
isp_msg_evt.msg_id = isp_msg_id;
isp_msg_evt.sof_count = vfe32_ctrl->vfeFrameId;
- v4l2_subdev_notify(vctrl->subdev,
+ v4l2_subdev_notify(&vctrl->subdev,
NOTIFY_ISP_MSG_EVT,
(void *)&isp_msg_evt);
}
@@ -2637,7 +2638,7 @@
msg.buf.ch_paddr[2] = ch2_paddr;
msg.frameCounter = vfe32_ctrl->vfeFrameId;
- v4l2_subdev_notify(vfe32_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_MSG_OUT,
&msg);
return;
@@ -2703,13 +2704,13 @@
VFE_MODE_OF_OPERATION_SNAPSHOT) {
/* will add message for multi-shot. */
vfe32_ctrl->outpath.out0.capture_cnt--;
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_T, ch0_paddr,
ch1_paddr, ch2_paddr);
} else {
/* always send message for continous mode. */
/* if continuous mode, for display. (preview) */
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_P, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2749,7 +2750,7 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out1.ch2,
free_buf->ch_paddr[2]);
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_T, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2775,7 +2776,7 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out2.ch1,
free_buf->ch_paddr[1]);
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_S, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2844,7 +2845,7 @@
vfe32_ctrl->operation_mode ==
VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
vfe32_ctrl->outpath.out1.capture_cnt--;
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_S, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2907,7 +2908,7 @@
vfe32_ctrl->outpath.out2.ch2,
free_buf->ch_paddr[2]);
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_V, ch0_paddr,
ch1_paddr, ch2_paddr);
@@ -2999,7 +3000,7 @@
goto stats_done;
}
- v4l2_subdev_notify(vfe32_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_MSG_STATS,
&msgStats);
stats_done:
@@ -3295,91 +3296,6 @@
return IRQ_HANDLED;
}
-static int vfe32_resource_init(struct platform_device *pdev, void *sdata)
-{
- struct resource *vfemem, *vfeirq, *vfeio;
- int rc;
- struct msm_camera_sensor_info *s_info;
- s_info = pdev->dev.platform_data;
-
- pdev->resource = s_info->resource;
- pdev->num_resources = s_info->num_resources;
-
- vfemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!vfemem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
-
- vfeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!vfeirq) {
- pr_err("%s: no irq resource?\n", __func__);
- return -ENODEV;
- }
-
- vfeio = request_mem_region(vfemem->start,
- resource_size(vfemem), pdev->name);
- if (!vfeio) {
- pr_err("%s: VFE region already claimed\n", __func__);
- return -EBUSY;
- }
-
- vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
- if (!vfe32_ctrl) {
- rc = -ENOMEM;
- goto cmd_init_failed1;
- }
-
- vfe32_ctrl->vfeirq = vfeirq->start;
-
- vfe32_ctrl->vfebase =
- ioremap(vfemem->start, (vfemem->end - vfemem->start) + 1);
- if (!vfe32_ctrl->vfebase) {
- rc = -ENOMEM;
- pr_err("%s: vfe ioremap failed\n", __func__);
- goto cmd_init_failed2;
- }
-
- vfe32_ctrl->extdata =
- kmalloc(sizeof(struct vfe32_frame_extra), GFP_KERNEL);
- if (!vfe32_ctrl->extdata) {
- rc = -ENOMEM;
- goto cmd_init_failed3;
- }
-
- vfe32_ctrl->extlen = sizeof(struct vfe32_frame_extra);
-
- spin_lock_init(&vfe32_ctrl->stop_flag_lock);
- spin_lock_init(&vfe32_ctrl->state_lock);
- spin_lock_init(&vfe32_ctrl->io_lock);
- spin_lock_init(&vfe32_ctrl->update_ack_lock);
- spin_lock_init(&vfe32_ctrl->tasklet_lock);
-
- spin_lock_init(&vfe32_ctrl->aec_ack_lock);
- spin_lock_init(&vfe32_ctrl->awb_ack_lock);
- spin_lock_init(&vfe32_ctrl->af_ack_lock);
- spin_lock_init(&vfe32_ctrl->sd_notify_lock);
- INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
-
- vfe32_ctrl->syncdata = sdata;
- vfe32_ctrl->vfemem = vfemem;
- vfe32_ctrl->vfeio = vfeio;
- vfe32_ctrl->update_linear = false;
- vfe32_ctrl->update_rolloff = false;
- vfe32_ctrl->update_la = false;
- vfe32_ctrl->update_gamma = false;
- return 0;
-
-cmd_init_failed3:
- free_irq(vfe32_ctrl->vfeirq, 0);
- iounmap(vfe32_ctrl->vfebase);
-cmd_init_failed2:
- kfree(vfe32_ctrl);
-cmd_init_failed1:
- release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
- return rc;
-}
-
static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int subdev_cmd, void *arg)
{
@@ -3678,36 +3594,103 @@
return rc;
}
+static struct msm_cam_clk_info vfe32_clk_info[] = {
+ {"vfe_clk", 228570000},
+ {"vfe_pclk", -1},
+ {"csi_vfe_clk", -1},
+};
+
+static int msm_vfe_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+ u32 freq, u32 flags)
+{
+ int rc = 0;
+ int round_rate;
+
+ round_rate = clk_round_rate(vfe32_ctrl->vfe_clk[0], freq);
+ if (rc < 0) {
+ pr_err("%s: clk_round_rate failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ vfe_clk_rate = round_rate;
+ rc = clk_set_rate(vfe32_ctrl->vfe_clk[0], round_rate);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static const struct v4l2_subdev_video_ops msm_vfe_subdev_video_ops = {
+ .s_crystal_freq = msm_vfe_subdev_s_crystal_freq,
+};
+
static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
.ioctl = msm_vfe_subdev_ioctl,
};
static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
.core = &msm_vfe_subdev_core_ops,
+ .video = &msm_vfe_subdev_video_ops,
};
int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
struct platform_device *pdev)
{
int rc = 0;
- struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-
- v4l2_subdev_init(sd, &msm_vfe_subdev_ops);
v4l2_set_subdev_hostdata(sd, data);
- snprintf(sd->name, sizeof(sd->name), "vfe3.2");
-
vfe_syncdata = data;
- camio_clk = camdev->ioclk;
+ spin_lock_init(&vfe32_ctrl->stop_flag_lock);
+ spin_lock_init(&vfe32_ctrl->state_lock);
+ spin_lock_init(&vfe32_ctrl->io_lock);
+ spin_lock_init(&vfe32_ctrl->update_ack_lock);
+ spin_lock_init(&vfe32_ctrl->tasklet_lock);
- rc = vfe32_resource_init(pdev, vfe_syncdata);
+ spin_lock_init(&vfe32_ctrl->aec_ack_lock);
+ spin_lock_init(&vfe32_ctrl->awb_ack_lock);
+ spin_lock_init(&vfe32_ctrl->af_ack_lock);
+ spin_lock_init(&vfe32_ctrl->sd_notify_lock);
+ INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
+
+ vfe32_ctrl->update_linear = false;
+ vfe32_ctrl->update_rolloff = false;
+ vfe32_ctrl->update_la = false;
+ vfe32_ctrl->update_gamma = false;
+
+ enable_irq(vfe32_ctrl->vfeirq->start);
+
+ vfe32_ctrl->vfebase = ioremap(vfe32_ctrl->vfemem->start,
+ resource_size(vfe32_ctrl->vfemem));
+ if (!vfe32_ctrl->vfebase) {
+ rc = -ENOMEM;
+ pr_err("%s: vfe ioremap failed\n", __func__);
+ goto vfe_remap_failed;
+ }
+
+ if (vfe32_ctrl->fs_vfe == NULL) {
+ vfe32_ctrl->fs_vfe =
+ regulator_get(&vfe32_ctrl->pdev->dev, "fs_vfe");
+ if (IS_ERR(vfe32_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator FS_VFE get failed %ld\n",
+ __func__, PTR_ERR(vfe32_ctrl->fs_vfe));
+ vfe32_ctrl->fs_vfe = NULL;
+ goto vfe_fs_failed;
+ } else if (regulator_enable(vfe32_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator FS_VFE enable failed\n",
+ __func__);
+ regulator_put(vfe32_ctrl->fs_vfe);
+ vfe32_ctrl->fs_vfe = NULL;
+ goto vfe_fs_failed;
+ }
+ }
+
+ rc = msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
+ vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 1);
if (rc < 0)
- return rc;
+ goto vfe_clk_enable_failed;
- vfe32_ctrl->subdev = sd;
- /* Bring up all the required GPIOs and Clocks */
- rc = msm_camio_enable(pdev);
msm_camio_set_perf_lvl(S_INIT);
msm_camio_set_perf_lvl(S_PREVIEW);
@@ -3717,38 +3700,118 @@
else
vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
- /* TO DO: Need to release the VFE resources */
- rc = request_irq(vfe32_ctrl->vfeirq, vfe32_parse_irq,
- IRQF_TRIGGER_RISING, "vfe", 0);
+ return rc;
+vfe_clk_enable_failed:
+ regulator_disable(vfe32_ctrl->fs_vfe);
+ regulator_put(vfe32_ctrl->fs_vfe);
+ vfe32_ctrl->fs_vfe = NULL;
+vfe_fs_failed:
+ iounmap(vfe32_ctrl->vfebase);
+vfe_remap_failed:
+ disable_irq(vfe32_ctrl->vfeirq->start);
return rc;
}
void msm_vfe_subdev_release(struct platform_device *pdev)
{
- struct resource *vfemem, *vfeio;
-
+ msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
+ vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
+ if (vfe32_ctrl->fs_vfe) {
+ regulator_disable(vfe32_ctrl->fs_vfe);
+ regulator_put(vfe32_ctrl->fs_vfe);
+ vfe32_ctrl->fs_vfe = NULL;
+ }
CDBG("%s, free_irq\n", __func__);
- free_irq(vfe32_ctrl->vfeirq, 0);
+ disable_irq(vfe32_ctrl->vfeirq->start);
tasklet_kill(&vfe32_tasklet);
+ iounmap(vfe32_ctrl->vfebase);
if (atomic_read(&irq_cnt))
pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
- vfemem = vfe32_ctrl->vfemem;
- vfeio = vfe32_ctrl->vfeio;
-
- kfree(vfe32_ctrl->extdata);
- iounmap(vfe32_ctrl->vfebase);
- kfree(vfe32_ctrl);
- vfe32_ctrl = NULL;
- release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
-
- CDBG("%s, msm_camio_disable\n", __func__);
- msm_camio_disable(pdev);
msm_camio_set_perf_lvl(S_EXIT);
-
vfe_syncdata = NULL;
}
+static int __devinit vfe32_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
+ if (!vfe32_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+ v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
+ snprintf(vfe32_ctrl->subdev.name,
+ sizeof(vfe32_ctrl->subdev.name), "vfe3.2");
+ v4l2_set_subdevdata(&vfe32_ctrl->subdev, vfe32_ctrl);
+ platform_set_drvdata(pdev, &vfe32_ctrl->subdev);
+
+ vfe32_ctrl->vfemem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "vfe32");
+ if (!vfe32_ctrl->vfemem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe32_no_resource;
+ }
+ vfe32_ctrl->vfeirq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "vfe32");
+ if (!vfe32_ctrl->vfeirq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe32_no_resource;
+ }
+
+ vfe32_ctrl->vfeio = request_mem_region(vfe32_ctrl->vfemem->start,
+ resource_size(vfe32_ctrl->vfemem), pdev->name);
+ if (!vfe32_ctrl->vfeio) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto vfe32_no_resource;
+ }
+
+ rc = request_irq(vfe32_ctrl->vfeirq->start, vfe32_parse_irq,
+ IRQF_TRIGGER_RISING, "vfe", 0);
+ if (rc < 0) {
+ release_mem_region(vfe32_ctrl->vfemem->start,
+ resource_size(vfe32_ctrl->vfemem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto vfe32_no_resource;
+ }
+
+ disable_irq(vfe32_ctrl->vfeirq->start);
+
+ vfe32_ctrl->pdev = pdev;
+ return 0;
+
+vfe32_no_resource:
+ kfree(vfe32_ctrl);
+ return 0;
+}
+
+static struct platform_driver vfe32_driver = {
+ .probe = vfe32_probe,
+ .driver = {
+ .name = MSM_VFE_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_vfe32_init_module(void)
+{
+ return platform_driver_register(&vfe32_driver);
+}
+
+static void __exit msm_vfe32_exit_module(void)
+{
+ platform_driver_unregister(&vfe32_driver);
+}
+
+module_init(msm_vfe32_init_module);
+module_exit(msm_vfe32_exit_module);
+MODULE_DESCRIPTION("VFE 3.2 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index a01d910..e41a544 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -915,13 +915,14 @@
spinlock_t tasklet_lock;
struct list_head tasklet_q;
- int vfeirq;
void __iomem *vfebase;
void *syncdata;
uint32_t register_total;
struct resource *vfemem;
struct resource *vfeio;
+ struct resource *vfeirq;
+ struct regulator *fs_vfe;
uint32_t stats_comp;
atomic_t vstate;
@@ -945,7 +946,9 @@
struct vfe_stats_control csStatsControl;
/* v4l2 subdev */
- struct v4l2_subdev *subdev;
+ struct v4l2_subdev subdev;
+ struct platform_device *pdev;
+ struct clk *vfe_clk[3];
spinlock_t sd_notify_lock;
};
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index c59918d..e4384f5 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -670,13 +670,13 @@
}
vpe_device = &vpe_ctrl->device_data;
/* does the device exist? */
- vpeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ 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, 1);
+ vpemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!vpemem) {
pr_err("%s: no vpe mem resource!\n", __func__);
rc = -ENODEV;