diff options
Diffstat (limited to 'drivers/staging/media/tegra-video/csi.c')
-rw-r--r-- | drivers/staging/media/tegra-video/csi.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 36ca639622c9..052172017b3b 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -328,12 +328,42 @@ static int tegra_csi_enable_stream(struct v4l2_subdev *subdev) } csi_chan->pg_mode = chan->pg_mode; + + /* + * Tegra CSI receiver can detect the first LP to HS transition. + * So, start the CSI stream-on prior to sensor stream-on and + * vice-versa for stream-off. + */ ret = csi->ops->csi_start_streaming(csi_chan); if (ret < 0) goto finish_calibration; + if (csi_chan->mipi) { + struct v4l2_subdev *src_subdev; + /* + * TRM has incorrectly documented to wait for done status from + * calibration logic after CSI interface power on. + * As per the design, calibration results are latched and applied + * to the pads only when the link is in LP11 state which will happen + * during the sensor stream-on. + * CSI subdev stream-on triggers start of MIPI pads calibration. + * Wait for calibration to finish here after sensor subdev stream-on. + */ + src_subdev = tegra_channel_get_remote_source_subdev(chan); + ret = v4l2_subdev_call(src_subdev, video, s_stream, true); + + if (ret < 0 && ret != -ENOIOCTLCMD) + goto disable_csi_stream; + + err = tegra_mipi_finish_calibration(csi_chan->mipi); + if (err < 0) + dev_warn(csi->dev, "MIPI calibration failed: %d\n", err); + } + return 0; +disable_csi_stream: + csi->ops->csi_stop_streaming(csi_chan); finish_calibration: if (csi_chan->mipi) tegra_mipi_finish_calibration(csi_chan->mipi); @@ -352,10 +382,24 @@ rpm_put: static int tegra_csi_disable_stream(struct v4l2_subdev *subdev) { + struct tegra_vi_channel *chan = v4l2_get_subdev_hostdata(subdev); struct tegra_csi_channel *csi_chan = to_csi_chan(subdev); struct tegra_csi *csi = csi_chan->csi; int err; + /* + * Stream-off subdevices in reverse order to stream-on. + * Remote source subdev in TPG mode is same as CSI subdev. + */ + if (csi_chan->mipi) { + struct v4l2_subdev *src_subdev; + + src_subdev = tegra_channel_get_remote_source_subdev(chan); + err = v4l2_subdev_call(src_subdev, video, s_stream, false); + if (err < 0 && err != -ENOIOCTLCMD) + dev_err_probe(csi->dev, err, "source subdev stream off failed\n"); + } + csi->ops->csi_stop_streaming(csi_chan); if (csi_chan->mipi) { @@ -786,6 +830,10 @@ static int tegra_csi_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_ARCH_TEGRA_210_SOC) +extern const struct tegra_csi_soc tegra210_csi_soc; +#endif + static const struct of_device_id tegra_csi_of_id_table[] = { #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc }, |