msm: camera: Convert CSID into platform device
Make CSID 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: Icdb7d878456e749500b3e7a9e183997dba651cfd
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 537605b..507bc32 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -1422,6 +1422,8 @@
platform_device_register(&msm8960_device_csiphy0);
platform_device_register(&msm8960_device_csiphy1);
+ platform_device_register(&msm8960_device_csid0);
+ platform_device_register(&msm8960_device_csid1);
}
#endif
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 5cc2d1b..52d8f63 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5379,21 +5379,12 @@
CLK_LOOKUP("cam_clk", cam0_clk.c, "msm_camera_imx074.0"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "msm_camera_ov2720.0"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, NULL),
- CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, NULL),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_camera_imx074.0"),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_camera_ov2720.0"),
- CLK_LOOKUP("csi_clk", csi0_clk.c, NULL),
- CLK_LOOKUP("csi_clk", csi1_clk.c, NULL),
- CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_camera_imx074.0"),
- CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_camera_ov2720.0"),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, NULL),
- CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, NULL),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_camera_imx074.0"),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_camera_ov2720.0"),
+ CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_csid.1"),
CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, NULL),
CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, NULL),
CLK_LOOKUP("csiphy_timer_src_clk",
@@ -5450,7 +5441,8 @@
CLK_LOOKUP("bus_b_clk", vcodec_axi_b_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_clk", vpe_axi_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("amp_pclk", amp_p_clk.c, NULL),
- CLK_LOOKUP("csi_pclk", csi_p_clk.c, NULL),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.1"),
CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, NULL),
CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index c5eee63..1b314f2 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1023,30 +1023,6 @@
.flags = IORESOURCE_IRQ,
},
{
- .name = "csid0",
- .start = 0x04800000,
- .end = 0x04800000 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "csid0",
- .start = CSI_0_IRQ,
- .end = CSI_0_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "csid1",
- .start = 0x04800400,
- .end = 0x04800400 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "csid1",
- .start = CSI_1_IRQ,
- .end = CSI_1_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
.name = "s3d_rw",
.start = 0x008003E0,
.end = 0x008003E0 + SZ_16 - 1,
@@ -1058,7 +1034,6 @@
.end = 0x008020B8 + SZ_16 - 1,
.flags = IORESOURCE_MEM,
},
-
};
int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
@@ -1111,6 +1086,50 @@
.resource = msm_csiphy1_resources,
.num_resources = ARRAY_SIZE(msm_csiphy1_resources),
};
+
+static struct resource msm_csid0_resources[] = {
+ {
+ .name = "csid",
+ .start = 0x04800000,
+ .end = 0x04800000 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csid",
+ .start = CSI_0_IRQ,
+ .end = CSI_0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_csid1_resources[] = {
+ {
+ .name = "csid",
+ .start = 0x04800400,
+ .end = 0x04800400 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csid",
+ .start = CSI_1_IRQ,
+ .end = CSI_1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_csid0 = {
+ .name = "msm_csid",
+ .id = 0,
+ .resource = msm_csid0_resources,
+ .num_resources = ARRAY_SIZE(msm_csid0_resources),
+};
+
+struct platform_device msm8960_device_csid1 = {
+ .name = "msm_csid",
+ .id = 1,
+ .resource = msm_csid1_resources,
+ .num_resources = ARRAY_SIZE(msm_csid1_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 7196224..fbbcd70 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -60,6 +60,8 @@
extern struct platform_device msm8960_gemini_device;
extern struct platform_device msm8960_device_csiphy0;
extern struct platform_device msm8960_device_csiphy1;
+extern struct platform_device msm8960_device_csid0;
+extern struct platform_device msm8960_device_csid1;
extern struct platform_device apq8064_device_uart_gsbi1;
extern struct platform_device apq8064_device_uart_gsbi3;
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 4ec67e6..9425c47 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,3 +1,3 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
EXTRA_CFLAGS += -Idrivers/media/video/msm
-obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o
+obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
new file mode 100644
index 0000000..fb809c9
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -0,0 +1,306 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <media/msm_isp.h>
+#include "msm_csid.h"
+#include "msm.h"
+
+#define V4L2_IDENT_CSID 50002
+
+/* MIPI CSID registers */
+#define CSID_HW_VERSION_ADDR 0x0
+#define CSID_CORE_CTRL_ADDR 0x4
+#define CSID_RST_CMD_ADDR 0x8
+#define CSID_CID_LUT_VC_0_ADDR 0xc
+#define CSID_CID_LUT_VC_1_ADDR 0x10
+#define CSID_CID_LUT_VC_2_ADDR 0x14
+#define CSID_CID_LUT_VC_3_ADDR 0x18
+#define CSID_CID_n_CFG_ADDR 0x1C
+#define CSID_IRQ_CLEAR_CMD_ADDR 0x5c
+#define CSID_IRQ_MASK_ADDR 0x60
+#define CSID_IRQ_STATUS_ADDR 0x64
+#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR 0x68
+#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR 0x6c
+#define CSID_CAPTURED_SHORT_PKT_ADDR 0x70
+#define CSID_CAPTURED_LONG_PKT_HDR_ADDR 0x74
+#define CSID_CAPTURED_LONG_PKT_FTR_ADDR 0x78
+#define CSID_PIF_MISR_DL0_ADDR 0x7C
+#define CSID_PIF_MISR_DL1_ADDR 0x80
+#define CSID_PIF_MISR_DL2_ADDR 0x84
+#define CSID_PIF_MISR_DL3_ADDR 0x88
+#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR 0x8C
+#define CSID_STATS_ECC_ADDR 0x90
+#define CSID_STATS_CRC_ADDR 0x94
+#define CSID_TG_CTRL_ADDR 0x9C
+#define CSID_TG_VC_CFG_ADDR 0xA0
+#define CSID_TG_DT_n_CFG_0_ADDR 0xA8
+#define CSID_TG_DT_n_CFG_1_ADDR 0xAC
+#define CSID_TG_DT_n_CFG_2_ADDR 0xB0
+#define CSID_TG_DT_n_CFG_3_ADDR 0xD8
+
+#define DBG_CSID 0
+
+static int msm_csid_cid_lut(
+ struct msm_camera_csid_lut_params *csid_lut_params,
+ void __iomem *csidbase)
+{
+ int rc = 0, i = 0;
+ uint32_t val = 0;
+
+ for (i = 0; i < csid_lut_params->num_cid && i < 4; i++) {
+ if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
+ csid_lut_params->vc_cfg[i].dt > 0x37) {
+ CDBG("%s: unsupported data type 0x%x\n",
+ __func__, csid_lut_params->vc_cfg[i].dt);
+ return rc;
+ }
+ val = msm_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
+ (csid_lut_params->vc_cfg[i].cid >> 2) * 4)
+ & ~(0xFF << csid_lut_params->vc_cfg[i].cid * 8);
+ val |= csid_lut_params->vc_cfg[i].dt <<
+ csid_lut_params->vc_cfg[i].cid * 8;
+ msm_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
+ (csid_lut_params->vc_cfg[i].cid >> 2) * 4);
+ val = csid_lut_params->vc_cfg[i].decode_format << 4 | 0x3;
+ msm_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
+ (csid_lut_params->vc_cfg[i].cid * 4));
+ }
+ return rc;
+}
+
+static int msm_csid_config(struct csid_cfg_params *cfg_params)
+{
+ int rc = 0;
+ uint32_t val = 0;
+ struct csid_device *csid_dev;
+ struct msm_camera_csid_params *csid_params;
+ void __iomem *csidbase;
+ csid_dev = v4l2_get_subdevdata(cfg_params->subdev);
+ csidbase = csid_dev->base;
+ csid_params = cfg_params->parms;
+ val = csid_params->lane_cnt - 1;
+ val |= csid_params->lane_assign << 2;
+ val |= 0x1 << 10;
+ val |= 0x1 << 11;
+ val |= 0x1 << 12;
+ val |= 0x1 << 28;
+ msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
+
+ rc = msm_csid_cid_lut(&csid_params->lut_params, csidbase);
+ if (rc < 0)
+ return rc;
+
+ msm_io_w(0x7fF10800, csidbase + CSID_IRQ_MASK_ADDR);
+ msm_io_w(0x7fF10800, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+
+ msleep(20);
+ return rc;
+}
+
+static irqreturn_t msm_csid_irq(int irq_num, void *data)
+{
+ uint32_t irq;
+ struct csid_device *csid_dev = data;
+ irq = msm_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+ CDBG("%s CSID_IRQ_STATUS_ADDR = 0x%x\n", __func__, irq);
+ msm_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+ return IRQ_HANDLED;
+}
+
+static int msm_csid_subdev_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ BUG_ON(!chip);
+ chip->ident = V4L2_IDENT_CSID;
+ chip->revision = 0;
+ return 0;
+}
+
+static struct msm_cam_clk_info csid_clk_info[] = {
+ {"csi_src_clk", 177780000},
+ {"csi_clk", -1},
+ {"csi_phy_clk", -1},
+ {"csi_pclk", -1},
+};
+
+static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
+{
+ int rc = 0;
+ struct csid_device *csid_dev;
+ csid_dev = v4l2_get_subdevdata(sd);
+ if (csid_dev == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ csid_dev->base = ioremap(csid_dev->mem->start,
+ resource_size(csid_dev->mem));
+ if (!csid_dev->base) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
+ if (rc < 0) {
+ iounmap(csid_dev->base);
+ return rc;
+ }
+
+#if DBG_CSID
+ enable_irq(csid_dev->irq->start);
+#endif
+
+ *csid_version = csid_dev->hw_version;
+
+ return 0;
+}
+
+static int msm_csid_release(struct v4l2_subdev *sd)
+{
+ struct csid_device *csid_dev;
+ csid_dev = v4l2_get_subdevdata(sd);
+
+#if DBG_CSID
+ disable_irq(csid_dev->irq->start);
+#endif
+
+ msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+
+ iounmap(csid_dev->base);
+ return 0;
+}
+
+static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct csid_cfg_params cfg_params;
+ switch (cmd) {
+ case VIDIOC_MSM_CSID_CFG:
+ cfg_params.subdev = sd;
+ cfg_params.parms = arg;
+ return msm_csid_config((struct csid_cfg_params *)&cfg_params);
+ case VIDIOC_MSM_CSID_INIT:
+ return msm_csid_init(sd, (uint32_t *)arg);
+ case VIDIOC_MSM_CSID_RELEASE:
+ return msm_csid_release(sd);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
+ .g_chip_ident = &msm_csid_subdev_g_chip_ident,
+ .ioctl = &msm_csid_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
+ .core = &msm_csid_subdev_core_ops,
+};
+
+static int __devinit csid_probe(struct platform_device *pdev)
+{
+ struct csid_device *new_csid_dev;
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
+ if (!new_csid_dev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&new_csid_dev->subdev, &msm_csid_subdev_ops);
+ v4l2_set_subdevdata(&new_csid_dev->subdev, new_csid_dev);
+ platform_set_drvdata(pdev, &new_csid_dev->subdev);
+ mutex_init(&new_csid_dev->mutex);
+
+ new_csid_dev->mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "csid");
+ if (!new_csid_dev->mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto csid_no_resource;
+ }
+ new_csid_dev->irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "csid");
+ if (!new_csid_dev->irq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto csid_no_resource;
+ }
+ new_csid_dev->io = request_mem_region(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem), pdev->name);
+ if (!new_csid_dev->io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto csid_no_resource;
+ }
+
+ rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
+ IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+ if (rc < 0) {
+ release_mem_region(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto csid_no_resource;
+ }
+ disable_irq(new_csid_dev->irq->start);
+
+ new_csid_dev->base = ioremap(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem));
+ if (!new_csid_dev->base) {
+ rc = -ENOMEM;
+ goto csid_no_resource;
+ }
+
+ new_csid_dev->hw_version =
+ msm_io_r(new_csid_dev->base + CSID_HW_VERSION_ADDR);
+ iounmap(new_csid_dev->base);
+
+ new_csid_dev->pdev = pdev;
+ return 0;
+
+csid_no_resource:
+ mutex_destroy(&new_csid_dev->mutex);
+ kfree(new_csid_dev);
+ return 0;
+}
+
+static struct platform_driver csid_driver = {
+ .probe = csid_probe,
+ .driver = {
+ .name = MSM_CSID_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_csid_init_module(void)
+{
+ return platform_driver_register(&csid_driver);
+}
+
+static void __exit msm_csid_exit_module(void)
+{
+ platform_driver_unregister(&csid_driver);
+}
+
+module_init(msm_csid_init_module);
+module_exit(msm_csid_exit_module);
+MODULE_DESCRIPTION("MSM CSID driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
new file mode 100644
index 0000000..f90abf2
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_H
+#define MSM_CSID_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csid_device {
+ struct platform_device *pdev;
+ struct v4l2_subdev subdev;
+ struct resource *mem;
+ struct resource *irq;
+ struct resource *io;
+ void __iomem *base;
+ struct mutex mutex;
+ uint32_t hw_version;
+
+ struct clk *csid_clk[5];
+};
+
+struct csid_cfg_params {
+ struct v4l2_subdev *subdev;
+ void *parms;
+};
+
+#define VIDIOC_MSM_CSID_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csid_cfg_params)
+
+#define VIDIOC_MSM_CSID_INIT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSID_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+
+#endif
+
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index ef6d684..c8b4abf 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -42,6 +42,7 @@
#define ERR_COPY_TO_USER() ERR_USER_COPY(1)
#define MSM_CSIPHY_DRV_NAME "msm_csiphy"
+#define MSM_CSID_DRV_NAME "msm_csid"
/* msm queue management APIs*/
@@ -116,6 +117,7 @@
NOTIFY_VPE_MSG_EVT,
NOTIFY_PCLK_CHANGE, /* arg = pclk */
NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
+ NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
NOTIFY_INVALID
};
@@ -219,6 +221,7 @@
struct v4l2_subdev *flash_sdev; /* vpe sub device : VPE */
struct msm_cam_config_dev *config_device;
struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
+ struct v4l2_subdev *csid_sdev; /*csid sub device*/
struct v4l2_subdev *ispif_sdev; /* ispif sub device */
struct v4l2_subdev *act_sdev; /* actuator sub device */
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 65bf3ad..de8d679 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -25,42 +25,8 @@
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
-#define DBG_CSID 0
#define BUFF_SIZE_128 128
-/* MIPI CSID registers */
-#define CSID_HW_VERSION_ADDR 0x0
-#define CSID_CORE_CTRL_ADDR 0x4
-#define CSID_RST_CMD_ADDR 0x8
-#define CSID_CID_LUT_VC_0_ADDR 0xc
-#define CSID_CID_LUT_VC_1_ADDR 0x10
-#define CSID_CID_LUT_VC_2_ADDR 0x14
-#define CSID_CID_LUT_VC_3_ADDR 0x18
-#define CSID_CID_n_CFG_ADDR 0x1C
-#define CSID_IRQ_CLEAR_CMD_ADDR 0x5c
-#define CSID_IRQ_MASK_ADDR 0x60
-#define CSID_IRQ_STATUS_ADDR 0x64
-#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR 0x68
-#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR 0x6c
-#define CSID_CAPTURED_SHORT_PKT_ADDR 0x70
-#define CSID_CAPTURED_LONG_PKT_HDR_ADDR 0x74
-#define CSID_CAPTURED_LONG_PKT_FTR_ADDR 0x78
-#define CSID_PIF_MISR_DL0_ADDR 0x7C
-#define CSID_PIF_MISR_DL1_ADDR 0x80
-#define CSID_PIF_MISR_DL2_ADDR 0x84
-#define CSID_PIF_MISR_DL3_ADDR 0x88
-#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR 0x8C
-#define CSID_STATS_ECC_ADDR 0x90
-#define CSID_STATS_CRC_ADDR 0x94
-#define CSID_TG_CTRL_ADDR 0x9C
-#define CSID_TG_VC_CFG_ADDR 0xA0
-#define CSID_TG_DT_n_CFG_0_ADDR 0xA8
-#define CSID_TG_DT_n_CFG_1_ADDR 0xAC
-#define CSID_TG_DT_n_CFG_2_ADDR 0xB0
-#define CSID_TG_DT_n_CFG_3_ADDR 0xD8
-
-/* Regulator Voltage and Current */
-
#define CAM_VAF_MINUV 2800000
#define CAM_VAF_MAXUV 2800000
#define CAM_VDIG_MINUV 1200000
@@ -75,23 +41,15 @@
#define CAM_VANA_LOAD_UA 85600
#define CAM_CSI_LOAD_UA 20000
-#define CSID_VERSION_V2 0x2000011
-
-static uint32_t csid_hw_version;
static struct clk *camio_cam_clk;
static struct clk *camio_vfe_clk;
-static struct clk *camio_csi_src_clk;
-static struct clk *camio_csi1_src_clk;
static struct clk *camio_csi0_vfe_clk;
-static struct clk *camio_csi0_clk;
-static struct clk *camio_csi0_pclk;
static struct clk *camio_csi_pix_clk;
static struct clk *camio_csi_pix1_clk;
static struct clk *camio_csi_rdi_clk;
static struct clk *camio_csi_rdi1_clk;
static struct clk *camio_csi_rdi2_clk;
static struct clk *camio_vfe_pclk;
-static struct clk *camio_csi0_phy_clk;
/*static struct clk *camio_vfe_pclk;*/
static struct clk *camio_jpeg_clk;
@@ -109,10 +67,9 @@
static struct msm_camera_io_clk camio_clk;
static struct platform_device *camio_dev;
-static struct resource *csidio, *s3drw_io, *s3dctl_io;
-static struct resource *csid_mem, *s3drw_mem, *s3dctl_mem;
-static struct resource *csid_irq;
-void __iomem *csidbase, *s3d_rw, *s3d_ctl;
+static struct resource *s3drw_io, *s3dctl_io;
+static struct resource *s3drw_mem, *s3dctl_mem;
+void __iomem *s3d_rw, *s3d_ctl;
struct msm_bus_scale_pdata *cam_bus_scale_table;
@@ -441,28 +398,6 @@
clk = clk_get(&camio_dev->dev, "csi_vfe_clk");
break;
*/
- case CAMIO_CSI_SRC_CLK:
- camio_csi_src_clk =
- clk = clk_get(NULL, "csi_src_clk");
- msm_camio_clk_rate_set_2(clk, 177780000);
- break;
-
- case CAMIO_CSI1_SRC_CLK:
- camio_csi1_src_clk =
- clk = clk_get(&camio_dev->dev, "csi_src_clk");
- msm_camio_clk_rate_set_2(clk, 177780000);
- break;
-
- case CAMIO_CSI0_CLK:
- camio_csi0_clk =
- clk = clk_get(&camio_dev->dev, "csi_clk");
- break;
-
- case CAMIO_CSI0_PHY_CLK:
- camio_csi0_phy_clk =
- clk = clk_get(&camio_dev->dev, "csi_phy_clk");
- break;
-
case CAMIO_CSI_PIX_CLK:
camio_csi_pix_clk =
clk = clk_get(NULL, "csi_pix_clk");
@@ -498,11 +433,6 @@
msm_camio_clk_rate_set_2(clk, csid_core);
break;
- case CAMIO_CSI0_PCLK:
- camio_csi0_pclk =
- clk = clk_get(NULL, "csi_pclk");
- break;
-
case CAMIO_JPEG_CLK:
camio_jpeg_clk =
clk = clk_get(NULL, "ijpeg_clk");
@@ -562,18 +492,6 @@
clk = camio_csi0_vfe_clk;
break;
- case CAMIO_CSI_SRC_CLK:
- clk = camio_csi_src_clk;
- break;
-
- case CAMIO_CSI0_CLK:
- clk = camio_csi0_clk;
- break;
-
- case CAMIO_CSI0_PHY_CLK:
- clk = camio_csi0_phy_clk;
- break;
-
case CAMIO_CSI_PIX1_CLK:
clk = camio_csi_pix1_clk;
break;
@@ -594,10 +512,6 @@
clk = camio_csi_rdi_clk;
break;
- case CAMIO_CSI0_PCLK:
- clk = camio_csi0_pclk;
- break;
-
case CAMIO_JPEG_CLK:
clk = camio_jpeg_clk;
break;
@@ -666,73 +580,10 @@
clk_set_min_rate(clk, rate);
}
-#if DBG_CSID
-static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
-{
- uint32_t irq;
- irq = msm_io_r(csidbase + CSID_IRQ_STATUS_ADDR);
- CDBG("%s CSID_IRQ_STATUS_ADDR = 0x%x\n", __func__, irq);
- msm_io_w(irq, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
- return IRQ_HANDLED;
-}
-#endif
-
-static int msm_camio_enable_v2_clks(void)
-{
- int rc = 0;
- csid_hw_version = msm_io_r(csidbase +
- CSID_HW_VERSION_ADDR);
- CDBG("%s csid_hw_version %d\n",
- __func__,
- csid_hw_version);
-
- if (csid_hw_version == CSID_VERSION_V2) {
- rc = msm_camio_clk_enable(CAMIO_CSI_PIX1_CLK);
- if (rc < 0)
- goto csi_pix1_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI_RDI1_CLK);
- if (rc < 0)
- goto csi_rdi1_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI_RDI2_CLK);
- if (rc < 0)
- goto csi_rdi2_fail;
- }
-
- return rc;
-
-csi_rdi2_fail:
- msm_camio_clk_disable(CAMIO_CSI_RDI1_CLK);
-csi_rdi1_fail:
- msm_camio_clk_disable(CAMIO_CSI_PIX1_CLK);
-csi_pix1_fail:
- return rc;
-}
-
static int msm_camio_enable_all_clks(uint8_t csid_core)
{
int rc = 0;
- rc = msm_camio_clk_enable(CAMIO_CSI_SRC_CLK);
- if (rc < 0)
- goto csi_src_fail;
- if (csid_core == 1) {
- rc = msm_camio_clk_enable(CAMIO_CSI1_SRC_CLK);
- if (rc < 0)
- goto csi1_src_fail;
- }
- rc = msm_camio_clk_enable(CAMIO_CSI0_CLK);
- if (rc < 0)
- goto csi0_fail;
- rc = msm_camio_clk_enable(CAMIO_CSI0_PHY_CLK);
- if (rc < 0)
- goto csi0_phy_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI0_PCLK);
- if (rc < 0)
- goto csi0p_fail;
-
rc = msm_camio_clk_enable(CAMIO_VFE_CLK);
if (rc < 0)
goto vfe_fail;
@@ -760,42 +611,16 @@
vfep_fail:
msm_camio_clk_disable(CAMIO_VFE_CLK);
vfe_fail:
- msm_camio_clk_disable(CAMIO_CSI0_PCLK);
-csi0p_fail:
- msm_camio_clk_disable(CAMIO_CSI0_PHY_CLK);
-csi0_phy_fail:
- msm_camio_clk_disable(CAMIO_CSI0_CLK);
-csi0_fail:
- msm_camio_clk_disable(CAMIO_CSI1_SRC_CLK);
-csi1_src_fail:
- msm_camio_clk_disable(CAMIO_CSI_SRC_CLK);
-csi_src_fail:
return rc;
}
-static void msm_camio_disable_v2_clks(void)
-{
- if (csid_hw_version == CSID_VERSION_V2) {
- msm_camio_clk_disable(CAMIO_CSI_RDI2_CLK);
- msm_camio_clk_disable(CAMIO_CSI_RDI1_CLK);
- msm_camio_clk_disable(CAMIO_CSI_PIX1_CLK);
- }
-}
-
static void msm_camio_disable_all_clks(uint8_t csid_core)
{
- msm_camio_disable_v2_clks();
msm_camio_clk_disable(CAMIO_CSI_RDI_CLK);
msm_camio_clk_disable(CAMIO_CSI_PIX_CLK);
msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
msm_camio_clk_disable(CAMIO_VFE_PCLK);
msm_camio_clk_disable(CAMIO_VFE_CLK);
- msm_camio_clk_disable(CAMIO_CSI0_PCLK);
- msm_camio_clk_disable(CAMIO_CSI0_PHY_CLK);
- msm_camio_clk_disable(CAMIO_CSI0_CLK);
- if (csid_core == 1)
- msm_camio_clk_disable(CAMIO_CSI1_SRC_CLK);
- msm_camio_clk_disable(CAMIO_CSI_SRC_CLK);
}
int msm_camio_jpeg_clk_disable(void)
@@ -915,11 +740,6 @@
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;
- char csid[] = "csid0";
- if (csid_core < 0 || csid_core > 2)
- return -ENODEV;
-
- csid[4] = '0' + csid_core;
camio_dev = pdev;
camio_clk = camdev->ioclk;
@@ -927,48 +747,12 @@
rc = msm_camio_enable_all_clks(csid_core);
if (rc < 0)
- return rc;
-
- csid_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, csid);
- if (!csid_mem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
- csid_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, csid);
- if (!csid_irq) {
- pr_err("%s: no irq resource?\n", __func__);
- return -ENODEV;
- }
-
- csidio = request_mem_region(csid_mem->start,
- resource_size(csid_mem), pdev->name);
- if (!csidio) {
- rc = -EBUSY;
goto common_fail;
- }
- csidbase = ioremap(csid_mem->start,
- resource_size(csid_mem));
- if (!csidbase) {
- rc = -ENOMEM;
- goto csi_busy;
- }
-#if DBG_CSID
- rc = request_irq(csid_irq->start, msm_io_csi_irq,
- IRQF_TRIGGER_RISING, "csid", 0);
- if (rc < 0)
- goto csi_irq_fail;
-#endif
- msm_camio_enable_v2_clks();
+
CDBG("camio enable done\n");
return 0;
-#if DBG_CSID
-csi_irq_fail:
- iounmap(csidbase);
-#endif
-csi_busy:
- release_mem_region(csid_mem->start, resource_size(csid_mem));
+
common_fail:
- msm_camio_disable_all_clks(csid_core);
msm_camera_vreg_disable();
config_gpio_table(0);
return rc;
@@ -979,12 +763,6 @@
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;
-#if DBG_CSID
- free_irq(csid_irq->start, 0);
-#endif
- iounmap(csidbase);
- release_mem_region(csid_mem->start, resource_size(csid_mem));
-
msm_camio_disable_all_clks(csid_core);
}
@@ -1135,55 +913,6 @@
return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
}
-int msm_camio_csid_cid_lut(struct msm_camera_csid_lut_params *csid_lut_params)
-{
- int rc = 0, i = 0;
- uint32_t val = 0;
-
- for (i = 0; i < csid_lut_params->num_cid && i < 4; i++) {
- if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
- csid_lut_params->vc_cfg[i].dt > 0x37) {
- CDBG("%s: unsupported data type 0x%x\n",
- __func__, csid_lut_params->vc_cfg[i].dt);
- return rc;
- }
- val = msm_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
- (csid_lut_params->vc_cfg[i].cid >> 2) * 4)
- & ~(0xFF << csid_lut_params->vc_cfg[i].cid * 8);
- val |= csid_lut_params->vc_cfg[i].dt <<
- csid_lut_params->vc_cfg[i].cid * 8;
- msm_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
- (csid_lut_params->vc_cfg[i].cid >> 2) * 4);
- val = csid_lut_params->vc_cfg[i].decode_format << 4 | 0x3;
- msm_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
- (csid_lut_params->vc_cfg[i].cid * 4));
- }
- return rc;
-}
-
-int msm_camio_csid_config(struct msm_camera_csid_params *csid_params)
-{
- int rc = 0;
- uint32_t val = 0;
- val = csid_params->lane_cnt - 1;
- val |= csid_params->lane_assign << 2;
- val |= 0x1 << 10;
- val |= 0x1 << 11;
- val |= 0x1 << 12;
- val |= 0x1 << 28;
- msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
-
- rc = msm_camio_csid_cid_lut(&csid_params->lut_params);
- if (rc < 0)
- return rc;
-
- msm_io_w(0x7fF10800, csidbase + CSID_IRQ_MASK_ADDR);
- msm_io_w(0x7fF10800, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
-
- msleep(20);
- return rc;
-}
-
void msm_camio_mode_config(enum msm_cam_mode mode)
{
uint32_t val;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 1a5b14c..406dbae 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -28,6 +28,7 @@
#include <linux/android_pmem.h>
#include "msm.h"
+#include "msm_csid.h"
#include "msm_csiphy.h"
#include "msm_ispif.h"
@@ -224,6 +225,10 @@
rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
break;
+ case NOTIFY_CSID_CFG:
+ rc = v4l2_subdev_call(p_mctl->csid_sdev,
+ core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
+ break;
default:
break;
}
@@ -349,6 +354,19 @@
p_mctl->csiphy_sdev = dev_get_drvdata(dev);
put_driver(driver);
+ /* register csid subdev */
+ driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, (void *)core_index,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->csid_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+
rc = 0;
return rc;
out_put_driver:
@@ -377,6 +395,7 @@
mutex_lock(&sync->lock);
/* open sub devices - once only*/
if (!sync->opencnt) {
+ uint32_t csid_version;
wake_lock(&sync->wake_lock);
sinfo = sync->pdev->dev.platform_data;
@@ -397,6 +416,22 @@
goto msm_open_done;
}
+ rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+ VIDIOC_MSM_CSIPHY_INIT, NULL);
+ if (rc < 0) {
+ pr_err("%s: csiphy initialization failed %d\n",
+ __func__, rc);
+ goto msm_open_done;
+ }
+
+ rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+ VIDIOC_MSM_CSID_INIT, &csid_version);
+ if (rc < 0) {
+ pr_err("%s: csid initialization failed %d\n",
+ __func__, rc);
+ goto msm_open_done;
+ }
+
/* ISP first*/
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open)
rc = p_mctl->isp_sdev->isp_open(
@@ -407,14 +442,6 @@
goto msm_open_done;
}
- rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
- VIDIOC_MSM_CSIPHY_INIT, NULL);
- if (rc < 0) {
- pr_err("%s: csiphy initialization failed %d\n",
- __func__, rc);
- goto msm_open_done;
- }
-
/*This has to be after isp_open, because isp_open initialize
*platform resource. This dependency needs to be removed. */
rc = msm_ispif_init(&p_mctl->ispif_sdev, sync->pdev);
@@ -454,12 +481,15 @@
struct msm_sync *sync = &(p_mctl->sync);
msm_ispif_release(p_mctl->ispif_sdev);
- v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
- VIDIOC_MSM_CSIPHY_RELEASE, NULL);
-
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
p_mctl->isp_sdev->isp_release(&p_mctl->sync);
+ v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+ VIDIOC_MSM_CSID_RELEASE, NULL);
+
+ v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+ VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+
if (p_mctl->sync.actctrl.a_power_down)
p_mctl->sync.actctrl.a_power_down();
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index c31e750..76ade6c 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -238,7 +238,8 @@
msm_sensor_write_res_settings(s_ctrl, res);
if (s_ctrl->curr_csi_params != s_ctrl->csi_params[res]) {
s_ctrl->curr_csi_params = s_ctrl->csi_params[res];
- rc = msm_camio_csid_config(
+ v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_CSID_CFG,
&s_ctrl->curr_csi_params->csid_params);
v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
NOTIFY_CID_CHANGE, NULL);