VI in Tegra20/Tegra30 has 2 VI outputs with different set of supported
formats. Convert output registers to macros for simpler work with both
outputs since apart formats their layout matches.

Signed-off-by: Svyatoslav Ryhel <clamo...@gmail.com>
---
 drivers/staging/media/tegra-video/tegra20.c | 82 ++++++++++++---------
 1 file changed, 46 insertions(+), 36 deletions(-)

diff --git a/drivers/staging/media/tegra-video/tegra20.c 
b/drivers/staging/media/tegra-video/tegra20.c
index 3dc26f5552eb..6e0b3b728623 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -29,13 +29,19 @@
 #define TEGRA20_MIN_HEIGHT     32U
 #define TEGRA20_MAX_HEIGHT     8190U
 
+/* Tegra20/Tegra30 has 2 outputs in VI */
+enum tegra_vi_out {
+       TEGRA_VI_OUT_1 = 0,
+       TEGRA_VI_OUT_2 = 1,
+};
+
 /* --------------------------------------------------------------------------
  * Registers
  */
 
-#define TEGRA_VI_CONT_SYNCPT_OUT_1                     0x0060
-#define       VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT   BIT(8)
-#define       VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT      0
+#define TEGRA_VI_CONT_SYNCPT_OUT(n)                    (0x0060 + (n) * 4)
+#define       VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT     BIT(8)
+#define       VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT                0
 
 #define TEGRA_VI_VI_INPUT_CONTROL                      0x0088
 #define       VI_INPUT_FIELD_DETECT                    BIT(27)
@@ -47,6 +53,7 @@
 #define       VI_INPUT_YUV_INPUT_FORMAT_YVYU           (3 << 
VI_INPUT_YUV_INPUT_FORMAT_SFT)
 #define       VI_INPUT_INPUT_FORMAT_SFT                        2  /* bits 
[5:2] */
 #define       VI_INPUT_INPUT_FORMAT_YUV422             (0 << 
VI_INPUT_INPUT_FORMAT_SFT)
+#define       VI_INPUT_INPUT_FORMAT_BAYER              (2 << 
VI_INPUT_INPUT_FORMAT_SFT)
 #define       VI_INPUT_VIP_INPUT_ENABLE                        BIT(1)
 
 #define TEGRA_VI_VI_CORE_CONTROL                       0x008c
@@ -67,7 +74,7 @@
 #define       VI_VI_CORE_CONTROL_OUTPUT_TO_EPP_SFT     2
 #define       VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_SFT     0
 
-#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL               0x0090
+#define TEGRA_VI_VI_OUTPUT_CONTROL(n)                  (0x0090 + (n) * 4)
 #define       VI_OUTPUT_FORMAT_EXT                     BIT(22)
 #define       VI_OUTPUT_V_DIRECTION                    BIT(20)
 #define       VI_OUTPUT_H_DIRECTION                    BIT(19)
@@ -81,6 +88,7 @@
 #define       VI_OUTPUT_OUTPUT_FORMAT_SFT              0
 #define       VI_OUTPUT_OUTPUT_FORMAT_YUV422POST       (3 << 
VI_OUTPUT_OUTPUT_FORMAT_SFT)
 #define       VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR     (6 << 
VI_OUTPUT_OUTPUT_FORMAT_SFT)
+#define       VI_OUTPUT_OUTPUT_FORMAT_VIP_BAYER_DIRECT (9 << 
VI_OUTPUT_OUTPUT_FORMAT_SFT)
 
 #define TEGRA_VI_VIP_H_ACTIVE                          0x00a4
 #define       VI_VIP_H_ACTIVE_PERIOD_SFT               16 /* active 
pixels/line, must be even */
@@ -90,26 +98,26 @@
 #define       VI_VIP_V_ACTIVE_PERIOD_SFT               16 /* active lines */
 #define       VI_VIP_V_ACTIVE_START_SFT                        0
 
-#define TEGRA_VI_VB0_START_ADDRESS_FIRST               0x00c4
-#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST                        0x00c8
+#define TEGRA_VI_VB0_START_ADDRESS(n)                  (0x00c4 + (n) * 44)
+#define TEGRA_VI_VB0_BASE_ADDRESS(n)                   (0x00c8 + (n) * 44)
 #define TEGRA_VI_VB0_START_ADDRESS_U                   0x00cc
 #define TEGRA_VI_VB0_BASE_ADDRESS_U                    0x00d0
 #define TEGRA_VI_VB0_START_ADDRESS_V                   0x00d4
 #define TEGRA_VI_VB0_BASE_ADDRESS_V                    0x00d8
 
-#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE               0x00e0
-#define       VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT         16
-#define       VI_FIRST_OUTPUT_FRAME_WIDTH_SFT          0
+#define TEGRA_VI_OUTPUT_FRAME_SIZE(n)                  (0x00e0 + (n) * 24)
+#define       VI_OUTPUT_FRAME_HEIGHT_SFT               16
+#define       VI_OUTPUT_FRAME_WIDTH_SFT                        0
 
-#define TEGRA_VI_VB0_COUNT_FIRST                       0x00e4
+#define TEGRA_VI_VB0_COUNT(n)                          (0x00e4 + (n) * 24)
 
-#define TEGRA_VI_VB0_SIZE_FIRST                                0x00e8
-#define       VI_VB0_SIZE_FIRST_V_SFT                  16
-#define       VI_VB0_SIZE_FIRST_H_SFT                  0
+#define TEGRA_VI_VB0_SIZE(n)                           (0x00e8 + (n) * 24)
+#define       VI_VB0_SIZE_V_SFT                                16
+#define       VI_VB0_SIZE_H_SFT                                0
 
-#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST               0x00ec
-#define       VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT    30
-#define       VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT      0
+#define TEGRA_VI_VB0_BUFFER_STRIDE(n)                  (0x00ec + (n) * 24)
+#define       VI_VB0_BUFFER_STRIDE_CHROMA_SFT          30
+#define       VI_VB0_BUFFER_STRIDE_LUMA_SFT            0
 
 #define TEGRA_VI_H_LPF_CONTROL                         0x0108
 #define       VI_H_LPF_CONTROL_CHROMA_SFT              16
@@ -137,7 +145,7 @@
 #define       VI_CAMERA_CONTROL_TEST_MODE              BIT(1)
 #define       VI_CAMERA_CONTROL_VIP_ENABLE             BIT(0)
 
-#define TEGRA_VI_VI_ENABLE                             0x01a4
+#define TEGRA_VI_VI_ENABLE(n)                          (0x01a4 + (n) * 4)
 #define       VI_VI_ENABLE_SW_FLOW_CONTROL_OUT1                BIT(1)
 #define       VI_VI_ENABLE_FIRST_OUTPUT_TO_MEM_DISABLE BIT(0)
 
@@ -367,8 +375,8 @@ static void tegra20_channel_vi_buffer_setup(struct 
tegra_vi_channel *chan,
        case V4L2_PIX_FMT_VYUY:
        case V4L2_PIX_FMT_YUYV:
        case V4L2_PIX_FMT_YVYU:
-               tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_FIRST,  base);
-               tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_FIRST, base + 
chan->start_offset);
+               tegra20_vi_write(chan, 
TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_1),  base);
+               tegra20_vi_write(chan, 
TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_1), base + chan->start_offset);
                break;
        }
 }
@@ -456,6 +464,7 @@ static void tegra20_camera_capture_setup(struct 
tegra_vi_channel *chan)
        int stride_l = chan->format.bytesperline;
        int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 ||
                        output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0;
+       enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
        int main_output_format;
        int yuv_output_format;
 
@@ -473,33 +482,33 @@ static void tegra20_camera_capture_setup(struct 
tegra_vi_channel *chan)
        /* Set up raise-on-edge, so we get an interrupt on end of frame. */
        tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
 
-       tegra20_vi_write(chan, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
+       tegra20_vi_write(chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
                         (chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
                         (chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
                         yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT |
                         main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT);
 
        /* Set up frame size */
-       tegra20_vi_write(chan, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
-                        height << VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT |
-                        width  << VI_FIRST_OUTPUT_FRAME_WIDTH_SFT);
+       tegra20_vi_write(chan, TEGRA_VI_OUTPUT_FRAME_SIZE(output_channel),
+                        height << VI_OUTPUT_FRAME_HEIGHT_SFT |
+                        width  << VI_OUTPUT_FRAME_WIDTH_SFT);
 
        /* First output memory enabled */
-       tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+       tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE(output_channel), 0);
 
        /* Set the number of frames in the buffer */
-       tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT_FIRST, 1);
+       tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT(output_channel), 1);
 
        /* Set up buffer frame size */
-       tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE_FIRST,
-                        height << VI_VB0_SIZE_FIRST_V_SFT |
-                        width  << VI_VB0_SIZE_FIRST_H_SFT);
+       tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE(output_channel),
+                        height << VI_VB0_SIZE_V_SFT |
+                        width  << VI_VB0_SIZE_H_SFT);
 
-       tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
-                        stride_l << VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT |
-                        stride_c << VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT);
+       tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE(output_channel),
+                        stride_l << VI_VB0_BUFFER_STRIDE_LUMA_SFT |
+                        stride_c << VI_VB0_BUFFER_STRIDE_CHROMA_SFT);
 
-       tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+       tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE(output_channel), 0);
 }
 
 static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count)
@@ -588,7 +597,7 @@ const struct tegra_vi_soc tegra20_vi_soc = {
        .nformats = ARRAY_SIZE(tegra20_video_formats),
        .default_video_format = &tegra20_video_formats[0],
        .ops = &tegra20_vi_ops,
-       .vi_max_channels = 1, /* parallel input (VIP) */
+       .vi_max_channels = 2, /* TEGRA_VI_OUT_1 and TEGRA_VI_OUT_2 */
        .vi_max_clk_hz = 150000000,
        .has_h_v_flip = true,
 };
@@ -608,6 +617,7 @@ static int tegra20_vip_start_streaming(struct 
tegra_vip_channel *vip_chan)
        struct tegra_vi_channel *vi_chan = 
v4l2_get_subdev_hostdata(&vip_chan->subdev);
        int width  = vi_chan->format.width;
        int height = vi_chan->format.height;
+       enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
 
        unsigned int main_input_format;
        unsigned int yuv_input_format;
@@ -638,10 +648,10 @@ static int tegra20_vip_start_streaming(struct 
tegra_vip_channel *vip_chan)
                         GENMASK(9, 2) << VI_DATA_INPUT_SFT);
        tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INVERSION, 0);
 
-       tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT_1,
-                        VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT |
+       tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT(output_channel),
+                        VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
                         host1x_syncpt_id(vi_chan->mw_ack_sp[0])
-                        << VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT);
+                        << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
 
        tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, 
VI_CAMERA_CONTROL_STOP_CAPTURE);
 
-- 
2.48.1

Reply via email to