summaryrefslogtreecommitdiff
path: root/drivers/media/platform/soc_camera
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2013-11-19 16:59:23 -0800
committerWinnie Hsu <whsu@nvidia.com>2014-09-26 10:49:14 -0700
commit447dd3f018c3a63350f10e67ba5edf02c77efeba (patch)
tree5ddcaf75ef21273fd0f00223f146665acdb232a3 /drivers/media/platform/soc_camera
parenta4201ceac4a89a495d759885b1e2d5a1c1466073 (diff)
media: tegra_camera: vi2: support for real sensor
Add code to support RAW10 capture from real sensor like IMX135. Add flag to skip register program from second frame. Fix sync point operations. Bug 1380143 Change-Id: I19bcd17ddfba0e16b4b3a34ae8a4e5a0119e85e1 Signed-off-by: Bryan Wu <pengw@nvidia.com> Reviewed-on: http://git-master/r/337470 (cherry picked from commit ff1055fa436ffb5c1d57eee2e09c17578774d65f) Reviewed-on: http://git-master/r/498936 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Diffstat (limited to 'drivers/media/platform/soc_camera')
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/common.c51
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/common.h2
-rw-r--r--drivers/media/platform/soc_camera/tegra_camera/vi2.c148
3 files changed, 125 insertions, 76 deletions
diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.c b/drivers/media/platform/soc_camera/tegra_camera/common.c
index 0076fbb6a4fc..d06ee4ac18bb 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/common.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/common.c
@@ -111,6 +111,13 @@ static const struct soc_mbus_pixelfmt tegra_camera_formats[] = {
.order = SOC_MBUS_ORDER_LE,
},
{
+ .fourcc = V4L2_PIX_FMT_SRGGB10,
+ .name = "Bayer 10 RGRG.. GBGB..",
+ .bits_per_sample = 16,
+ .packing = SOC_MBUS_PACKING_EXTEND16,
+ .order = SOC_MBUS_ORDER_LE,
+ },
+ {
.fourcc = V4L2_PIX_FMT_RGB32,
.name = "RGBA 8-8-8-8",
.bits_per_sample = 32,
@@ -149,8 +156,7 @@ static int tegra_camera_activate(struct tegra_camera_dev *cam)
if (cam_ops->capture_clean)
cam_ops->capture_clean(cam);
- if (cam_ops->save_syncpts)
- cam_ops->save_syncpts(cam);
+ cam->sof = 1;
return 0;
}
@@ -173,6 +179,8 @@ static void tegra_camera_deactivate(struct tegra_camera_dev *cam)
regulator_disable(cam->reg);
nvhost_module_idle_ext(cam->ndev);
+
+ cam->sof = 0;
}
static int tegra_camera_capture_frame(struct tegra_camera_dev *cam)
@@ -189,6 +197,8 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam)
/* Setup capture registers */
cam->ops->capture_setup(cam);
+ cam->ops->incr_syncpts(cam);
+
while (retry) {
err = cam->ops->capture_start(cam, buf);
/* Capturing succeed, stop capturing */
@@ -197,7 +207,8 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam)
retry--;
cam->ops->incr_syncpts(cam);
- cam->ops->save_syncpts(cam);
+ if (cam->ops->save_syncpts)
+ cam->ops->save_syncpts(cam);
continue;
}
@@ -277,6 +288,7 @@ static int tegra_camera_init_buffer(struct tegra_camera_buffer *buf)
case V4L2_PIX_FMT_SBGGR8:
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_RGB32:
buf->buffer_addr = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
buf->start_addr = buf->buffer_addr;
@@ -611,6 +623,7 @@ static int tegra_camera_get_formats(struct soc_camera_device *icd,
case V4L2_MBUS_FMT_SBGGR8_1X8:
case V4L2_MBUS_FMT_SGBRG8_1X8:
case V4L2_MBUS_FMT_SBGGR10_1X10:
+ case V4L2_MBUS_FMT_SRGGB10_1X10:
case V4L2_MBUS_FMT_RGBA8888_4X8_LE:
formats += ARRAY_SIZE(tegra_camera_formats);
for (k = 0;
@@ -819,7 +832,16 @@ static int tegra_camera_probe(struct platform_device *pdev)
goto exit;
}
- cam = kzalloc(sizeof(struct tegra_camera_dev), GFP_KERNEL);
+ /* vi.1 has to wait vi.0 initialized, so defer probing */
+ if (pdev->id && ndata->master) {
+ struct nvhost_device_data *master_ndata =
+ ndata->master->dev.platform_data;
+ if (master_ndata == platform_get_drvdata(ndata->master))
+ return -EPROBE_DEFER;
+ }
+
+ cam = devm_kzalloc(&pdev->dev, sizeof(struct tegra_camera_dev),
+ GFP_KERNEL);
if (!cam) {
dev_err(&pdev->dev, "couldn't allocate cam\n");
err = -ENOMEM;
@@ -885,14 +907,22 @@ static int tegra_camera_probe(struct platform_device *pdev)
/* Init syncpts */
cam->ops->init_syncpts(cam);
- cam->reg_base = ndata->aperture[0];
- if (!cam->reg_base) {
- dev_err(&pdev->dev, "%s: failed to map register base\n",
+ if (!ndata->aperture[0]) {
+ if (ndata->master) {
+ struct nvhost_device_data *master_ndata =
+ ndata->master->dev.platform_data;
+ ndata->aperture[0] = master_ndata->aperture[0];
+ } else {
+ dev_err(&pdev->dev, "%s: failed to map register base\n",
__func__);
- err = -ENXIO;
- goto exit_free_syncpts;
+ err = -ENXIO;
+ goto exit_free_syncpts;
+ }
}
+ cam->reg_base = ndata->aperture[0];
+ /* Match the nvhost_module_init VENC powergating */
+ tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
nvhost_module_init(pdev);
err = nvhost_client_device_init(pdev);
@@ -924,7 +954,6 @@ exit_free_syncpts:
cam->ops->free_syncpts(cam);
exit_deinit_clk:
cam->ops->clks_deinit(cam);
- kfree(cam);
exit:
return err;
}
@@ -949,8 +978,6 @@ static int tegra_camera_remove(struct platform_device *pdev)
if (cam->ops)
cam->ops->clks_deinit(cam);
- kfree(cam);
-
dev_notice(&pdev->dev, "Tegra camera host driver unloaded\n");
return 0;
diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.h b/drivers/media/platform/soc_camera/tegra_camera/common.h
index 3e713c8c550d..ab1a9af15d9f 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/common.h
+++ b/drivers/media/platform/soc_camera/tegra_camera/common.h
@@ -118,6 +118,8 @@ struct tegra_camera_dev {
/* Test Pattern Generator mode */
int tpg_mode;
+
+ int sof;
};
#define TC_VI_REG_RD(dev, offset) readl(dev->reg_base + offset)
diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
index b97e0b341fe0..95f88bfd4129 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
@@ -236,7 +236,7 @@ static int vi2_port_is_valid(int port)
static struct tegra_camera_clk vi2_clks0[] = {
{
.name = "vi",
- .freq = 150000000,
+ .freq = 408000000,
.use_devname = 1,
},
{
@@ -245,7 +245,7 @@ static struct tegra_camera_clk vi2_clks0[] = {
},
{
.name = "csi",
- .freq = 0,
+ .freq = 408000000,
.use_devname = 1,
},
{
@@ -263,7 +263,7 @@ static struct tegra_camera_clk vi2_clks0[] = {
},
{
.name = "emc",
- .freq = 375000000,
+ .freq = 300000000,
},
{
.name = "cilab",
@@ -280,7 +280,7 @@ static struct tegra_camera_clk vi2_clks0[] = {
static struct tegra_camera_clk vi2_clks1[] = {
{
.name = "vi",
- .freq = 150000000,
+ .freq = 408000000,
.use_devname = 1,
},
{
@@ -289,7 +289,7 @@ static struct tegra_camera_clk vi2_clks1[] = {
},
{
.name = "csi",
- .freq = 0,
+ .freq = 408000000,
.use_devname = 1,
},
{
@@ -302,7 +302,7 @@ static struct tegra_camera_clk vi2_clks1[] = {
},
{
.name = "emc",
- .freq = 375000000,
+ .freq = 300000000,
},
{
.name = "cilcd",
@@ -442,37 +442,37 @@ static void vi2_free_syncpts(struct tegra_camera_dev *cam)
nvhost_free_syncpt(cam->syncpt_id_csi_b);
}
-static void vi2_save_syncpts(struct tegra_camera_dev *cam)
+static void vi2_incr_syncpts(struct tegra_camera_dev *cam)
{
u32 val;
if (!nvhost_syncpt_read_ext_check(cam->ndev,
cam->syncpt_id_csi_a, &val))
- cam->syncpt_csi_a = val;
+ cam->syncpt_csi_a = nvhost_syncpt_incr_max_ext(cam->ndev,
+ cam->syncpt_id_csi_a, 1);
if (!nvhost_syncpt_read_ext_check(cam->ndev,
cam->syncpt_id_csi_b, &val))
- cam->syncpt_csi_b = val;
-}
-
-static void vi2_incr_syncpts(struct tegra_camera_dev *cam)
-{
- nvhost_syncpt_cpu_incr_ext(cam->ndev, cam->syncpt_id_csi_a);
-
- nvhost_syncpt_cpu_incr_ext(cam->ndev, cam->syncpt_id_csi_b);
+ cam->syncpt_csi_b = nvhost_syncpt_incr_max_ext(cam->ndev,
+ cam->syncpt_id_csi_b, 1);
}
static void vi2_capture_clean(struct tegra_camera_dev *cam)
{
/* Clean up status */
TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_A_STATUS, 0xFFFFFFFF);
- TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILA_STATUS, 0xFFFFFFFF);
TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_B_STATUS, 0xFFFFFFFF);
TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_C_STATUS, 0xFFFFFFFF);
TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_D_STATUS, 0xFFFFFFFF);
TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_E_STATUS, 0xFFFFFFFF);
+ TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILA_STATUS, 0xFFFFFFFF);
+ TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILB_STATUS, 0xFFFFFFFF);
+ TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILC_STATUS, 0xFFFFFFFF);
+ TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILD_STATUS, 0xFFFFFFFF);
TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS, 0xFFFFFFFF);
+ TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS, 0xFFFFFFFF);
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_ERROR_STATUS, 0xFFFFFFFF);
+ TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_ERROR_STATUS, 0xFFFFFFFF);
}
static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
@@ -495,10 +495,6 @@ static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
else
TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020201);
- /* VI_MWA_REQ_DONE */
- TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
- (0x4 << 8) | cam->syncpt_id_csi_a);
-
if (cam->tpg_mode) {
TC_VI_REG_WT(cam, TEGRA_CSI_PATTERN_GENERATOR_CTRL_A,
((cam->tpg_mode - 1) << 2) | 0x1);
@@ -515,13 +511,21 @@ static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_IMAGE_DEF, (64 << 16) | 0x1);
/* input format is RGB888 */
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_DT, 36);
+
+ TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
+ icd->user_width * 3);
+ } else {
+ /* output format RAW10 T_R16_I, only support direct to mem */
+ TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_IMAGE_DEF, (32 << 16) | 0x1);
+ /* input format is RAW10 */
+ TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_DT, 43);
+
+ TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
+ icd->user_width * 10 / 8);
}
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE,
- (icd->user_height << 16) | icd->user_width);
-
- TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
- icd->user_width * 3);
+ (icd->user_height << 16) | icd->user_width);
return 0;
}
@@ -548,10 +552,6 @@ static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
else
TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22010202);
- /* VI_MWB_REQ_DONE */
- TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
- (0x5 << 8) | cam->syncpt_id_csi_b);
-
if (cam->tpg_mode) {
TC_VI_REG_WT(cam, TEGRA_CSI_PATTERN_GENERATOR_CTRL_B,
((cam->tpg_mode - 1) << 2) | 0x1);
@@ -588,11 +588,14 @@ static int vi2_capture_setup(struct tegra_camera_dev *cam)
struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
int port = pdata->port;
- /*
- * MIPI pad controls
- * MIPI_CAL_MIPI_BIAS_PAD_CFG0_0 MIPI_BIAS_PAD_E_VCLAMP_REF 1
- * MIPI_CAL_MIPI_BIAS_PAD_CFG2_0 PAD_PDVREG 0
- */
+ /* Skip VI2/CSI2 setup for second and later frame capture */
+ if (!cam->sof)
+ return 0;
+
+#ifdef DEBUG
+ TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_CONTROL,
+ 0x3 | (0x1 << 5) | (0x40 << 8));
+#endif
/*
* PAD_CILA_PDVCLAMP 0, PAD_CILA_PDIO_CLK 0,
@@ -663,6 +666,7 @@ static int vi2_capture_buffer_setup(struct tegra_camera_dev *cam,
case V4L2_PIX_FMT_SBGGR8:
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_RGB32:
switch (buf->output_channel) {
case 0:
@@ -701,6 +705,43 @@ static int vi2_capture_buffer_setup(struct tegra_camera_dev *cam,
return 0;
}
+static int vi2_capture_error_status(struct tegra_camera_dev *cam)
+{
+ int err;
+
+#ifdef DEBUG
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_DEBUG_COUNTER_0);
+ if (err)
+ pr_err("TEGRA_CSI_DEBUG_COUNTER_0 0x%08x\n", err);
+#endif
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_CIL_A_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CILA_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_CILA_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_B_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_CIL_B_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_C_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_CIL_C_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_D_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_CIL_D_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_E_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_CIL_E_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS);
+ if (err)
+ pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS 0x%08x\n", err);
+ err = TC_VI_REG_RD(cam, TEGRA_VI_CSI_0_ERROR_STATUS);
+ if (err)
+ pr_err("TEGRA_VI_CSI_0_ERROR_STATUS 0x%08x\n", err);
+
+ return err;
+}
+
static int vi2_capture_start(struct tegra_camera_dev *cam,
struct tegra_camera_buffer *buf)
{
@@ -716,7 +757,8 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
/* Only wait on CSI frame end syncpt if we're using CSI. */
if (port == TEGRA_CAMERA_PORT_CSI_A) {
- cam->syncpt_csi_a++;
+ TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
+ (6 << 8) | cam->syncpt_id_csi_a);
TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
0x0000f005);
TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SINGLE_SHOT, 0x1);
@@ -727,7 +769,8 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
NULL,
NULL);
} else if (port == TEGRA_CAMERA_PORT_CSI_B) {
- cam->syncpt_csi_b++;
+ TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
+ (7 << 8) | cam->syncpt_id_csi_b);
TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
0x0000f005);
TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_SINGLE_SHOT, 0x1);
@@ -739,35 +782,13 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
NULL);
}
- if (!err)
- return 0;
+ /* Mark SOF flag to Zero after we captured the FIRST frame */
+ if (cam->sof)
+ cam->sof = 0;
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
+ /* Capture syncpt timeout err, then dump error status */
if (err)
- pr_err("TEGRA_CSI_CSI_CIL_A_STATUS 0x%08x\n", err);
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CILA_STATUS);
- if (err)
- pr_err("TEGRA_CSI_CSI_CILA_STATUS 0x%08x\n", err);
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_B_STATUS);
- if (err)
- pr_err("TEGRA_CSI_CSI_CIL_B_STATUS 0x%08x\n", err);
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_C_STATUS);
- if (err)
- pr_err("TEGRA_CSI_CSI_CIL_C_STATUS 0x%08x\n", err);
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_D_STATUS);
- if (err)
- pr_err("TEGRA_CSI_CSI_CIL_D_STATUS 0x%08x\n", err);
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_E_STATUS);
- if (err)
- pr_err("TEGRA_CSI_CSI_CIL_E_STATUS 0x%08x\n", err);
-
- err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS);
- if (err)
- pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS 0x%08x\n", err);
-
- err = TC_VI_REG_RD(cam, TEGRA_VI_CSI_0_ERROR_STATUS);
- if (err)
- pr_err("TEGRA_VI_CSI_0_ERROR_STATUS 0x%08x\n", err);
+ err = vi2_capture_error_status(cam);
return err;
}
@@ -810,7 +831,6 @@ struct tegra_camera_ops vi2_ops = {
.init_syncpts = vi2_init_syncpts,
.free_syncpts = vi2_free_syncpts,
- .save_syncpts = vi2_save_syncpts,
.incr_syncpts = vi2_incr_syncpts,
.port_is_valid = vi2_port_is_valid,