]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
media:camera: Fix s_stream and s_power sequence
authorWenjia Zhou <wenjiaz@nvidia.com>
Mon, 5 Jun 2017 23:05:00 +0000 (16:05 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Wed, 7 Jun 2017 06:04:23 +0000 (23:04 -0700)
Bug 1920440
Bug 200295634

Change-Id: I1f268b709821f327aad9d426e0544370824beae3
Signed-off-by: Wenjia Zhou <wenjiaz@nvidia.com>
Reviewed-on: http://git-master/r/1479671
(cherry picked from commit 37351f2e9ad9056755b949a59f5c817cddcbb606)
Reviewed-on: http://git-master/r/1490063
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
drivers/media/platform/tegra/camera/csi/csi.c
drivers/media/platform/tegra/camera/vi/channel.c

index e3316531829932e147e4c80f2c2d9c73b1d17122..0939b2eaaaef66104e0246753e8355f3c5edf3c8 100644 (file)
@@ -76,11 +76,13 @@ int tegra_csi_power(struct tegra_csi_device *csi, int enable)
        int err = 0;
 
        if (enable) {
+               tegra_mipi_bias_pad_enable();
                err = csi->fops->csi_power_on(csi);
                if (!err)
                        atomic_inc(&csi->power_ref);
        } else {
                err = csi->fops->csi_power_off(csi);
+               tegra_mipi_bias_pad_disable();
                if (!err)
                        atomic_dec(&csi->power_ref);
        }
@@ -166,13 +168,10 @@ static int tegra_csi_s_stream(struct v4l2_subdev *subdev, int enable)
        ret = update_video_source(csi, enable, chan->pg_mode);
        if (ret)
                return ret;
-       if (!chan->pg_mode) {
-               if (enable) {
-                       tegra_mipi_bias_pad_enable();
+       if (!chan->pg_mode)
+               if (enable)
                        csi->fops->mipical(chan);
-               } else
-                       tegra_mipi_bias_pad_disable();
-       }
+
        if (tegra_chan->bypass) {
                atomic_set(&chan->is_streaming, enable);
                return 0;
@@ -192,7 +191,6 @@ start_fail:
        update_video_source(csi, 0, chan->pg_mode);
        for (i = 0; i < tegra_chan->valid_ports; i++)
                tegra_csi_stop_streaming(chan, i);
-       tegra_mipi_bias_pad_disable();
        return ret;
 }
 
index de901d5fd0d7e3ab3ad021ed765e3d9214efd239..22ff1af3b0dba1846d379284cfc4877b05f4aa09 100644 (file)
@@ -536,21 +536,36 @@ int tegra_channel_set_stream(struct tegra_channel *chan, bool on)
 {
        int num_sd;
        int ret = 0;
+       int err = 0;
+       struct v4l2_subdev *sd;
 
        if (atomic_read(&chan->is_streaming) == on)
                return 0;
 
-       for (num_sd = chan->num_subdevs - 1; num_sd >= 0; num_sd--) {
-               struct v4l2_subdev *sd = chan->subdev[num_sd];
-               int err = 0;
+       if (on) {
+               /* Enable CSI before sensor. Reason is as follows:
+                * CSI is able to catch the very first clk transition.
+                * Ensure mipi calibration is done before transmission/first frame data.
+                * TODO:Ensure deskew is setup properly before first deskew sync signal.
+                */
+               for (num_sd = 0; num_sd < chan->num_subdevs; num_sd++) {
+                       sd = chan->subdev[num_sd];
 
-               err = v4l2_subdev_call(sd, video, s_stream, on);
-               if (!ret && err < 0 && err != -ENOIOCTLCMD)
-                       ret = err;
+                       err = v4l2_subdev_call(sd, video, s_stream, on);
+                       if (!ret && err < 0 && err != -ENOIOCTLCMD)
+                               ret = err;
+               }
+       } else {
+               for (num_sd = chan->num_subdevs - 1; num_sd >= 0; num_sd--) {
+                       sd = chan->subdev[num_sd];
+
+                       err = v4l2_subdev_call(sd, video, s_stream, on);
+                       if (!ret && err < 0 && err != -ENOIOCTLCMD)
+                               ret = err;
+               }
        }
 
        atomic_set(&chan->is_streaming, on);
-
        return ret;
 }
 
@@ -558,14 +573,25 @@ int tegra_channel_set_power(struct tegra_channel *chan, bool on)
 {
        int num_sd;
        int ret = 0;
+       int err = 0;
+       struct v4l2_subdev *sd;
 
-       for (num_sd = 0; num_sd < chan->num_subdevs; num_sd++) {
-               struct v4l2_subdev *sd = chan->subdev[num_sd];
-               int err = 0;
+       if (on) {
+               for (num_sd = 0; num_sd < chan->num_subdevs; num_sd++) {
+                       sd = chan->subdev[num_sd];
 
-               err = v4l2_subdev_call(sd, core, s_power, on);
-               if (!ret && err < 0 && err != -ENOIOCTLCMD)
-                       ret = err;
+                       err = v4l2_subdev_call(sd, core, s_power, on);
+                       if (!ret && err < 0 && err != -ENOIOCTLCMD)
+                               ret = err;
+               }
+       } else {
+               for (num_sd = chan->num_subdevs - 1; num_sd >= 0; num_sd--) {
+                       sd = chan->subdev[num_sd];
+
+                       err = v4l2_subdev_call(sd, core, s_power, on);
+                       if (!ret && err < 0 && err != -ENOIOCTLCMD)
+                               ret = err;
+               }
        }
 
        return ret;