Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2020 NVIDIA CORPORATION.  All rights reserved.
0004  */
0005 
0006 /*
0007  * This source file contains Tegra210 supported video formats,
0008  * VI and CSI SoC specific data, operations and registers accessors.
0009  */
0010 #include <linux/bitfield.h>
0011 #include <linux/clk.h>
0012 #include <linux/clk/tegra.h>
0013 #include <linux/delay.h>
0014 #include <linux/host1x.h>
0015 #include <linux/kthread.h>
0016 
0017 #include "csi.h"
0018 #include "vi.h"
0019 
0020 #define TEGRA_VI_SYNCPT_WAIT_TIMEOUT            msecs_to_jiffies(200)
0021 
0022 /* Tegra210 VI registers */
0023 #define TEGRA_VI_CFG_VI_INCR_SYNCPT         0x000
0024 #define   VI_CFG_VI_INCR_SYNCPT_COND(x)         (((x) & 0xff) << 8)
0025 #define   VI_CSI_PP_FRAME_START(port)           (5 + (port) * 4)
0026 #define   VI_CSI_MW_ACK_DONE(port)          (7 + (port) * 4)
0027 #define TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL       0x004
0028 #define   VI_INCR_SYNCPT_NO_STALL           BIT(8)
0029 #define TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR       0x008
0030 #define TEGRA_VI_CFG_CG_CTRL                0x0b8
0031 #define   VI_CG_2ND_LEVEL_EN                0x1
0032 
0033 /* Tegra210 VI CSI registers */
0034 #define TEGRA_VI_CSI_SW_RESET               0x000
0035 #define TEGRA_VI_CSI_SINGLE_SHOT            0x004
0036 #define   SINGLE_SHOT_CAPTURE               0x1
0037 #define TEGRA_VI_CSI_IMAGE_DEF              0x00c
0038 #define   BYPASS_PXL_TRANSFORM_OFFSET           24
0039 #define   IMAGE_DEF_FORMAT_OFFSET           16
0040 #define   IMAGE_DEF_DEST_MEM                0x1
0041 #define TEGRA_VI_CSI_IMAGE_SIZE             0x018
0042 #define   IMAGE_SIZE_HEIGHT_OFFSET          16
0043 #define TEGRA_VI_CSI_IMAGE_SIZE_WC          0x01c
0044 #define TEGRA_VI_CSI_IMAGE_DT               0x020
0045 #define TEGRA_VI_CSI_SURFACE0_OFFSET_MSB        0x024
0046 #define TEGRA_VI_CSI_SURFACE0_OFFSET_LSB        0x028
0047 #define TEGRA_VI_CSI_SURFACE1_OFFSET_MSB        0x02c
0048 #define TEGRA_VI_CSI_SURFACE1_OFFSET_LSB        0x030
0049 #define TEGRA_VI_CSI_SURFACE2_OFFSET_MSB        0x034
0050 #define TEGRA_VI_CSI_SURFACE2_OFFSET_LSB        0x038
0051 #define TEGRA_VI_CSI_SURFACE0_STRIDE            0x054
0052 #define TEGRA_VI_CSI_SURFACE1_STRIDE            0x058
0053 #define TEGRA_VI_CSI_SURFACE2_STRIDE            0x05c
0054 #define TEGRA_VI_CSI_SURFACE_HEIGHT0            0x060
0055 #define TEGRA_VI_CSI_ERROR_STATUS           0x084
0056 
0057 /* Tegra210 CSI Pixel Parser registers: Starts from 0x838, offset 0x0 */
0058 #define TEGRA_CSI_INPUT_STREAM_CONTROL                  0x000
0059 #define   CSI_SKIP_PACKET_THRESHOLD_OFFSET      16
0060 #define TEGRA_CSI_PIXEL_STREAM_CONTROL0         0x004
0061 #define   CSI_PP_PACKET_HEADER_SENT         BIT(4)
0062 #define   CSI_PP_DATA_IDENTIFIER_ENABLE         BIT(5)
0063 #define   CSI_PP_WORD_COUNT_SELECT_HEADER       BIT(6)
0064 #define   CSI_PP_CRC_CHECK_ENABLE           BIT(7)
0065 #define   CSI_PP_WC_CHECK               BIT(8)
0066 #define   CSI_PP_OUTPUT_FORMAT_STORE            (0x3 << 16)
0067 #define   CSI_PPA_PAD_LINE_NOPAD            (0x2 << 24)
0068 #define   CSI_PP_HEADER_EC_DISABLE          (0x1 << 27)
0069 #define   CSI_PPA_PAD_FRAME_NOPAD           (0x2 << 28)
0070 #define TEGRA_CSI_PIXEL_STREAM_CONTROL1                 0x008
0071 #define   CSI_PP_TOP_FIELD_FRAME_OFFSET         0
0072 #define   CSI_PP_TOP_FIELD_FRAME_MASK_OFFSET        4
0073 #define TEGRA_CSI_PIXEL_STREAM_GAP                      0x00c
0074 #define   PP_FRAME_MIN_GAP_OFFSET           16
0075 #define TEGRA_CSI_PIXEL_STREAM_PP_COMMAND               0x010
0076 #define   CSI_PP_ENABLE                 0x1
0077 #define   CSI_PP_DISABLE                0x2
0078 #define   CSI_PP_RST                    0x3
0079 #define   CSI_PP_SINGLE_SHOT_ENABLE         (0x1 << 2)
0080 #define   CSI_PP_START_MARKER_FRAME_MAX_OFFSET      12
0081 #define TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME           0x014
0082 #define TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK           0x018
0083 #define TEGRA_CSI_PIXEL_PARSER_STATUS                   0x01c
0084 
0085 /* Tegra210 CSI PHY registers */
0086 /* CSI_PHY_CIL_COMMAND_0 offset 0x0d0 from TEGRA_CSI_PIXEL_PARSER_0_BASE */
0087 #define TEGRA_CSI_PHY_CIL_COMMAND                       0x0d0
0088 #define   CSI_A_PHY_CIL_NOP             0x0
0089 #define   CSI_A_PHY_CIL_ENABLE              0x1
0090 #define   CSI_A_PHY_CIL_DISABLE             0x2
0091 #define   CSI_A_PHY_CIL_ENABLE_MASK         0x3
0092 #define   CSI_B_PHY_CIL_NOP             (0x0 << 8)
0093 #define   CSI_B_PHY_CIL_ENABLE              (0x1 << 8)
0094 #define   CSI_B_PHY_CIL_DISABLE             (0x2 << 8)
0095 #define   CSI_B_PHY_CIL_ENABLE_MASK         (0x3 << 8)
0096 
0097 #define TEGRA_CSI_CIL_PAD_CONFIG0                       0x000
0098 #define   BRICK_CLOCK_A_4X              (0x1 << 16)
0099 #define   BRICK_CLOCK_B_4X              (0x2 << 16)
0100 #define TEGRA_CSI_CIL_PAD_CONFIG1                       0x004
0101 #define TEGRA_CSI_CIL_PHY_CONTROL                       0x008
0102 #define   CLK_SETTLE_MASK               GENMASK(13, 8)
0103 #define   THS_SETTLE_MASK               GENMASK(5, 0)
0104 #define TEGRA_CSI_CIL_INTERRUPT_MASK                    0x00c
0105 #define TEGRA_CSI_CIL_STATUS                            0x010
0106 #define TEGRA_CSI_CILX_STATUS                           0x014
0107 #define TEGRA_CSI_CIL_SW_SENSOR_RESET                   0x020
0108 
0109 #define TEGRA_CSI_PATTERN_GENERATOR_CTRL        0x000
0110 #define   PG_MODE_OFFSET                2
0111 #define   PG_ENABLE                 0x1
0112 #define   PG_DISABLE                    0x0
0113 #define TEGRA_CSI_PG_BLANK              0x004
0114 #define   PG_VBLANK_OFFSET              16
0115 #define TEGRA_CSI_PG_PHASE              0x008
0116 #define TEGRA_CSI_PG_RED_FREQ               0x00c
0117 #define   PG_RED_VERT_INIT_FREQ_OFFSET          16
0118 #define   PG_RED_HOR_INIT_FREQ_OFFSET           0
0119 #define TEGRA_CSI_PG_RED_FREQ_RATE          0x010
0120 #define TEGRA_CSI_PG_GREEN_FREQ             0x014
0121 #define   PG_GREEN_VERT_INIT_FREQ_OFFSET        16
0122 #define   PG_GREEN_HOR_INIT_FREQ_OFFSET         0
0123 #define TEGRA_CSI_PG_GREEN_FREQ_RATE            0x018
0124 #define TEGRA_CSI_PG_BLUE_FREQ              0x01c
0125 #define   PG_BLUE_VERT_INIT_FREQ_OFFSET         16
0126 #define   PG_BLUE_HOR_INIT_FREQ_OFFSET          0
0127 #define TEGRA_CSI_PG_BLUE_FREQ_RATE         0x020
0128 #define TEGRA_CSI_PG_AOHDR              0x024
0129 #define TEGRA_CSI_CSI_SW_STATUS_RESET           0x214
0130 #define TEGRA_CSI_CLKEN_OVERRIDE            0x218
0131 
0132 #define TEGRA210_CSI_PORT_OFFSET            0x34
0133 #define TEGRA210_CSI_CIL_OFFSET             0x0f4
0134 #define TEGRA210_CSI_TPG_OFFSET             0x18c
0135 
0136 #define CSI_PP_OFFSET(block)                ((block) * 0x800)
0137 #define TEGRA210_VI_CSI_BASE(x)             (0x100 + (x) * 0x100)
0138 
0139 /* Tegra210 VI registers accessors */
0140 static void tegra_vi_write(struct tegra_vi_channel *chan, unsigned int addr,
0141                u32 val)
0142 {
0143     writel_relaxed(val, chan->vi->iomem + addr);
0144 }
0145 
0146 static u32 tegra_vi_read(struct tegra_vi_channel *chan, unsigned int addr)
0147 {
0148     return readl_relaxed(chan->vi->iomem + addr);
0149 }
0150 
0151 /* Tegra210 VI_CSI registers accessors */
0152 static void vi_csi_write(struct tegra_vi_channel *chan, u8 portno,
0153              unsigned int addr, u32 val)
0154 {
0155     void __iomem *vi_csi_base;
0156 
0157     vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(portno);
0158 
0159     writel_relaxed(val, vi_csi_base + addr);
0160 }
0161 
0162 static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno,
0163                unsigned int addr)
0164 {
0165     void __iomem *vi_csi_base;
0166 
0167     vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(portno);
0168 
0169     return readl_relaxed(vi_csi_base + addr);
0170 }
0171 
0172 /*
0173  * Tegra210 VI channel capture operations
0174  */
0175 static int tegra_channel_capture_setup(struct tegra_vi_channel *chan,
0176                        u8 portno)
0177 {
0178     u32 height = chan->format.height;
0179     u32 width = chan->format.width;
0180     u32 format = chan->fmtinfo->img_fmt;
0181     u32 data_type = chan->fmtinfo->img_dt;
0182     u32 word_count = (width * chan->fmtinfo->bit_width) / 8;
0183     u32 bypass_pixel_transform = BIT(BYPASS_PXL_TRANSFORM_OFFSET);
0184 
0185     /*
0186      * VI Pixel transformation unit converts source pixels data format
0187      * into selected destination pixel format and aligns properly while
0188      * interfacing with memory packer.
0189      * This pixel transformation should be enabled for YUV and RGB
0190      * formats and should be bypassed for RAW formats as RAW formats
0191      * only support direct to memory.
0192      */
0193     if (chan->pg_mode || data_type == TEGRA_IMAGE_DT_YUV422_8 ||
0194         data_type == TEGRA_IMAGE_DT_RGB888)
0195         bypass_pixel_transform = 0;
0196 
0197     /*
0198      * For x8 source streaming, the source image is split onto two x4 ports
0199      * with left half to first x4 port and right half to second x4 port.
0200      * So, use split width and corresponding word count for each x4 port.
0201      */
0202     if (chan->numgangports > 1) {
0203         width = width >> 1;
0204         word_count = (width * chan->fmtinfo->bit_width) / 8;
0205     }
0206 
0207     vi_csi_write(chan, portno, TEGRA_VI_CSI_ERROR_STATUS, 0xffffffff);
0208     vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_DEF,
0209              bypass_pixel_transform |
0210              (format << IMAGE_DEF_FORMAT_OFFSET) |
0211              IMAGE_DEF_DEST_MEM);
0212     vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_DT, data_type);
0213     vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_SIZE_WC, word_count);
0214     vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_SIZE,
0215              (height << IMAGE_SIZE_HEIGHT_OFFSET) | width);
0216     return 0;
0217 }
0218 
0219 static void tegra_channel_vi_soft_reset(struct tegra_vi_channel *chan,
0220                     u8 portno)
0221 {
0222     /* disable clock gating to enable continuous clock */
0223     tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, 0);
0224     /*
0225      * Soft reset memory client interface, pixel format logic, sensor
0226      * control logic, and a shadow copy logic to bring VI to clean state.
0227      */
0228     vi_csi_write(chan, portno, TEGRA_VI_CSI_SW_RESET, 0xf);
0229     usleep_range(100, 200);
0230     vi_csi_write(chan, portno, TEGRA_VI_CSI_SW_RESET, 0x0);
0231 
0232     /* enable back VI clock gating */
0233     tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, VI_CG_2ND_LEVEL_EN);
0234 }
0235 
0236 static void tegra_channel_capture_error_recover(struct tegra_vi_channel *chan,
0237                         u8 portno)
0238 {
0239     struct v4l2_subdev *subdev;
0240     u32 val;
0241 
0242     /*
0243      * Recover VI and CSI hardware blocks in case of missing frame start
0244      * events due to source not streaming or noisy csi inputs from the
0245      * external source or many outstanding frame start or MW_ACK_DONE
0246      * events which can cause CSI and VI hardware hang.
0247      * This helps to have a clean capture for next frame.
0248      */
0249     val = vi_csi_read(chan, portno, TEGRA_VI_CSI_ERROR_STATUS);
0250     dev_dbg(&chan->video.dev, "TEGRA_VI_CSI_ERROR_STATUS 0x%08x\n", val);
0251     vi_csi_write(chan, portno, TEGRA_VI_CSI_ERROR_STATUS, val);
0252 
0253     val = tegra_vi_read(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR);
0254     dev_dbg(&chan->video.dev,
0255         "TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR 0x%08x\n", val);
0256     tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, val);
0257 
0258     /* recover VI by issuing software reset and re-setup for capture */
0259     tegra_channel_vi_soft_reset(chan, portno);
0260     tegra_channel_capture_setup(chan, portno);
0261 
0262     /* recover CSI block */
0263     subdev = tegra_channel_get_remote_csi_subdev(chan);
0264     tegra_csi_error_recover(subdev);
0265 }
0266 
0267 static struct tegra_channel_buffer *
0268 dequeue_buf_done(struct tegra_vi_channel *chan)
0269 {
0270     struct tegra_channel_buffer *buf = NULL;
0271 
0272     spin_lock(&chan->done_lock);
0273     if (list_empty(&chan->done)) {
0274         spin_unlock(&chan->done_lock);
0275         return NULL;
0276     }
0277 
0278     buf = list_first_entry(&chan->done,
0279                    struct tegra_channel_buffer, queue);
0280     if (buf)
0281         list_del_init(&buf->queue);
0282     spin_unlock(&chan->done_lock);
0283 
0284     return buf;
0285 }
0286 
0287 static void release_buffer(struct tegra_vi_channel *chan,
0288                struct tegra_channel_buffer *buf,
0289                enum vb2_buffer_state state)
0290 {
0291     struct vb2_v4l2_buffer *vb = &buf->buf;
0292 
0293     vb->sequence = chan->sequence++;
0294     vb->field = V4L2_FIELD_NONE;
0295     vb->vb2_buf.timestamp = ktime_get_ns();
0296     vb2_buffer_done(&vb->vb2_buf, state);
0297 }
0298 
0299 static void tegra_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
0300                       u8 portno, u32 buf_offset,
0301                       struct tegra_channel_buffer *buf)
0302 {
0303     int bytesperline = chan->format.bytesperline;
0304     u32 sizeimage = chan->format.sizeimage;
0305 
0306     /* program buffer address by using surface 0 */
0307     vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_OFFSET_MSB,
0308              ((u64)buf->addr + buf_offset) >> 32);
0309     vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_OFFSET_LSB,
0310              buf->addr + buf_offset);
0311     vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_STRIDE, bytesperline);
0312 
0313     if (chan->fmtinfo->fourcc != V4L2_PIX_FMT_NV16)
0314         return;
0315     /*
0316      * Program surface 1 for UV plane with offset sizeimage from Y plane.
0317      */
0318     vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_OFFSET_MSB,
0319              (((u64)buf->addr + sizeimage / 2) + buf_offset) >> 32);
0320     vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_OFFSET_LSB,
0321              buf->addr + sizeimage / 2 + buf_offset);
0322     vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_STRIDE, bytesperline);
0323 }
0324 
0325 static int tegra_channel_capture_frame(struct tegra_vi_channel *chan,
0326                        struct tegra_channel_buffer *buf)
0327 {
0328     u32 thresh, value, frame_start, mw_ack_done;
0329     u32 fs_thresh[GANG_PORTS_MAX];
0330     u8 *portnos = chan->portnos;
0331     int gang_bpl = (chan->format.width >> 1) * chan->fmtinfo->bpp;
0332     u32 buf_offset;
0333     bool capture_timedout = false;
0334     int err, i;
0335 
0336     for (i = 0; i < chan->numgangports; i++) {
0337         /*
0338          * Align buffers side-by-side for all consecutive x4 ports
0339          * in gang ports using bytes per line based on source split
0340          * width.
0341          */
0342         buf_offset = i * roundup(gang_bpl, SURFACE_ALIGN_BYTES);
0343         tegra_channel_vi_buffer_setup(chan, portnos[i], buf_offset,
0344                           buf);
0345 
0346         /*
0347          * Tegra VI block interacts with host1x syncpt to synchronize
0348          * programmed condition and hardware operation for capture.
0349          * Frame start and Memory write acknowledge syncpts has their
0350          * own FIFO of depth 2.
0351          *
0352          * Syncpoint trigger conditions set through VI_INCR_SYNCPT
0353          * register are added to HW syncpt FIFO and when HW triggers,
0354          * syncpt condition is removed from the FIFO and counter at
0355          * syncpoint index will be incremented by the hardware and
0356          * software can wait for counter to reach threshold to
0357          * synchronize capturing frame with hardware capture events.
0358          */
0359 
0360         /* increase channel syncpoint threshold for FRAME_START */
0361         thresh = host1x_syncpt_incr_max(chan->frame_start_sp[i], 1);
0362         fs_thresh[i] = thresh;
0363 
0364         /* Program FRAME_START trigger condition syncpt request */
0365         frame_start = VI_CSI_PP_FRAME_START(portnos[i]);
0366         value = VI_CFG_VI_INCR_SYNCPT_COND(frame_start) |
0367             host1x_syncpt_id(chan->frame_start_sp[i]);
0368         tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value);
0369 
0370         /* increase channel syncpoint threshold for MW_ACK_DONE */
0371         thresh = host1x_syncpt_incr_max(chan->mw_ack_sp[i], 1);
0372         buf->mw_ack_sp_thresh[i] = thresh;
0373 
0374         /* Program MW_ACK_DONE trigger condition syncpt request */
0375         mw_ack_done = VI_CSI_MW_ACK_DONE(portnos[i]);
0376         value = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) |
0377             host1x_syncpt_id(chan->mw_ack_sp[i]);
0378         tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value);
0379     }
0380 
0381     /* enable single shot capture after all ganged ports are ready */
0382     for (i = 0; i < chan->numgangports; i++)
0383         vi_csi_write(chan, portnos[i], TEGRA_VI_CSI_SINGLE_SHOT,
0384                  SINGLE_SHOT_CAPTURE);
0385 
0386     for (i = 0; i < chan->numgangports; i++) {
0387         /*
0388          * Wait for syncpt counter to reach frame start event threshold
0389          */
0390         err = host1x_syncpt_wait(chan->frame_start_sp[i], fs_thresh[i],
0391                      TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value);
0392         if (err) {
0393             capture_timedout = true;
0394             /* increment syncpoint counter for timedout events */
0395             host1x_syncpt_incr(chan->frame_start_sp[i]);
0396             spin_lock(&chan->sp_incr_lock[i]);
0397             host1x_syncpt_incr(chan->mw_ack_sp[i]);
0398             spin_unlock(&chan->sp_incr_lock[i]);
0399             /* clear errors and recover */
0400             tegra_channel_capture_error_recover(chan, portnos[i]);
0401         }
0402     }
0403 
0404     if (capture_timedout) {
0405         dev_err_ratelimited(&chan->video.dev,
0406                     "frame start syncpt timeout: %d\n", err);
0407         release_buffer(chan, buf, VB2_BUF_STATE_ERROR);
0408         return err;
0409     }
0410 
0411     /* move buffer to capture done queue */
0412     spin_lock(&chan->done_lock);
0413     list_add_tail(&buf->queue, &chan->done);
0414     spin_unlock(&chan->done_lock);
0415 
0416     /* wait up kthread for capture done */
0417     wake_up_interruptible(&chan->done_wait);
0418 
0419     return 0;
0420 }
0421 
0422 static void tegra_channel_capture_done(struct tegra_vi_channel *chan,
0423                        struct tegra_channel_buffer *buf)
0424 {
0425     enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
0426     u32 value;
0427     bool capture_timedout = false;
0428     int ret, i;
0429 
0430     for (i = 0; i < chan->numgangports; i++) {
0431         /*
0432          * Wait for syncpt counter to reach MW_ACK_DONE event threshold
0433          */
0434         ret = host1x_syncpt_wait(chan->mw_ack_sp[i],
0435                      buf->mw_ack_sp_thresh[i],
0436                      TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value);
0437         if (ret) {
0438             capture_timedout = true;
0439             state = VB2_BUF_STATE_ERROR;
0440             /* increment syncpoint counter for timedout event */
0441             spin_lock(&chan->sp_incr_lock[i]);
0442             host1x_syncpt_incr(chan->mw_ack_sp[i]);
0443             spin_unlock(&chan->sp_incr_lock[i]);
0444         }
0445     }
0446 
0447     if (capture_timedout)
0448         dev_err_ratelimited(&chan->video.dev,
0449                     "MW_ACK_DONE syncpt timeout: %d\n", ret);
0450     release_buffer(chan, buf, state);
0451 }
0452 
0453 static int chan_capture_kthread_start(void *data)
0454 {
0455     struct tegra_vi_channel *chan = data;
0456     struct tegra_channel_buffer *buf;
0457     unsigned int retries = 0;
0458     int err = 0;
0459 
0460     while (1) {
0461         /*
0462          * Source is not streaming if error is non-zero.
0463          * So, do not dequeue buffers on error and let the thread sleep
0464          * till kthread stop signal is received.
0465          */
0466         wait_event_interruptible(chan->start_wait,
0467                      kthread_should_stop() ||
0468                      (!list_empty(&chan->capture) &&
0469                      !err));
0470 
0471         if (kthread_should_stop())
0472             break;
0473 
0474         /* dequeue the buffer and start capture */
0475         spin_lock(&chan->start_lock);
0476         if (list_empty(&chan->capture)) {
0477             spin_unlock(&chan->start_lock);
0478             continue;
0479         }
0480 
0481         buf = list_first_entry(&chan->capture,
0482                        struct tegra_channel_buffer, queue);
0483         list_del_init(&buf->queue);
0484         spin_unlock(&chan->start_lock);
0485 
0486         err = tegra_channel_capture_frame(chan, buf);
0487         if (!err) {
0488             retries = 0;
0489             continue;
0490         }
0491 
0492         if (retries++ > chan->syncpt_timeout_retry)
0493             vb2_queue_error(&chan->queue);
0494         else
0495             err = 0;
0496     }
0497 
0498     return 0;
0499 }
0500 
0501 static int chan_capture_kthread_finish(void *data)
0502 {
0503     struct tegra_vi_channel *chan = data;
0504     struct tegra_channel_buffer *buf;
0505 
0506     while (1) {
0507         wait_event_interruptible(chan->done_wait,
0508                      !list_empty(&chan->done) ||
0509                      kthread_should_stop());
0510 
0511         /* dequeue buffers and finish capture */
0512         buf = dequeue_buf_done(chan);
0513         while (buf) {
0514             tegra_channel_capture_done(chan, buf);
0515             buf = dequeue_buf_done(chan);
0516         }
0517 
0518         if (kthread_should_stop())
0519             break;
0520     }
0521 
0522     return 0;
0523 }
0524 
0525 static int tegra210_vi_start_streaming(struct vb2_queue *vq, u32 count)
0526 {
0527     struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
0528     struct media_pipeline *pipe = &chan->video.pipe;
0529     u32 val;
0530     u8 *portnos = chan->portnos;
0531     int ret, i;
0532 
0533     tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, VI_CG_2ND_LEVEL_EN);
0534 
0535     /* clear syncpt errors */
0536     val = tegra_vi_read(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR);
0537     tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, val);
0538 
0539     /*
0540      * Sync point FIFO full stalls the host interface.
0541      * Setting NO_STALL will drop INCR_SYNCPT methods when fifos are
0542      * full and the corresponding condition bits in INCR_SYNCPT_ERROR
0543      * register will be set.
0544      * This allows SW to process error recovery.
0545      */
0546     tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL,
0547                VI_INCR_SYNCPT_NO_STALL);
0548 
0549     /* start the pipeline */
0550     ret = media_pipeline_start(&chan->video.entity, pipe);
0551     if (ret < 0)
0552         goto error_pipeline_start;
0553 
0554     /* clear csi errors and do capture setup for all ports in gang mode */
0555     for (i = 0; i < chan->numgangports; i++) {
0556         val = vi_csi_read(chan, portnos[i], TEGRA_VI_CSI_ERROR_STATUS);
0557         vi_csi_write(chan, portnos[i], TEGRA_VI_CSI_ERROR_STATUS, val);
0558 
0559         tegra_channel_capture_setup(chan, portnos[i]);
0560     }
0561 
0562     ret = tegra_channel_set_stream(chan, true);
0563     if (ret < 0)
0564         goto error_set_stream;
0565 
0566     chan->sequence = 0;
0567 
0568     /* start kthreads to capture data to buffer and return them */
0569     chan->kthread_start_capture = kthread_run(chan_capture_kthread_start,
0570                           chan, "%s:0",
0571                           chan->video.name);
0572     if (IS_ERR(chan->kthread_start_capture)) {
0573         ret = PTR_ERR(chan->kthread_start_capture);
0574         chan->kthread_start_capture = NULL;
0575         dev_err(&chan->video.dev,
0576             "failed to run capture start kthread: %d\n", ret);
0577         goto error_kthread_start;
0578     }
0579 
0580     chan->kthread_finish_capture = kthread_run(chan_capture_kthread_finish,
0581                            chan, "%s:1",
0582                            chan->video.name);
0583     if (IS_ERR(chan->kthread_finish_capture)) {
0584         ret = PTR_ERR(chan->kthread_finish_capture);
0585         chan->kthread_finish_capture = NULL;
0586         dev_err(&chan->video.dev,
0587             "failed to run capture finish kthread: %d\n", ret);
0588         goto error_kthread_done;
0589     }
0590 
0591     return 0;
0592 
0593 error_kthread_done:
0594     kthread_stop(chan->kthread_start_capture);
0595 error_kthread_start:
0596     tegra_channel_set_stream(chan, false);
0597 error_set_stream:
0598     media_pipeline_stop(&chan->video.entity);
0599 error_pipeline_start:
0600     tegra_channel_release_buffers(chan, VB2_BUF_STATE_QUEUED);
0601     return ret;
0602 }
0603 
0604 static void tegra210_vi_stop_streaming(struct vb2_queue *vq)
0605 {
0606     struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
0607 
0608     if (chan->kthread_start_capture) {
0609         kthread_stop(chan->kthread_start_capture);
0610         chan->kthread_start_capture = NULL;
0611     }
0612 
0613     if (chan->kthread_finish_capture) {
0614         kthread_stop(chan->kthread_finish_capture);
0615         chan->kthread_finish_capture = NULL;
0616     }
0617 
0618     tegra_channel_release_buffers(chan, VB2_BUF_STATE_ERROR);
0619     tegra_channel_set_stream(chan, false);
0620     media_pipeline_stop(&chan->video.entity);
0621 }
0622 
0623 /*
0624  * Tegra210 VI Pixel memory format enum.
0625  * These format enum value gets programmed into corresponding Tegra VI
0626  * channel register bits.
0627  */
0628 enum tegra210_image_format {
0629     TEGRA210_IMAGE_FORMAT_T_L8 = 16,
0630 
0631     TEGRA210_IMAGE_FORMAT_T_R16_I = 32,
0632     TEGRA210_IMAGE_FORMAT_T_B5G6R5,
0633     TEGRA210_IMAGE_FORMAT_T_R5G6B5,
0634     TEGRA210_IMAGE_FORMAT_T_A1B5G5R5,
0635     TEGRA210_IMAGE_FORMAT_T_A1R5G5B5,
0636     TEGRA210_IMAGE_FORMAT_T_B5G5R5A1,
0637     TEGRA210_IMAGE_FORMAT_T_R5G5B5A1,
0638     TEGRA210_IMAGE_FORMAT_T_A4B4G4R4,
0639     TEGRA210_IMAGE_FORMAT_T_A4R4G4B4,
0640     TEGRA210_IMAGE_FORMAT_T_B4G4R4A4,
0641     TEGRA210_IMAGE_FORMAT_T_R4G4B4A4,
0642 
0643     TEGRA210_IMAGE_FORMAT_T_A8B8G8R8 = 64,
0644     TEGRA210_IMAGE_FORMAT_T_A8R8G8B8,
0645     TEGRA210_IMAGE_FORMAT_T_B8G8R8A8,
0646     TEGRA210_IMAGE_FORMAT_T_R8G8B8A8,
0647     TEGRA210_IMAGE_FORMAT_T_A2B10G10R10,
0648     TEGRA210_IMAGE_FORMAT_T_A2R10G10B10,
0649     TEGRA210_IMAGE_FORMAT_T_B10G10R10A2,
0650     TEGRA210_IMAGE_FORMAT_T_R10G10B10A2,
0651 
0652     TEGRA210_IMAGE_FORMAT_T_A8Y8U8V8 = 193,
0653     TEGRA210_IMAGE_FORMAT_T_V8U8Y8A8,
0654 
0655     TEGRA210_IMAGE_FORMAT_T_A2Y10U10V10 = 197,
0656     TEGRA210_IMAGE_FORMAT_T_V10U10Y10A2,
0657     TEGRA210_IMAGE_FORMAT_T_Y8_U8__Y8_V8,
0658     TEGRA210_IMAGE_FORMAT_T_Y8_V8__Y8_U8,
0659     TEGRA210_IMAGE_FORMAT_T_U8_Y8__V8_Y8,
0660     TEGRA210_IMAGE_FORMAT_T_V8_Y8__U8_Y8,
0661 
0662     TEGRA210_IMAGE_FORMAT_T_Y8__U8__V8_N444 = 224,
0663     TEGRA210_IMAGE_FORMAT_T_Y8__U8V8_N444,
0664     TEGRA210_IMAGE_FORMAT_T_Y8__V8U8_N444,
0665     TEGRA210_IMAGE_FORMAT_T_Y8__U8__V8_N422,
0666     TEGRA210_IMAGE_FORMAT_T_Y8__U8V8_N422,
0667     TEGRA210_IMAGE_FORMAT_T_Y8__V8U8_N422,
0668     TEGRA210_IMAGE_FORMAT_T_Y8__U8__V8_N420,
0669     TEGRA210_IMAGE_FORMAT_T_Y8__U8V8_N420,
0670     TEGRA210_IMAGE_FORMAT_T_Y8__V8U8_N420,
0671     TEGRA210_IMAGE_FORMAT_T_X2LC10LB10LA10,
0672     TEGRA210_IMAGE_FORMAT_T_A2R6R6R6R6R6,
0673 };
0674 
0675 #define TEGRA210_VIDEO_FMT(DATA_TYPE, BIT_WIDTH, MBUS_CODE, BPP,    \
0676                FORMAT, FOURCC)              \
0677 {                                   \
0678     TEGRA_IMAGE_DT_##DATA_TYPE,                 \
0679     BIT_WIDTH,                          \
0680     MEDIA_BUS_FMT_##MBUS_CODE,                  \
0681     BPP,                                \
0682     TEGRA210_IMAGE_FORMAT_##FORMAT,                 \
0683     V4L2_PIX_FMT_##FOURCC,                      \
0684 }
0685 
0686 /* Tegra210 supported video formats */
0687 static const struct tegra_video_format tegra210_video_formats[] = {
0688     /* RAW 8 */
0689     TEGRA210_VIDEO_FMT(RAW8, 8, SRGGB8_1X8, 1, T_L8, SRGGB8),
0690     TEGRA210_VIDEO_FMT(RAW8, 8, SGRBG8_1X8, 1, T_L8, SGRBG8),
0691     TEGRA210_VIDEO_FMT(RAW8, 8, SGBRG8_1X8, 1, T_L8, SGBRG8),
0692     TEGRA210_VIDEO_FMT(RAW8, 8, SBGGR8_1X8, 1, T_L8, SBGGR8),
0693     /* RAW 10 */
0694     TEGRA210_VIDEO_FMT(RAW10, 10, SRGGB10_1X10, 2, T_R16_I, SRGGB10),
0695     TEGRA210_VIDEO_FMT(RAW10, 10, SGRBG10_1X10, 2, T_R16_I, SGRBG10),
0696     TEGRA210_VIDEO_FMT(RAW10, 10, SGBRG10_1X10, 2, T_R16_I, SGBRG10),
0697     TEGRA210_VIDEO_FMT(RAW10, 10, SBGGR10_1X10, 2, T_R16_I, SBGGR10),
0698     /* RAW 12 */
0699     TEGRA210_VIDEO_FMT(RAW12, 12, SRGGB12_1X12, 2, T_R16_I, SRGGB12),
0700     TEGRA210_VIDEO_FMT(RAW12, 12, SGRBG12_1X12, 2, T_R16_I, SGRBG12),
0701     TEGRA210_VIDEO_FMT(RAW12, 12, SGBRG12_1X12, 2, T_R16_I, SGBRG12),
0702     TEGRA210_VIDEO_FMT(RAW12, 12, SBGGR12_1X12, 2, T_R16_I, SBGGR12),
0703     /* RGB888 */
0704     TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X24, 4, T_A8R8G8B8, XBGR32),
0705     TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X32_PADHI, 4, T_A8B8G8R8,
0706                RGBX32),
0707     /* YUV422 */
0708     TEGRA210_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 2, T_U8_Y8__V8_Y8, YVYU),
0709     TEGRA210_VIDEO_FMT(YUV422_8, 16, VYUY8_1X16, 2, T_V8_Y8__U8_Y8, YUYV),
0710     TEGRA210_VIDEO_FMT(YUV422_8, 16, YUYV8_1X16, 2, T_Y8_U8__Y8_V8, VYUY),
0711     TEGRA210_VIDEO_FMT(YUV422_8, 16, YVYU8_1X16, 2, T_Y8_V8__Y8_U8, UYVY),
0712     TEGRA210_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 1, T_Y8__V8U8_N422, NV16),
0713     TEGRA210_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 2, T_U8_Y8__V8_Y8, YVYU),
0714     TEGRA210_VIDEO_FMT(YUV422_8, 16, VYUY8_2X8, 2, T_V8_Y8__U8_Y8, YUYV),
0715     TEGRA210_VIDEO_FMT(YUV422_8, 16, YUYV8_2X8, 2, T_Y8_U8__Y8_V8, VYUY),
0716     TEGRA210_VIDEO_FMT(YUV422_8, 16, YVYU8_2X8, 2, T_Y8_V8__Y8_U8, UYVY),
0717 };
0718 
0719 /* Tegra210 VI operations */
0720 static const struct tegra_vi_ops tegra210_vi_ops = {
0721     .vi_start_streaming = tegra210_vi_start_streaming,
0722     .vi_stop_streaming = tegra210_vi_stop_streaming,
0723 };
0724 
0725 /* Tegra210 VI SoC data */
0726 const struct tegra_vi_soc tegra210_vi_soc = {
0727     .video_formats = tegra210_video_formats,
0728     .nformats = ARRAY_SIZE(tegra210_video_formats),
0729     .ops = &tegra210_vi_ops,
0730     .hw_revision = 3,
0731     .vi_max_channels = 6,
0732 #if IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)
0733     .vi_max_clk_hz = 499200000,
0734 #else
0735     .vi_max_clk_hz = 998400000,
0736 #endif
0737 };
0738 
0739 /* Tegra210 CSI PHY registers accessors */
0740 static void csi_write(struct tegra_csi *csi, u8 portno, unsigned int addr,
0741               u32 val)
0742 {
0743     void __iomem *csi_pp_base;
0744 
0745     csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
0746 
0747     writel_relaxed(val, csi_pp_base + addr);
0748 }
0749 
0750 /* Tegra210 CSI Pixel parser registers accessors */
0751 static void pp_write(struct tegra_csi *csi, u8 portno, u32 addr, u32 val)
0752 {
0753     void __iomem *csi_pp_base;
0754     unsigned int offset;
0755 
0756     csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
0757     offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
0758 
0759     writel_relaxed(val, csi_pp_base + offset + addr);
0760 }
0761 
0762 static u32 pp_read(struct tegra_csi *csi, u8 portno, u32 addr)
0763 {
0764     void __iomem *csi_pp_base;
0765     unsigned int offset;
0766 
0767     csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
0768     offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
0769 
0770     return readl_relaxed(csi_pp_base + offset + addr);
0771 }
0772 
0773 /* Tegra210 CSI CIL A/B port registers accessors */
0774 static void cil_write(struct tegra_csi *csi, u8 portno, u32 addr, u32 val)
0775 {
0776     void __iomem *csi_cil_base;
0777     unsigned int offset;
0778 
0779     csi_cil_base = csi->iomem + CSI_PP_OFFSET(portno >> 1) +
0780                TEGRA210_CSI_CIL_OFFSET;
0781     offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
0782 
0783     writel_relaxed(val, csi_cil_base + offset + addr);
0784 }
0785 
0786 static u32 cil_read(struct tegra_csi *csi, u8 portno, u32 addr)
0787 {
0788     void __iomem *csi_cil_base;
0789     unsigned int offset;
0790 
0791     csi_cil_base = csi->iomem + CSI_PP_OFFSET(portno >> 1) +
0792                TEGRA210_CSI_CIL_OFFSET;
0793     offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
0794 
0795     return readl_relaxed(csi_cil_base + offset + addr);
0796 }
0797 
0798 /* Tegra210 CSI Test pattern generator registers accessor */
0799 static void tpg_write(struct tegra_csi *csi, u8 portno, unsigned int addr,
0800               u32 val)
0801 {
0802     void __iomem *csi_pp_base;
0803     unsigned int offset;
0804 
0805     csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
0806     offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET +
0807          TEGRA210_CSI_TPG_OFFSET;
0808 
0809     writel_relaxed(val, csi_pp_base + offset + addr);
0810 }
0811 
0812 /*
0813  * Tegra210 CSI operations
0814  */
0815 static void tegra210_csi_port_recover(struct tegra_csi_channel *csi_chan,
0816                       u8 portno)
0817 {
0818     struct tegra_csi *csi = csi_chan->csi;
0819     u32 val;
0820 
0821     /*
0822      * Recover CSI hardware in case of capture errors by issuing
0823      * software reset to CSICIL sensor, pixel parser, and clear errors
0824      * to have clean capture on  next streaming.
0825      */
0826     val = pp_read(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS);
0827     dev_dbg(csi->dev, "TEGRA_CSI_PIXEL_PARSER_STATUS 0x%08x\n", val);
0828 
0829     val = cil_read(csi, portno, TEGRA_CSI_CIL_STATUS);
0830     dev_dbg(csi->dev, "TEGRA_CSI_CIL_STATUS 0x%08x\n", val);
0831 
0832     val = cil_read(csi, portno, TEGRA_CSI_CILX_STATUS);
0833     dev_dbg(csi->dev, "TEGRA_CSI_CILX_STATUS 0x%08x\n", val);
0834 
0835     if (csi_chan->numlanes == 4) {
0836         /* reset CSI CIL sensor */
0837         cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
0838         cil_write(csi, portno + 1, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
0839         /*
0840          * SW_STATUS_RESET resets all status bits of PPA, PPB, CILA,
0841          * CILB status registers and debug counters.
0842          * So, SW_STATUS_RESET can be used only when CSI brick is in
0843          * x4 mode.
0844          */
0845         csi_write(csi, portno, TEGRA_CSI_CSI_SW_STATUS_RESET, 0x1);
0846 
0847         /* sleep for 20 clock cycles to drain the FIFO */
0848         usleep_range(10, 20);
0849 
0850         cil_write(csi, portno + 1, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
0851         cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
0852         csi_write(csi, portno, TEGRA_CSI_CSI_SW_STATUS_RESET, 0x0);
0853     } else {
0854         /* reset CSICIL sensor */
0855         cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
0856         usleep_range(10, 20);
0857         cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
0858 
0859         /* clear the errors */
0860         pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS,
0861              0xffffffff);
0862         cil_write(csi, portno, TEGRA_CSI_CIL_STATUS, 0xffffffff);
0863         cil_write(csi, portno, TEGRA_CSI_CILX_STATUS, 0xffffffff);
0864     }
0865 }
0866 
0867 static void tegra210_csi_error_recover(struct tegra_csi_channel *csi_chan)
0868 {
0869     u8 *portnos = csi_chan->csi_port_nums;
0870     int i;
0871 
0872     for (i = 0; i < csi_chan->numgangports; i++)
0873         tegra210_csi_port_recover(csi_chan, portnos[i]);
0874 }
0875 
0876 static int
0877 tegra210_csi_port_start_streaming(struct tegra_csi_channel *csi_chan,
0878                   u8 portno)
0879 {
0880     struct tegra_csi *csi = csi_chan->csi;
0881     u8 clk_settle_time = 0;
0882     u8 ths_settle_time = 10;
0883     u32 val;
0884 
0885     if (!csi_chan->pg_mode)
0886         tegra_csi_calc_settle_time(csi_chan, portno, &clk_settle_time,
0887                        &ths_settle_time);
0888 
0889     csi_write(csi, portno, TEGRA_CSI_CLKEN_OVERRIDE, 0);
0890 
0891     /* clean up status */
0892     pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS, 0xffffffff);
0893     cil_write(csi, portno, TEGRA_CSI_CIL_STATUS, 0xffffffff);
0894     cil_write(csi, portno, TEGRA_CSI_CILX_STATUS, 0xffffffff);
0895     cil_write(csi, portno, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
0896 
0897     /* CIL PHY registers setup */
0898     cil_write(csi, portno, TEGRA_CSI_CIL_PAD_CONFIG0, 0x0);
0899     cil_write(csi, portno, TEGRA_CSI_CIL_PHY_CONTROL,
0900           FIELD_PREP(CLK_SETTLE_MASK, clk_settle_time) |
0901           FIELD_PREP(THS_SETTLE_MASK, ths_settle_time));
0902 
0903     /*
0904      * The CSI unit provides for connection of up to six cameras in
0905      * the system and is organized as three identical instances of
0906      * two MIPI support blocks, each with a separate 4-lane
0907      * interface that can be configured as a single camera with 4
0908      * lanes or as a dual camera with 2 lanes available for each
0909      * camera.
0910      */
0911     if (csi_chan->numlanes == 4) {
0912         cil_write(csi, portno + 1, TEGRA_CSI_CIL_STATUS, 0xffffffff);
0913         cil_write(csi, portno + 1, TEGRA_CSI_CILX_STATUS, 0xffffffff);
0914         cil_write(csi, portno + 1, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
0915 
0916         cil_write(csi, portno, TEGRA_CSI_CIL_PAD_CONFIG0,
0917               BRICK_CLOCK_A_4X);
0918         cil_write(csi, portno + 1, TEGRA_CSI_CIL_PAD_CONFIG0, 0x0);
0919         cil_write(csi, portno + 1, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
0920         cil_write(csi, portno + 1, TEGRA_CSI_CIL_PHY_CONTROL,
0921               FIELD_PREP(CLK_SETTLE_MASK, clk_settle_time) |
0922               FIELD_PREP(THS_SETTLE_MASK, ths_settle_time));
0923         csi_write(csi, portno, TEGRA_CSI_PHY_CIL_COMMAND,
0924               CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_ENABLE);
0925     } else {
0926         val = ((portno & 1) == PORT_A) ?
0927               CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_NOP :
0928               CSI_B_PHY_CIL_ENABLE | CSI_A_PHY_CIL_NOP;
0929         csi_write(csi, portno, TEGRA_CSI_PHY_CIL_COMMAND, val);
0930     }
0931 
0932     /* CSI pixel parser registers setup */
0933     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
0934          (0xf << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
0935          CSI_PP_SINGLE_SHOT_ENABLE | CSI_PP_RST);
0936     pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0);
0937     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_CONTROL0,
0938          CSI_PP_PACKET_HEADER_SENT |
0939          CSI_PP_DATA_IDENTIFIER_ENABLE |
0940          CSI_PP_WORD_COUNT_SELECT_HEADER |
0941          CSI_PP_CRC_CHECK_ENABLE |  CSI_PP_WC_CHECK |
0942          CSI_PP_OUTPUT_FORMAT_STORE | CSI_PPA_PAD_LINE_NOPAD |
0943          CSI_PP_HEADER_EC_DISABLE | CSI_PPA_PAD_FRAME_NOPAD |
0944          (portno & 1));
0945     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_CONTROL1,
0946          (0x1 << CSI_PP_TOP_FIELD_FRAME_OFFSET) |
0947          (0x1 << CSI_PP_TOP_FIELD_FRAME_MASK_OFFSET));
0948     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_GAP,
0949          0x14 << PP_FRAME_MIN_GAP_OFFSET);
0950     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME, 0x0);
0951     pp_write(csi, portno, TEGRA_CSI_INPUT_STREAM_CONTROL,
0952          (0x3f << CSI_SKIP_PACKET_THRESHOLD_OFFSET) |
0953          (csi_chan->numlanes - 1));
0954 
0955     /* TPG setup */
0956     if (csi_chan->pg_mode) {
0957         tpg_write(csi, portno, TEGRA_CSI_PATTERN_GENERATOR_CTRL,
0958               ((csi_chan->pg_mode - 1) << PG_MODE_OFFSET) |
0959               PG_ENABLE);
0960         tpg_write(csi, portno, TEGRA_CSI_PG_BLANK,
0961               csi_chan->v_blank << PG_VBLANK_OFFSET |
0962               csi_chan->h_blank);
0963         tpg_write(csi, portno, TEGRA_CSI_PG_PHASE, 0x0);
0964         tpg_write(csi, portno, TEGRA_CSI_PG_RED_FREQ,
0965               (0x10 << PG_RED_VERT_INIT_FREQ_OFFSET) |
0966               (0x10 << PG_RED_HOR_INIT_FREQ_OFFSET));
0967         tpg_write(csi, portno, TEGRA_CSI_PG_RED_FREQ_RATE, 0x0);
0968         tpg_write(csi, portno, TEGRA_CSI_PG_GREEN_FREQ,
0969               (0x10 << PG_GREEN_VERT_INIT_FREQ_OFFSET) |
0970               (0x10 << PG_GREEN_HOR_INIT_FREQ_OFFSET));
0971         tpg_write(csi, portno, TEGRA_CSI_PG_GREEN_FREQ_RATE, 0x0);
0972         tpg_write(csi, portno, TEGRA_CSI_PG_BLUE_FREQ,
0973               (0x10 << PG_BLUE_VERT_INIT_FREQ_OFFSET) |
0974               (0x10 << PG_BLUE_HOR_INIT_FREQ_OFFSET));
0975         tpg_write(csi, portno, TEGRA_CSI_PG_BLUE_FREQ_RATE, 0x0);
0976     }
0977 
0978     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
0979          (0xf << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
0980          CSI_PP_SINGLE_SHOT_ENABLE | CSI_PP_ENABLE);
0981 
0982     return 0;
0983 }
0984 
0985 static void
0986 tegra210_csi_port_stop_streaming(struct tegra_csi_channel *csi_chan, u8 portno)
0987 {
0988     struct tegra_csi *csi = csi_chan->csi;
0989     u32 val;
0990 
0991     val = pp_read(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS);
0992 
0993     dev_dbg(csi->dev, "TEGRA_CSI_PIXEL_PARSER_STATUS 0x%08x\n", val);
0994     pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS, val);
0995 
0996     val = cil_read(csi, portno, TEGRA_CSI_CIL_STATUS);
0997     dev_dbg(csi->dev, "TEGRA_CSI_CIL_STATUS 0x%08x\n", val);
0998     cil_write(csi, portno, TEGRA_CSI_CIL_STATUS, val);
0999 
1000     val = cil_read(csi, portno, TEGRA_CSI_CILX_STATUS);
1001     dev_dbg(csi->dev, "TEGRA_CSI_CILX_STATUS 0x%08x\n", val);
1002     cil_write(csi, portno, TEGRA_CSI_CILX_STATUS, val);
1003 
1004     pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
1005          (0xf << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
1006          CSI_PP_DISABLE);
1007 
1008     if (csi_chan->pg_mode) {
1009         tpg_write(csi, portno, TEGRA_CSI_PATTERN_GENERATOR_CTRL,
1010               PG_DISABLE);
1011         return;
1012     }
1013 
1014     if (csi_chan->numlanes == 4) {
1015         csi_write(csi, portno, TEGRA_CSI_PHY_CIL_COMMAND,
1016               CSI_A_PHY_CIL_DISABLE |
1017               CSI_B_PHY_CIL_DISABLE);
1018     } else {
1019         val = ((portno & 1) == PORT_A) ?
1020               CSI_A_PHY_CIL_DISABLE | CSI_B_PHY_CIL_NOP :
1021               CSI_B_PHY_CIL_DISABLE | CSI_A_PHY_CIL_NOP;
1022         csi_write(csi, portno, TEGRA_CSI_PHY_CIL_COMMAND, val);
1023     }
1024 }
1025 
1026 static int tegra210_csi_start_streaming(struct tegra_csi_channel *csi_chan)
1027 {
1028     u8 *portnos = csi_chan->csi_port_nums;
1029     int ret, i;
1030 
1031     for (i = 0; i < csi_chan->numgangports; i++) {
1032         ret = tegra210_csi_port_start_streaming(csi_chan, portnos[i]);
1033         if (ret)
1034             goto stream_start_fail;
1035     }
1036 
1037     return 0;
1038 
1039 stream_start_fail:
1040     for (i = i - 1; i >= 0; i--)
1041         tegra210_csi_port_stop_streaming(csi_chan, portnos[i]);
1042 
1043     return ret;
1044 }
1045 
1046 static void tegra210_csi_stop_streaming(struct tegra_csi_channel *csi_chan)
1047 {
1048     u8 *portnos = csi_chan->csi_port_nums;
1049     int i;
1050 
1051     for (i = 0; i < csi_chan->numgangports; i++)
1052         tegra210_csi_port_stop_streaming(csi_chan, portnos[i]);
1053 }
1054 
1055 /*
1056  * Tegra210 CSI TPG frame rate table with horizontal and vertical
1057  * blanking intervals for corresponding format and resolution.
1058  * Blanking intervals are tuned values from design team for max TPG
1059  * clock rate.
1060  */
1061 static const struct tpg_framerate tegra210_tpg_frmrate_table[] = {
1062     {
1063         .frmsize = { 1280, 720 },
1064         .code = MEDIA_BUS_FMT_SRGGB10_1X10,
1065         .framerate = 120,
1066         .h_blank = 512,
1067         .v_blank = 8,
1068     },
1069     {
1070         .frmsize = { 1920, 1080 },
1071         .code = MEDIA_BUS_FMT_SRGGB10_1X10,
1072         .framerate = 60,
1073         .h_blank = 512,
1074         .v_blank = 8,
1075     },
1076     {
1077         .frmsize = { 3840, 2160 },
1078         .code = MEDIA_BUS_FMT_SRGGB10_1X10,
1079         .framerate = 20,
1080         .h_blank = 8,
1081         .v_blank = 8,
1082     },
1083     {
1084         .frmsize = { 1280, 720 },
1085         .code = MEDIA_BUS_FMT_RGB888_1X32_PADHI,
1086         .framerate = 60,
1087         .h_blank = 512,
1088         .v_blank = 8,
1089     },
1090     {
1091         .frmsize = { 1920, 1080 },
1092         .code = MEDIA_BUS_FMT_RGB888_1X32_PADHI,
1093         .framerate = 30,
1094         .h_blank = 512,
1095         .v_blank = 8,
1096     },
1097     {
1098         .frmsize = { 3840, 2160 },
1099         .code = MEDIA_BUS_FMT_RGB888_1X32_PADHI,
1100         .framerate = 8,
1101         .h_blank = 8,
1102         .v_blank = 8,
1103     },
1104 };
1105 
1106 static const char * const tegra210_csi_cil_clks[] = {
1107     "csi",
1108     "cilab",
1109     "cilcd",
1110     "cile",
1111 #if IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)
1112     "csi_tpg",
1113 #endif
1114 };
1115 
1116 /* Tegra210 CSI operations */
1117 static const struct tegra_csi_ops tegra210_csi_ops = {
1118     .csi_start_streaming = tegra210_csi_start_streaming,
1119     .csi_stop_streaming = tegra210_csi_stop_streaming,
1120     .csi_err_recover = tegra210_csi_error_recover,
1121 };
1122 
1123 /* Tegra210 CSI SoC data */
1124 const struct tegra_csi_soc tegra210_csi_soc = {
1125     .ops = &tegra210_csi_ops,
1126     .csi_max_channels = 6,
1127     .clk_names = tegra210_csi_cil_clks,
1128     .num_clks = ARRAY_SIZE(tegra210_csi_cil_clks),
1129     .tpg_frmrate_table = tegra210_tpg_frmrate_table,
1130     .tpg_frmrate_table_size = ARRAY_SIZE(tegra210_tpg_frmrate_table),
1131 };