From 5cc760088433a2b55c0f9d02b5279732eda335b5 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Thu, 18 Sep 2014 17:45:35 -0700 Subject: media: tegra_v4l2_camera: add CSI_B/CSI_C support Bug 1560636 Change-Id: I2d27c631da0f4b6540af9b4da9ba9e212a4a56c5 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/539003 Reviewed-by: Venkat Moganty (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 --- .../media/platform/soc_camera/tegra_camera/vi2.c | 160 ++++++++++++++------- 1 file changed, 112 insertions(+), 48 deletions(-) (limited to 'drivers/media/platform/soc_camera/tegra_camera/vi2.c') diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c index 09a3a6173a9f..8937eb813ea7 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c +++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c @@ -289,7 +289,7 @@ 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); -- cgit v1.2.3