drivers: media: camera: Gang Mode from device tree
Ahung Cheng [Fri, 3 Jun 2016 10:22:05 +0000 (18:22 +0800)]
Add support for reversing CSI mapping by looking for a new entry,
gang-mode. Set gang mode to GANG_MODE_R_L, instead of default
GANG_MODE_L_R, to swap input ports.

bug 1772273

Change-Id: Ia2be129354e4aca3c7236125667f18e950061f63
Reviewed-on: http://git-master/r/1158678
(cherry picked from commit b595683f9b562b55323ed185e3a4405a31b722b5)
Signed-off-by: Ahung Cheng <ahcheng@nvidia.com>
(cherry picked from commit 7cc03562332180e21090c288ffaa5dfd89ec2df3)
Signed-off-by: Ahung Cheng <ahcheng@nvidia.com>
Reviewed-on: http://git-master/r/1165727
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Reviewed-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-by: Hayden Du <haydend@nvidia.com>

drivers/media/platform/tegra/camera/channel.c
drivers/media/platform/tegra/camera/graph.c
drivers/media/platform/tegra/camera/mc_common.h

index e218165..6b4ce21 100644 (file)
@@ -54,18 +54,21 @@ static int tegra_channel_mipi_cal(struct tegra_channel *chan, char is_bypass);
 
 static void gang_buffer_offsets(struct tegra_channel *chan)
 {
-       int i;
+       bool reverse = false;
+       int i, ports;
        u32 offset = 0;
 
        for (i = 0; i < chan->total_ports; i++) {
                switch (chan->gang_mode) {
+               case CAMERA_GANG_R_L:
+                       reverse = true;
                case CAMERA_NO_GANG_MODE:
                case CAMERA_GANG_L_R:
-               case CAMERA_GANG_R_L:
                        offset = chan->gang_bytesperline;
                        break;
-               case CAMERA_GANG_T_B:
                case CAMERA_GANG_B_T:
+                       reverse = true;
+               case CAMERA_GANG_T_B:
                        offset = chan->gang_sizeimage;
                        break;
                default:
@@ -73,7 +76,8 @@ static void gang_buffer_offsets(struct tegra_channel *chan)
                }
                offset = ((offset + TEGRA_SURFACE_ALIGNMENT - 1) &
                                        ~(TEGRA_SURFACE_ALIGNMENT - 1));
-               chan->buffer_offset[i] = i * offset;
+               ports = reverse ? (chan->total_ports - 1 - i) : i;
+               chan->buffer_offset[i] = ports * offset;
        }
 }
 
@@ -123,7 +127,7 @@ static void update_gang_mode(struct tegra_channel *chan)
         * on gang mode and surface stride alignment
         */
        if ((width > 1920) && (height > 1080)) {
-               chan->gang_mode = CAMERA_GANG_L_R;
+               chan->gang_mode = chan->gang_mode_default;
                chan->valid_ports = chan->total_ports;
        } else {
                chan->gang_mode = CAMERA_NO_GANG_MODE;
index d43f1de..c350e7b 100644 (file)
@@ -387,6 +387,19 @@ int tegra_vi_get_port_info(struct tegra_channel *chan,
                                next_port = (next_port % (PORT_F + 1));
                                chan->port[i] = next_port;
                        }
+
+                       if (chan->numlanes > 4) {
+                               /* Get Gang mode */
+                               ret = of_property_read_u32(ep, "gang-mode", &value);
+                               if (ret != 0 || value < 1 || value > 4) {
+                                       dev_err(&chan->video.dev,
+                                               "%s: invalid gang mode value"
+                                               ", default to CAMERA_GANG_L_R\n",
+                                               __func__);
+                                       value = CAMERA_GANG_L_R;
+                               }
+                               chan->gang_mode_default = value;
+                       }
                }
        }
 
index b52f69a..dd37ca4 100644 (file)
@@ -159,6 +159,7 @@ struct tegra_channel {
        unsigned int saved_ctx_bypass;
        unsigned int saved_ctx_pgmode;
        unsigned int gang_mode;
+       unsigned int gang_mode_default;
        unsigned int gang_width;
        unsigned int gang_height;
        unsigned int gang_bytesperline;