media: tegra_v4l2_camera: add CSI_B/CSI_C support
Bryan Wu [Fri, 19 Sep 2014 00:45:35 +0000 (17:45 -0700)]
Bug 1560636

Change-Id: I2d27c631da0f4b6540af9b4da9ba9e212a4a56c5
Signed-off-by: Bryan Wu <pengw@nvidia.com>
Reviewed-on: http://git-master/r/539003
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
(cherry picked from commit e9b82e8a6e6edf5fc00e88c8610b9c2bb67f3872)
Reviewed-on: http://git-master/r/665996
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Winnie Hsu <whsu@nvidia.com>

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

index 09a3a61..8937eb8 100644 (file)
 static int vi2_port_is_valid(int port)
 {
        return (((port) >= TEGRA_CAMERA_PORT_CSI_A) &&
-               ((port) <= TEGRA_CAMERA_PORT_CSI_E));
+               ((port) <= TEGRA_CAMERA_PORT_CSI_C));
 }
 
 /* Clock settings for camera */
@@ -544,6 +544,13 @@ static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
        struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
        int format = 0, data_type = 0, image_size = 0;
 
+#ifdef DEBUG
+       TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_CONTROL,
+                       0x3 | (0x1 << 5) | (0x40 << 8));
+#endif
+
+       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILA_CONTROL0, 0x9);
+       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILB_CONTROL0, 0x9);
        TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0xf007);
        TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK, 0x0);
        TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, 0x280301f0);
@@ -610,6 +617,17 @@ static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
        struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
        int format = 0, data_type = 0, image_size = 0;
 
+#ifdef DEBUG
+       TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_CONTROL,
+                       0x5 | (0x1 << 5) | (0x50 << 8));
+#endif
+
+       if (pdata->port == TEGRA_CAMERA_PORT_CSI_B) {
+               TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILC_CONTROL0, 0x9);
+               TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILD_CONTROL0, 0x9);
+       } else if (pdata->port == TEGRA_CAMERA_PORT_CSI_C)
+               TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILE_CONTROL0, 0x9);
+
        TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0xf007);
        TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_INTERRUPT_MASK, 0x0);
        TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x280301f1);
@@ -621,7 +639,7 @@ static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
                        0x3f0000 | (pdata->lanes - 1));
        if (pdata->lanes == 4)
                TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x21010202);
-       else if (pdata->lanes == 1 && pdata->port == TEGRA_CAMERA_PORT_CSI_E)
+       else if (pdata->lanes == 1 && pdata->port == TEGRA_CAMERA_PORT_CSI_C)
                TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x12020202);
        else
                TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22010202);
@@ -665,6 +683,9 @@ static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
 
        TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE_WC, image_size);
 
+       TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE,
+                       (icd->user_height << 16) | icd->user_width);
+
        return 0;
 }
 
@@ -681,11 +702,6 @@ static int vi2_capture_setup(struct tegra_camera_dev *cam)
        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,
         * PAD_CILA_PDIO 0, PAD_AB_BK_MODE 1
@@ -716,21 +732,11 @@ static int vi2_capture_setup(struct tegra_camera_dev *cam)
        TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_D_INTERRUPT_MASK, 0x0);
        TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_E_INTERRUPT_MASK, 0x0);
 
-       /*
-        * TODO: these values should be different with different
-        * sensor connected.
-        * Hardcode THS settle value just for TPG testing
-        */
-       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILA_CONTROL0, 0x8);
-       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILB_CONTROL0, 0x8);
-       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILC_CONTROL0, 0xa);
-       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILD_CONTROL0, 0xa);
-       TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILE_CONTROL0, 0xa);
-
        /* Setup registers for CSI-A and CSI-B inputs */
        if (port == TEGRA_CAMERA_PORT_CSI_A)
                return vi2_capture_setup_csi_0(cam, icd);
-       else if (port == TEGRA_CAMERA_PORT_CSI_B)
+       else if (port == TEGRA_CAMERA_PORT_CSI_B ||
+                       port == TEGRA_CAMERA_PORT_CSI_C)
                return vi2_capture_setup_csi_1(cam, icd);
        else
                return -ENODEV;
@@ -742,6 +748,9 @@ static int vi2_capture_buffer_setup(struct tegra_camera_dev *cam,
        struct soc_camera_device *icd = buf->icd;
        int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
                        icd->current_fmt->host_fmt);
+       struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
+       struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
+       int port = pdata->port;
 
        switch (icd->current_fmt->host_fmt->fourcc) {
        case V4L2_PIX_FMT_YUV420:
@@ -757,31 +766,79 @@ static int vi2_capture_buffer_setup(struct tegra_camera_dev *cam,
        case V4L2_PIX_FMT_SBGGR10:
        case V4L2_PIX_FMT_SRGGB10:
        case V4L2_PIX_FMT_RGB32:
-               switch (buf->output_channel) {
-               case 0:
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_OFFSET_MSB,
-                                    0x0);
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_OFFSET_LSB,
-                                    buf->buffer_addr);
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_STRIDE,
-                                    bytes_per_line);
-                       break;
-               case 1:
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_OFFSET_MSB,
-                                    0x0);
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_OFFSET_LSB,
-                                    buf->buffer_addr);
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_STRIDE,
-                                    bytes_per_line);
-                       break;
-               case 2:
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_OFFSET_MSB,
-                                    0x0);
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_OFFSET_LSB,
-                                    buf->buffer_addr);
-                       TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_STRIDE,
-                                    bytes_per_line);
-                       break;
+               if (port == TEGRA_CAMERA_PORT_CSI_A) {
+                       switch (buf->output_channel) {
+                       case 0:
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE0_OFFSET_MSB,
+                                            0x0);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE0_OFFSET_LSB,
+                                            buf->buffer_addr);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE0_STRIDE,
+                                            bytes_per_line);
+                               break;
+                       case 1:
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE1_OFFSET_MSB,
+                                            0x0);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE1_OFFSET_LSB,
+                                            buf->buffer_addr);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE1_STRIDE,
+                                            bytes_per_line);
+                               break;
+                       case 2:
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE2_OFFSET_MSB,
+                                            0x0);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE2_OFFSET_LSB,
+                                            buf->buffer_addr);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_0_SURFACE2_STRIDE,
+                                            bytes_per_line);
+                               break;
+                       }
+               } else if (port == TEGRA_CAMERA_PORT_CSI_B ||
+                       port == TEGRA_CAMERA_PORT_CSI_C) {
+                       switch (buf->output_channel) {
+                       case 0:
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE0_OFFSET_MSB,
+                                            0x0);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE0_OFFSET_LSB,
+                                            buf->buffer_addr);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE0_STRIDE,
+                                            bytes_per_line);
+                               break;
+                       case 1:
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE1_OFFSET_MSB,
+                                            0x0);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE1_OFFSET_LSB,
+                                            buf->buffer_addr);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE1_STRIDE,
+                                            bytes_per_line);
+                               break;
+                       case 2:
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE2_OFFSET_MSB,
+                                            0x0);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE2_OFFSET_LSB,
+                                            buf->buffer_addr);
+                               TC_VI_REG_WT(cam,
+                                            TEGRA_VI_CSI_1_SURFACE2_STRIDE,
+                                            bytes_per_line);
+                               break;
+                       }
                }
                break;
 
@@ -816,8 +873,12 @@ static void vi2_capture_error_status(struct tegra_camera_dev *cam)
        pr_err("TEGRA_CSI_CSI_CIL_E_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS);
        pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS 0x%08x\n", val);
+       val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS);
+       pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_VI_CSI_0_ERROR_STATUS);
        pr_err("TEGRA_VI_CSI_0_ERROR_STATUS 0x%08x\n", val);
+       val = TC_VI_REG_RD(cam, TEGRA_VI_CSI_1_ERROR_STATUS);
+       pr_err("TEGRA_VI_CSI_1_ERROR_STATUS 0x%08x\n", val);
 }
 
 static int vi2_capture_start(struct tegra_camera_dev *cam,
@@ -846,7 +907,8 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
                                TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
                                NULL,
                                NULL);
-       } else if (port == TEGRA_CAMERA_PORT_CSI_B) {
+       } else if (port == TEGRA_CAMERA_PORT_CSI_B ||
+                       port == TEGRA_CAMERA_PORT_CSI_C) {
                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,
@@ -870,9 +932,10 @@ static int vi2_capture_start(struct tegra_camera_dev *cam,
                        dev_err(&cam->ndev->dev,
                                "CSI_A syncpt timeout, syncpt = %d, err = %d\n",
                                cam->syncpt_csi_a, err);
-               else if (port == TEGRA_CAMERA_PORT_CSI_B)
+               else if (port == TEGRA_CAMERA_PORT_CSI_B ||
+                               port == TEGRA_CAMERA_PORT_CSI_C)
                        dev_err(&cam->ndev->dev,
-                               "CSI_B syncpt timeout, syncpt = %d, err = %d\n",
+                               "CSI_B/CSI_C syncpt timeout, syncpt = %d, err = %d\n",
                                cam->syncpt_csi_b, err);
                vi2_capture_error_status(cam);
        }
@@ -885,7 +948,8 @@ static int vi2_capture_stop(struct tegra_camera_dev *cam, int port)
        if (port == TEGRA_CAMERA_PORT_CSI_A)
                TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
                             0x0000f002);
-       else if (port == TEGRA_CAMERA_PORT_CSI_B)
+       else if (port == TEGRA_CAMERA_PORT_CSI_B ||
+                       port == TEGRA_CAMERA_PORT_CSI_C)
                TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
                             0x0000f002);