media: tegra_camera: vi2: support for real sensor
Bryan Wu [Wed, 20 Nov 2013 00:59:23 +0000 (16:59 -0800)]
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>

drivers/media/platform/soc_camera/tegra_camera/common.c
drivers/media/platform/soc_camera/tegra_camera/common.h
drivers/media/platform/soc_camera/tegra_camera/vi2.c

index 0076fbb..d06ee4a 100644 (file)
@@ -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;
index 3e713c8..ab1a9af 100644 (file)
@@ -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)
index b97e0b3..95f88bf 100644 (file)
@@ -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,