summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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,