diff options
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, |