linux/drivers/staging/media/tegra-video/tegra210.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2020 NVIDIA CORPORATION.  All rights reserved.
   4 */
   5
   6/*
   7 * This source file contains Tegra210 supported video formats,
   8 * VI and CSI SoC specific data, operations and registers accessors.
   9 */
  10#include <linux/bitfield.h>
  11#include <linux/clk.h>
  12#include <linux/clk/tegra.h>
  13#include <linux/delay.h>
  14#include <linux/host1x.h>
  15#include <linux/kthread.h>
  16
  17#include "csi.h"
  18#include "vi.h"
  19
  20#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT                    msecs_to_jiffies(200)
  21
  22/* Tegra210 VI registers */
  23#define TEGRA_VI_CFG_VI_INCR_SYNCPT                     0x000
  24#define   VI_CFG_VI_INCR_SYNCPT_COND(x)                 (((x) & 0xff) << 8)
  25#define   VI_CSI_PP_FRAME_START(port)                   (5 + (port) * 4)
  26#define   VI_CSI_MW_ACK_DONE(port)                      (7 + (port) * 4)
  27#define TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL               0x004
  28#define   VI_INCR_SYNCPT_NO_STALL                       BIT(8)
  29#define TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR               0x008
  30#define TEGRA_VI_CFG_CG_CTRL                            0x0b8
  31#define   VI_CG_2ND_LEVEL_EN                            0x1
  32
  33/* Tegra210 VI CSI registers */
  34#define TEGRA_VI_CSI_SW_RESET                           0x000
  35#define TEGRA_VI_CSI_SINGLE_SHOT                        0x004
  36#define   SINGLE_SHOT_CAPTURE                           0x1
  37#define TEGRA_VI_CSI_IMAGE_DEF                          0x00c
  38#define   BYPASS_PXL_TRANSFORM_OFFSET                   24
  39#define   IMAGE_DEF_FORMAT_OFFSET                       16
  40#define   IMAGE_DEF_DEST_MEM                            0x1
  41#define TEGRA_VI_CSI_IMAGE_SIZE                         0x018
  42#define   IMAGE_SIZE_HEIGHT_OFFSET                      16
  43#define TEGRA_VI_CSI_IMAGE_SIZE_WC                      0x01c
  44#define TEGRA_VI_CSI_IMAGE_DT                           0x020
  45#define TEGRA_VI_CSI_SURFACE0_OFFSET_MSB                0x024
  46#define TEGRA_VI_CSI_SURFACE0_OFFSET_LSB                0x028
  47#define TEGRA_VI_CSI_SURFACE1_OFFSET_MSB                0x02c
  48#define TEGRA_VI_CSI_SURFACE1_OFFSET_LSB                0x030
  49#define TEGRA_VI_CSI_SURFACE2_OFFSET_MSB                0x034
  50#define TEGRA_VI_CSI_SURFACE2_OFFSET_LSB                0x038
  51#define TEGRA_VI_CSI_SURFACE0_STRIDE                    0x054
  52#define TEGRA_VI_CSI_SURFACE1_STRIDE                    0x058
  53#define TEGRA_VI_CSI_SURFACE2_STRIDE                    0x05c
  54#define TEGRA_VI_CSI_SURFACE_HEIGHT0                    0x060
  55#define TEGRA_VI_CSI_ERROR_STATUS                       0x084
  56
  57/* Tegra210 CSI Pixel Parser registers: Starts from 0x838, offset 0x0 */
  58#define TEGRA_CSI_INPUT_STREAM_CONTROL                  0x000
  59#define   CSI_SKIP_PACKET_THRESHOLD_OFFSET              16
  60#define TEGRA_CSI_PIXEL_STREAM_CONTROL0                 0x004
  61#define   CSI_PP_PACKET_HEADER_SENT                     BIT(4)
  62#define   CSI_PP_DATA_IDENTIFIER_ENABLE                 BIT(5)
  63#define   CSI_PP_WORD_COUNT_SELECT_HEADER               BIT(6)
  64#define   CSI_PP_CRC_CHECK_ENABLE                       BIT(7)
  65#define   CSI_PP_WC_CHECK                               BIT(8)
  66#define   CSI_PP_OUTPUT_FORMAT_STORE                    (0x3 << 16)
  67#define   CSI_PPA_PAD_LINE_NOPAD                        (0x2 << 24)
  68#define   CSI_PP_HEADER_EC_DISABLE                      (0x1 << 27)
  69#define   CSI_PPA_PAD_FRAME_NOPAD                       (0x2 << 28)
  70#define TEGRA_CSI_PIXEL_STREAM_CONTROL1                 0x008
  71#define   CSI_PP_TOP_FIELD_FRAME_OFFSET                 0
  72#define   CSI_PP_TOP_FIELD_FRAME_MASK_OFFSET            4
  73#define TEGRA_CSI_PIXEL_STREAM_GAP                      0x00c
  74#define   PP_FRAME_MIN_GAP_OFFSET                       16
  75#define TEGRA_CSI_PIXEL_STREAM_PP_COMMAND               0x010
  76#define   CSI_PP_ENABLE                                 0x1
  77#define   CSI_PP_DISABLE                                0x2
  78#define   CSI_PP_RST                                    0x3
  79#define   CSI_PP_SINGLE_SHOT_ENABLE                     (0x1 << 2)
  80#define   CSI_PP_START_MARKER_FRAME_MAX_OFFSET          12
  81#define TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME           0x014
  82#define TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK           0x018
  83#define TEGRA_CSI_PIXEL_PARSER_STATUS                   0x01c
  84
  85/* Tegra210 CSI PHY registers */
  86/* CSI_PHY_CIL_COMMAND_0 offset 0x0d0 from TEGRA_CSI_PIXEL_PARSER_0_BASE */
  87#define TEGRA_CSI_PHY_CIL_COMMAND                       0x0d0
  88#define   CSI_A_PHY_CIL_NOP                             0x0
  89#define   CSI_A_PHY_CIL_ENABLE                          0x1
  90#define   CSI_A_PHY_CIL_DISABLE                         0x2
  91#define   CSI_A_PHY_CIL_ENABLE_MASK                     0x3
  92#define   CSI_B_PHY_CIL_NOP                             (0x0 << 8)
  93#define   CSI_B_PHY_CIL_ENABLE                          (0x1 << 8)
  94#define   CSI_B_PHY_CIL_DISABLE                         (0x2 << 8)
  95#define   CSI_B_PHY_CIL_ENABLE_MASK                     (0x3 << 8)
  96
  97#define TEGRA_CSI_CIL_PAD_CONFIG0                       0x000
  98#define   BRICK_CLOCK_A_4X                              (0x1 << 16)
  99#define   BRICK_CLOCK_B_4X                              (0x2 << 16)
 100#define TEGRA_CSI_CIL_PAD_CONFIG1                       0x004
 101#define TEGRA_CSI_CIL_PHY_CONTROL                       0x008
 102#define   CLK_SETTLE_MASK                               GENMASK(13, 8)
 103#define   THS_SETTLE_MASK                               GENMASK(5, 0)
 104#define TEGRA_CSI_CIL_INTERRUPT_MASK                    0x00c
 105#define TEGRA_CSI_CIL_STATUS                            0x010
 106#define TEGRA_CSI_CILX_STATUS                           0x014
 107#define TEGRA_CSI_CIL_SW_SENSOR_RESET                   0x020
 108
 109#define TEGRA_CSI_PATTERN_GENERATOR_CTRL                0x000
 110#define   PG_MODE_OFFSET                                2
 111#define   PG_ENABLE                                     0x1
 112#define   PG_DISABLE                                    0x0
 113#define TEGRA_CSI_PG_BLANK                              0x004
 114#define   PG_VBLANK_OFFSET                              16
 115#define TEGRA_CSI_PG_PHASE                              0x008
 116#define TEGRA_CSI_PG_RED_FREQ                           0x00c
 117#define   PG_RED_VERT_INIT_FREQ_OFFSET                  16
 118#define   PG_RED_HOR_INIT_FREQ_OFFSET                   0
 119#define TEGRA_CSI_PG_RED_FREQ_RATE                      0x010
 120#define TEGRA_CSI_PG_GREEN_FREQ                         0x014
 121#define   PG_GREEN_VERT_INIT_FREQ_OFFSET                16
 122#define   PG_GREEN_HOR_INIT_FREQ_OFFSET                 0
 123#define TEGRA_CSI_PG_GREEN_FREQ_RATE                    0x018
 124#define TEGRA_CSI_PG_BLUE_FREQ                          0x01c
 125#define   PG_BLUE_VERT_INIT_FREQ_OFFSET                 16
 126#define   PG_BLUE_HOR_INIT_FREQ_OFFSET                  0
 127#define TEGRA_CSI_PG_BLUE_FREQ_RATE                     0x020
 128#define TEGRA_CSI_PG_AOHDR                              0x024
 129#define TEGRA_CSI_CSI_SW_STATUS_RESET                   0x214
 130#define TEGRA_CSI_CLKEN_OVERRIDE                        0x218
 131
 132#define TEGRA210_CSI_PORT_OFFSET                        0x34
 133#define TEGRA210_CSI_CIL_OFFSET                         0x0f4
 134#define TEGRA210_CSI_TPG_OFFSET                         0x18c
 135
 136#define CSI_PP_OFFSET(block)                            ((block) * 0x800)
 137#define TEGRA210_VI_CSI_BASE(x)                         (0x100 + (x) * 0x100)
 138
 139/* Tegra210 VI registers accessors */
 140static void tegra_vi_write(struct tegra_vi_channel *chan, unsigned int addr,
 141                           u32 val)
 142{
 143        writel_relaxed(val, chan->vi->iomem + addr);
 144}
 145
 146static u32 tegra_vi_read(struct tegra_vi_channel *chan, unsigned int addr)
 147{
 148        return readl_relaxed(chan->vi->iomem + addr);
 149}
 150
 151/* Tegra210 VI_CSI registers accessors */
 152static void vi_csi_write(struct tegra_vi_channel *chan, u8 portno,
 153                         unsigned int addr, u32 val)
 154{
 155        void __iomem *vi_csi_base;
 156
 157        vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(portno);
 158
 159        writel_relaxed(val, vi_csi_base + addr);
 160}
 161
 162static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno,
 163                       unsigned int addr)
 164{
 165        void __iomem *vi_csi_base;
 166
 167        vi_csi_base = chan->vi->iomem + TEGRA210_VI_CSI_BASE(portno);
 168
 169        return readl_relaxed(vi_csi_base + addr);
 170}
 171
 172/*
 173 * Tegra210 VI channel capture operations
 174 */
 175static int tegra_channel_capture_setup(struct tegra_vi_channel *chan,
 176                                       u8 portno)
 177{
 178        u32 height = chan->format.height;
 179        u32 width = chan->format.width;
 180        u32 format = chan->fmtinfo->img_fmt;
 181        u32 data_type = chan->fmtinfo->img_dt;
 182        u32 word_count = (width * chan->fmtinfo->bit_width) / 8;
 183        u32 bypass_pixel_transform = BIT(BYPASS_PXL_TRANSFORM_OFFSET);
 184
 185        /*
 186         * VI Pixel transformation unit converts source pixels data format
 187         * into selected destination pixel format and aligns properly while
 188         * interfacing with memory packer.
 189         * This pixel transformation should be enabled for YUV and RGB
 190         * formats and should be bypassed for RAW formats as RAW formats
 191         * only support direct to memory.
 192         */
 193        if (chan->pg_mode || data_type == TEGRA_IMAGE_DT_YUV422_8 ||
 194            data_type == TEGRA_IMAGE_DT_RGB888)
 195                bypass_pixel_transform = 0;
 196
 197        /*
 198         * For x8 source streaming, the source image is split onto two x4 ports
 199         * with left half to first x4 port and right half to second x4 port.
 200         * So, use split width and corresponding word count for each x4 port.
 201         */
 202        if (chan->numgangports > 1) {
 203                width = width >> 1;
 204                word_count = (width * chan->fmtinfo->bit_width) / 8;
 205        }
 206
 207        vi_csi_write(chan, portno, TEGRA_VI_CSI_ERROR_STATUS, 0xffffffff);
 208        vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_DEF,
 209                     bypass_pixel_transform |
 210                     (format << IMAGE_DEF_FORMAT_OFFSET) |
 211                     IMAGE_DEF_DEST_MEM);
 212        vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_DT, data_type);
 213        vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_SIZE_WC, word_count);
 214        vi_csi_write(chan, portno, TEGRA_VI_CSI_IMAGE_SIZE,
 215                     (height << IMAGE_SIZE_HEIGHT_OFFSET) | width);
 216        return 0;
 217}
 218
 219static void tegra_channel_vi_soft_reset(struct tegra_vi_channel *chan,
 220                                        u8 portno)
 221{
 222        /* disable clock gating to enable continuous clock */
 223        tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, 0);
 224        /*
 225         * Soft reset memory client interface, pixel format logic, sensor
 226         * control logic, and a shadow copy logic to bring VI to clean state.
 227         */
 228        vi_csi_write(chan, portno, TEGRA_VI_CSI_SW_RESET, 0xf);
 229        usleep_range(100, 200);
 230        vi_csi_write(chan, portno, TEGRA_VI_CSI_SW_RESET, 0x0);
 231
 232        /* enable back VI clock gating */
 233        tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, VI_CG_2ND_LEVEL_EN);
 234}
 235
 236static void tegra_channel_capture_error_recover(struct tegra_vi_channel *chan,
 237                                                u8 portno)
 238{
 239        struct v4l2_subdev *subdev;
 240        u32 val;
 241
 242        /*
 243         * Recover VI and CSI hardware blocks in case of missing frame start
 244         * events due to source not streaming or noisy csi inputs from the
 245         * external source or many outstanding frame start or MW_ACK_DONE
 246         * events which can cause CSI and VI hardware hang.
 247         * This helps to have a clean capture for next frame.
 248         */
 249        val = vi_csi_read(chan, portno, TEGRA_VI_CSI_ERROR_STATUS);
 250        dev_dbg(&chan->video.dev, "TEGRA_VI_CSI_ERROR_STATUS 0x%08x\n", val);
 251        vi_csi_write(chan, portno, TEGRA_VI_CSI_ERROR_STATUS, val);
 252
 253        val = tegra_vi_read(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR);
 254        dev_dbg(&chan->video.dev,
 255                "TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR 0x%08x\n", val);
 256        tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, val);
 257
 258        /* recover VI by issuing software reset and re-setup for capture */
 259        tegra_channel_vi_soft_reset(chan, portno);
 260        tegra_channel_capture_setup(chan, portno);
 261
 262        /* recover CSI block */
 263        subdev = tegra_channel_get_remote_csi_subdev(chan);
 264        tegra_csi_error_recover(subdev);
 265}
 266
 267static struct tegra_channel_buffer *
 268dequeue_buf_done(struct tegra_vi_channel *chan)
 269{
 270        struct tegra_channel_buffer *buf = NULL;
 271
 272        spin_lock(&chan->done_lock);
 273        if (list_empty(&chan->done)) {
 274                spin_unlock(&chan->done_lock);
 275                return NULL;
 276        }
 277
 278        buf = list_first_entry(&chan->done,
 279                               struct tegra_channel_buffer, queue);
 280        if (buf)
 281                list_del_init(&buf->queue);
 282        spin_unlock(&chan->done_lock);
 283
 284        return buf;
 285}
 286
 287static void release_buffer(struct tegra_vi_channel *chan,
 288                           struct tegra_channel_buffer *buf,
 289                           enum vb2_buffer_state state)
 290{
 291        struct vb2_v4l2_buffer *vb = &buf->buf;
 292
 293        vb->sequence = chan->sequence++;
 294        vb->field = V4L2_FIELD_NONE;
 295        vb->vb2_buf.timestamp = ktime_get_ns();
 296        vb2_buffer_done(&vb->vb2_buf, state);
 297}
 298
 299static void tegra_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
 300                                          u8 portno, u32 buf_offset,
 301                                          struct tegra_channel_buffer *buf)
 302{
 303        int bytesperline = chan->format.bytesperline;
 304        u32 sizeimage = chan->format.sizeimage;
 305
 306        /* program buffer address by using surface 0 */
 307        vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_OFFSET_MSB,
 308                     ((u64)buf->addr + buf_offset) >> 32);
 309        vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_OFFSET_LSB,
 310                     buf->addr + buf_offset);
 311        vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE0_STRIDE, bytesperline);
 312
 313        if (chan->fmtinfo->fourcc != V4L2_PIX_FMT_NV16)
 314                return;
 315        /*
 316         * Program surface 1 for UV plane with offset sizeimage from Y plane.
 317         */
 318        vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_OFFSET_MSB,
 319                     (((u64)buf->addr + sizeimage / 2) + buf_offset) >> 32);
 320        vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_OFFSET_LSB,
 321                     buf->addr + sizeimage / 2 + buf_offset);
 322        vi_csi_write(chan, portno, TEGRA_VI_CSI_SURFACE1_STRIDE, bytesperline);
 323}
 324
 325static int tegra_channel_capture_frame(struct tegra_vi_channel *chan,
 326                                       struct tegra_channel_buffer *buf)
 327{
 328        u32 thresh, value, frame_start, mw_ack_done;
 329        u32 fs_thresh[GANG_PORTS_MAX];
 330        u8 *portnos = chan->portnos;
 331        int gang_bpl = (chan->format.width >> 1) * chan->fmtinfo->bpp;
 332        u32 buf_offset;
 333        bool capture_timedout = false;
 334        int err, i;
 335
 336        for (i = 0; i < chan->numgangports; i++) {
 337                /*
 338                 * Align buffers side-by-side for all consecutive x4 ports
 339                 * in gang ports using bytes per line based on source split
 340                 * width.
 341                 */
 342                buf_offset = i * roundup(gang_bpl, SURFACE_ALIGN_BYTES);
 343                tegra_channel_vi_buffer_setup(chan, portnos[i], buf_offset,
 344                                              buf);
 345
 346                /*
 347                 * Tegra VI block interacts with host1x syncpt to synchronize
 348                 * programmed condition and hardware operation for capture.
 349                 * Frame start and Memory write acknowledge syncpts has their
 350                 * own FIFO of depth 2.
 351                 *
 352                 * Syncpoint trigger conditions set through VI_INCR_SYNCPT
 353                 * register are added to HW syncpt FIFO and when HW triggers,
 354                 * syncpt condition is removed from the FIFO and counter at
 355                 * syncpoint index will be incremented by the hardware and
 356                 * software can wait for counter to reach threshold to
 357                 * synchronize capturing frame with hardware capture events.
 358                 */
 359
 360                /* increase channel syncpoint threshold for FRAME_START */
 361                thresh = host1x_syncpt_incr_max(chan->frame_start_sp[i], 1);
 362                fs_thresh[i] = thresh;
 363
 364                /* Program FRAME_START trigger condition syncpt request */
 365                frame_start = VI_CSI_PP_FRAME_START(portnos[i]);
 366                value = VI_CFG_VI_INCR_SYNCPT_COND(frame_start) |
 367                        host1x_syncpt_id(chan->frame_start_sp[i]);
 368                tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value);
 369
 370                /* increase channel syncpoint threshold for MW_ACK_DONE */
 371                thresh = host1x_syncpt_incr_max(chan->mw_ack_sp[i], 1);
 372                buf->mw_ack_sp_thresh[i] = thresh;
 373
 374                /* Program MW_ACK_DONE trigger condition syncpt request */
 375                mw_ack_done = VI_CSI_MW_ACK_DONE(portnos[i]);
 376                value = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) |
 377                        host1x_syncpt_id(chan->mw_ack_sp[i]);
 378                tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, value);
 379        }
 380
 381        /* enable single shot capture after all ganged ports are ready */
 382        for (i = 0; i < chan->numgangports; i++)
 383                vi_csi_write(chan, portnos[i], TEGRA_VI_CSI_SINGLE_SHOT,
 384                             SINGLE_SHOT_CAPTURE);
 385
 386        for (i = 0; i < chan->numgangports; i++) {
 387                /*
 388                 * Wait for syncpt counter to reach frame start event threshold
 389                 */
 390                err = host1x_syncpt_wait(chan->frame_start_sp[i], fs_thresh[i],
 391                                         TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value);
 392                if (err) {
 393                        capture_timedout = true;
 394                        /* increment syncpoint counter for timedout events */
 395                        host1x_syncpt_incr(chan->frame_start_sp[i]);
 396                        spin_lock(&chan->sp_incr_lock[i]);
 397                        host1x_syncpt_incr(chan->mw_ack_sp[i]);
 398                        spin_unlock(&chan->sp_incr_lock[i]);
 399                        /* clear errors and recover */
 400                        tegra_channel_capture_error_recover(chan, portnos[i]);
 401                }
 402        }
 403
 404        if (capture_timedout) {
 405                dev_err_ratelimited(&chan->video.dev,
 406                                    "frame start syncpt timeout: %d\n", err);
 407                release_buffer(chan, buf, VB2_BUF_STATE_ERROR);
 408                return err;
 409        }
 410
 411        /* move buffer to capture done queue */
 412        spin_lock(&chan->done_lock);
 413        list_add_tail(&buf->queue, &chan->done);
 414        spin_unlock(&chan->done_lock);
 415
 416        /* wait up kthread for capture done */
 417        wake_up_interruptible(&chan->done_wait);
 418
 419        return 0;
 420}
 421
 422static void tegra_channel_capture_done(struct tegra_vi_channel *chan,
 423                                       struct tegra_channel_buffer *buf)
 424{
 425        enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
 426        u32 value;
 427        bool capture_timedout = false;
 428        int ret, i;
 429
 430        for (i = 0; i < chan->numgangports; i++) {
 431                /*
 432                 * Wait for syncpt counter to reach MW_ACK_DONE event threshold
 433                 */
 434                ret = host1x_syncpt_wait(chan->mw_ack_sp[i],
 435                                         buf->mw_ack_sp_thresh[i],
 436                                         TEGRA_VI_SYNCPT_WAIT_TIMEOUT, &value);
 437                if (ret) {
 438                        capture_timedout = true;
 439                        state = VB2_BUF_STATE_ERROR;
 440                        /* increment syncpoint counter for timedout event */
 441                        spin_lock(&chan->sp_incr_lock[i]);
 442                        host1x_syncpt_incr(chan->mw_ack_sp[i]);
 443                        spin_unlock(&chan->sp_incr_lock[i]);
 444                }
 445        }
 446
 447        if (capture_timedout)
 448                dev_err_ratelimited(&chan->video.dev,
 449                                    "MW_ACK_DONE syncpt timeout: %d\n", ret);
 450        release_buffer(chan, buf, state);
 451}
 452
 453static int chan_capture_kthread_start(void *data)
 454{
 455        struct tegra_vi_channel *chan = data;
 456        struct tegra_channel_buffer *buf;
 457        unsigned int retries = 0;
 458        int err = 0;
 459
 460        while (1) {
 461                /*
 462                 * Source is not streaming if error is non-zero.
 463                 * So, do not dequeue buffers on error and let the thread sleep
 464                 * till kthread stop signal is received.
 465                 */
 466                wait_event_interruptible(chan->start_wait,
 467                                         kthread_should_stop() ||
 468                                         (!list_empty(&chan->capture) &&
 469                                         !err));
 470
 471                if (kthread_should_stop())
 472                        break;
 473
 474                /* dequeue the buffer and start capture */
 475                spin_lock(&chan->start_lock);
 476                if (list_empty(&chan->capture)) {
 477                        spin_unlock(&chan->start_lock);
 478                        continue;
 479                }
 480
 481                buf = list_first_entry(&chan->capture,
 482                                       struct tegra_channel_buffer, queue);
 483                list_del_init(&buf->queue);
 484                spin_unlock(&chan->start_lock);
 485
 486                err = tegra_channel_capture_frame(chan, buf);
 487                if (!err) {
 488                        retries = 0;
 489                        continue;
 490                }
 491
 492                if (retries++ > chan->syncpt_timeout_retry)
 493                        vb2_queue_error(&chan->queue);
 494                else
 495                        err = 0;
 496        }
 497
 498        return 0;
 499}
 500
 501static int chan_capture_kthread_finish(void *data)
 502{
 503        struct tegra_vi_channel *chan = data;
 504        struct tegra_channel_buffer *buf;
 505
 506        while (1) {
 507                wait_event_interruptible(chan->done_wait,
 508                                         !list_empty(&chan->done) ||
 509                                         kthread_should_stop());
 510
 511                /* dequeue buffers and finish capture */
 512                buf = dequeue_buf_done(chan);
 513                while (buf) {
 514                        tegra_channel_capture_done(chan, buf);
 515                        buf = dequeue_buf_done(chan);
 516                }
 517
 518                if (kthread_should_stop())
 519                        break;
 520        }
 521
 522        return 0;
 523}
 524
 525static int tegra210_vi_start_streaming(struct vb2_queue *vq, u32 count)
 526{
 527        struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
 528        struct media_pipeline *pipe = &chan->video.pipe;
 529        u32 val;
 530        u8 *portnos = chan->portnos;
 531        int ret, i;
 532
 533        tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, VI_CG_2ND_LEVEL_EN);
 534
 535        /* clear syncpt errors */
 536        val = tegra_vi_read(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR);
 537        tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, val);
 538
 539        /*
 540         * Sync point FIFO full stalls the host interface.
 541         * Setting NO_STALL will drop INCR_SYNCPT methods when fifos are
 542         * full and the corresponding condition bits in INCR_SYNCPT_ERROR
 543         * register will be set.
 544         * This allows SW to process error recovery.
 545         */
 546        tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL,
 547                       VI_INCR_SYNCPT_NO_STALL);
 548
 549        /* start the pipeline */
 550        ret = media_pipeline_start(&chan->video.entity, pipe);
 551        if (ret < 0)
 552                goto error_pipeline_start;
 553
 554        /* clear csi errors and do capture setup for all ports in gang mode */
 555        for (i = 0; i < chan->numgangports; i++) {
 556                val = vi_csi_read(chan, portnos[i], TEGRA_VI_CSI_ERROR_STATUS);
 557                vi_csi_write(chan, portnos[i], TEGRA_VI_CSI_ERROR_STATUS, val);
 558
 559                tegra_channel_capture_setup(chan, portnos[i]);
 560        }
 561
 562        ret = tegra_channel_set_stream(chan, true);
 563        if (ret < 0)
 564                goto error_set_stream;
 565
 566        chan->sequence = 0;
 567
 568        /* start kthreads to capture data to buffer and return them */
 569        chan->kthread_start_capture = kthread_run(chan_capture_kthread_start,
 570                                                  chan, "%s:0",
 571                                                  chan->video.name);
 572        if (IS_ERR(chan->kthread_start_capture)) {
 573                ret = PTR_ERR(chan->kthread_start_capture);
 574                chan->kthread_start_capture = NULL;
 575                dev_err(&chan->video.dev,
 576                        "failed to run capture start kthread: %d\n", ret);
 577                goto error_kthread_start;
 578        }
 579
 580        chan->kthread_finish_capture = kthread_run(chan_capture_kthread_finish,
 581                                                   chan, "%s:1",
 582                                                   chan->video.name);
 583        if (IS_ERR(chan->kthread_finish_capture)) {
 584                ret = PTR_ERR(chan->kthread_finish_capture);
 585                chan->kthread_finish_capture = NULL;
 586                dev_err(&chan->video.dev,
 587                        "failed to run capture finish kthread: %d\n", ret);
 588                goto error_kthread_done;
 589        }
 590
 591        return 0;
 592
 593error_kthread_done:
 594        kthread_stop(chan->kthread_start_capture);
 595error_kthread_start:
 596        tegra_channel_set_stream(chan, false);
 597error_set_stream:
 598        media_pipeline_stop(&chan->video.entity);
 599error_pipeline_start:
 600        tegra_channel_release_buffers(chan, VB2_BUF_STATE_QUEUED);
 601        return ret;
 602}
 603
 604static void tegra210_vi_stop_streaming(struct vb2_queue *vq)
 605{
 606        struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
 607
 608        if (chan->kthread_start_capture) {
 609                kthread_stop(chan->kthread_start_capture);
 610                chan->kthread_start_capture = NULL;
 611        }
 612
 613        if (chan->kthread_finish_capture) {
 614                kthread_stop(chan->kthread_finish_capture);
 615                chan->kthread_finish_capture = NULL;
 616        }
 617
 618        tegra_channel_release_buffers(chan, VB2_BUF_STATE_ERROR);
 619        tegra_channel_set_stream(chan, false);
 620        media_pipeline_stop(&chan->video.entity);
 621}
 622
 623/*
 624 * Tegra210 VI Pixel memory format enum.
 625 * These format enum value gets programmed into corresponding Tegra VI
 626 * channel register bits.
 627 */
 628enum tegra210_image_format {
 629        TEGRA210_IMAGE_FORMAT_T_L8 = 16,
 630
 631        TEGRA210_IMAGE_FORMAT_T_R16_I = 32,
 632        TEGRA210_IMAGE_FORMAT_T_B5G6R5,
 633        TEGRA210_IMAGE_FORMAT_T_R5G6B5,
 634        TEGRA210_IMAGE_FORMAT_T_A1B5G5R5,
 635        TEGRA210_IMAGE_FORMAT_T_A1R5G5B5,
 636        TEGRA210_IMAGE_FORMAT_T_B5G5R5A1,
 637        TEGRA210_IMAGE_FORMAT_T_R5G5B5A1,
 638        TEGRA210_IMAGE_FORMAT_T_A4B4G4R4,
 639        TEGRA210_IMAGE_FORMAT_T_A4R4G4B4,
 640        TEGRA210_IMAGE_FORMAT_T_B4G4R4A4,
 641        TEGRA210_IMAGE_FORMAT_T_R4G4B4A4,
 642
 643        TEGRA210_IMAGE_FORMAT_T_A8B8G8R8 = 64,
 644        TEGRA210_IMAGE_FORMAT_T_A8R8G8B8,
 645        TEGRA210_IMAGE_FORMAT_T_B8G8R8A8,
 646        TEGRA210_IMAGE_FORMAT_T_R8G8B8A8,
 647        TEGRA210_IMAGE_FORMAT_T_A2B10G10R10,
 648        TEGRA210_IMAGE_FORMAT_T_A2R10G10B10,
 649        TEGRA210_IMAGE_FORMAT_T_B10G10R10A2,
 650        TEGRA210_IMAGE_FORMAT_T_R10G10B10A2,
 651
 652        TEGRA210_IMAGE_FORMAT_T_A8Y8U8V8 = 193,
 653        TEGRA210_IMAGE_FORMAT_T_V8U8Y8A8,
 654
 655        TEGRA210_IMAGE_FORMAT_T_A2Y10U10V10 = 197,
 656        TEGRA210_IMAGE_FORMAT_T_V10U10Y10A2,
 657        TEGRA210_IMAGE_FORMAT_T_Y8_U8__Y8_V8,
 658        TEGRA210_IMAGE_FORMAT_T_Y8_V8__Y8_U8,
 659        TEGRA210_IMAGE_FORMAT_T_U8_Y8__V8_Y8,
 660        TEGRA210_IMAGE_FORMAT_T_V8_Y8__U8_Y8,
 661
 662        TEGRA210_IMAGE_FORMAT_T_Y8__U8__V8_N444 = 224,
 663        TEGRA210_IMAGE_FORMAT_T_Y8__U8V8_N444,
 664        TEGRA210_IMAGE_FORMAT_T_Y8__V8U8_N444,
 665        TEGRA210_IMAGE_FORMAT_T_Y8__U8__V8_N422,
 666        TEGRA210_IMAGE_FORMAT_T_Y8__U8V8_N422,
 667        TEGRA210_IMAGE_FORMAT_T_Y8__V8U8_N422,
 668        TEGRA210_IMAGE_FORMAT_T_Y8__U8__V8_N420,
 669        TEGRA210_IMAGE_FORMAT_T_Y8__U8V8_N420,
 670        TEGRA210_IMAGE_FORMAT_T_Y8__V8U8_N420,
 671        TEGRA210_IMAGE_FORMAT_T_X2LC10LB10LA10,
 672        TEGRA210_IMAGE_FORMAT_T_A2R6R6R6R6R6,
 673};
 674
 675#define TEGRA210_VIDEO_FMT(DATA_TYPE, BIT_WIDTH, MBUS_CODE, BPP,        \
 676                           FORMAT, FOURCC)                              \
 677{                                                                       \
 678        TEGRA_IMAGE_DT_##DATA_TYPE,                                     \
 679        BIT_WIDTH,                                                      \
 680        MEDIA_BUS_FMT_##MBUS_CODE,                                      \
 681        BPP,                                                            \
 682        TEGRA210_IMAGE_FORMAT_##FORMAT,                                 \
 683        V4L2_PIX_FMT_##FOURCC,                                          \
 684}
 685
 686/* Tegra210 supported video formats */
 687static const struct tegra_video_format tegra210_video_formats[] = {
 688        /* RAW 8 */
 689        TEGRA210_VIDEO_FMT(RAW8, 8, SRGGB8_1X8, 1, T_L8, SRGGB8),
 690        TEGRA210_VIDEO_FMT(RAW8, 8, SGRBG8_1X8, 1, T_L8, SGRBG8),
 691        TEGRA210_VIDEO_FMT(RAW8, 8, SGBRG8_1X8, 1, T_L8, SGBRG8),
 692        TEGRA210_VIDEO_FMT(RAW8, 8, SBGGR8_1X8, 1, T_L8, SBGGR8),
 693        /* RAW 10 */
 694        TEGRA210_VIDEO_FMT(RAW10, 10, SRGGB10_1X10, 2, T_R16_I, SRGGB10),
 695        TEGRA210_VIDEO_FMT(RAW10, 10, SGRBG10_1X10, 2, T_R16_I, SGRBG10),
 696        TEGRA210_VIDEO_FMT(RAW10, 10, SGBRG10_1X10, 2, T_R16_I, SGBRG10),
 697        TEGRA210_VIDEO_FMT(RAW10, 10, SBGGR10_1X10, 2, T_R16_I, SBGGR10),
 698        /* RAW 12 */
 699        TEGRA210_VIDEO_FMT(RAW12, 12, SRGGB12_1X12, 2, T_R16_I, SRGGB12),
 700        TEGRA210_VIDEO_FMT(RAW12, 12, SGRBG12_1X12, 2, T_R16_I, SGRBG12),
 701        TEGRA210_VIDEO_FMT(RAW12, 12, SGBRG12_1X12, 2, T_R16_I, SGBRG12),
 702        TEGRA210_VIDEO_FMT(RAW12, 12, SBGGR12_1X12, 2, T_R16_I, SBGGR12),
 703        /* RGB888 */
 704        TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X24, 4, T_A8R8G8B8, XBGR32),
 705        TEGRA210_VIDEO_FMT(RGB888, 24, RGB888_1X32_PADHI, 4, T_A8B8G8R8,
 706                           RGBX32),
 707        /* YUV422 */
 708        TEGRA210_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 2, T_U8_Y8__V8_Y8, YVYU),
 709        TEGRA210_VIDEO_FMT(YUV422_8, 16, VYUY8_1X16, 2, T_V8_Y8__U8_Y8, YUYV),
 710        TEGRA210_VIDEO_FMT(YUV422_8, 16, YUYV8_1X16, 2, T_Y8_U8__Y8_V8, VYUY),
 711        TEGRA210_VIDEO_FMT(YUV422_8, 16, YVYU8_1X16, 2, T_Y8_V8__Y8_U8, UYVY),
 712        TEGRA210_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 1, T_Y8__V8U8_N422, NV16),
 713        TEGRA210_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 2, T_U8_Y8__V8_Y8, YVYU),
 714        TEGRA210_VIDEO_FMT(YUV422_8, 16, VYUY8_2X8, 2, T_V8_Y8__U8_Y8, YUYV),
 715        TEGRA210_VIDEO_FMT(YUV422_8, 16, YUYV8_2X8, 2, T_Y8_U8__Y8_V8, VYUY),
 716        TEGRA210_VIDEO_FMT(YUV422_8, 16, YVYU8_2X8, 2, T_Y8_V8__Y8_U8, UYVY),
 717};
 718
 719/* Tegra210 VI operations */
 720static const struct tegra_vi_ops tegra210_vi_ops = {
 721        .vi_start_streaming = tegra210_vi_start_streaming,
 722        .vi_stop_streaming = tegra210_vi_stop_streaming,
 723};
 724
 725/* Tegra210 VI SoC data */
 726const struct tegra_vi_soc tegra210_vi_soc = {
 727        .video_formats = tegra210_video_formats,
 728        .nformats = ARRAY_SIZE(tegra210_video_formats),
 729        .ops = &tegra210_vi_ops,
 730        .hw_revision = 3,
 731        .vi_max_channels = 6,
 732#if IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)
 733        .vi_max_clk_hz = 499200000,
 734#else
 735        .vi_max_clk_hz = 998400000,
 736#endif
 737};
 738
 739/* Tegra210 CSI PHY registers accessors */
 740static void csi_write(struct tegra_csi *csi, u8 portno, unsigned int addr,
 741                      u32 val)
 742{
 743        void __iomem *csi_pp_base;
 744
 745        csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
 746
 747        writel_relaxed(val, csi_pp_base + addr);
 748}
 749
 750/* Tegra210 CSI Pixel parser registers accessors */
 751static void pp_write(struct tegra_csi *csi, u8 portno, u32 addr, u32 val)
 752{
 753        void __iomem *csi_pp_base;
 754        unsigned int offset;
 755
 756        csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
 757        offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
 758
 759        writel_relaxed(val, csi_pp_base + offset + addr);
 760}
 761
 762static u32 pp_read(struct tegra_csi *csi, u8 portno, u32 addr)
 763{
 764        void __iomem *csi_pp_base;
 765        unsigned int offset;
 766
 767        csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
 768        offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
 769
 770        return readl_relaxed(csi_pp_base + offset + addr);
 771}
 772
 773/* Tegra210 CSI CIL A/B port registers accessors */
 774static void cil_write(struct tegra_csi *csi, u8 portno, u32 addr, u32 val)
 775{
 776        void __iomem *csi_cil_base;
 777        unsigned int offset;
 778
 779        csi_cil_base = csi->iomem + CSI_PP_OFFSET(portno >> 1) +
 780                       TEGRA210_CSI_CIL_OFFSET;
 781        offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
 782
 783        writel_relaxed(val, csi_cil_base + offset + addr);
 784}
 785
 786static u32 cil_read(struct tegra_csi *csi, u8 portno, u32 addr)
 787{
 788        void __iomem *csi_cil_base;
 789        unsigned int offset;
 790
 791        csi_cil_base = csi->iomem + CSI_PP_OFFSET(portno >> 1) +
 792                       TEGRA210_CSI_CIL_OFFSET;
 793        offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET;
 794
 795        return readl_relaxed(csi_cil_base + offset + addr);
 796}
 797
 798/* Tegra210 CSI Test pattern generator registers accessor */
 799static void tpg_write(struct tegra_csi *csi, u8 portno, unsigned int addr,
 800                      u32 val)
 801{
 802        void __iomem *csi_pp_base;
 803        unsigned int offset;
 804
 805        csi_pp_base = csi->iomem + CSI_PP_OFFSET(portno >> 1);
 806        offset = (portno % CSI_PORTS_PER_BRICK) * TEGRA210_CSI_PORT_OFFSET +
 807                 TEGRA210_CSI_TPG_OFFSET;
 808
 809        writel_relaxed(val, csi_pp_base + offset + addr);
 810}
 811
 812/*
 813 * Tegra210 CSI operations
 814 */
 815static void tegra210_csi_port_recover(struct tegra_csi_channel *csi_chan,
 816                                      u8 portno)
 817{
 818        struct tegra_csi *csi = csi_chan->csi;
 819        u32 val;
 820
 821        /*
 822         * Recover CSI hardware in case of capture errors by issuing
 823         * software reset to CSICIL sensor, pixel parser, and clear errors
 824         * to have clean capture on  next streaming.
 825         */
 826        val = pp_read(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS);
 827        dev_dbg(csi->dev, "TEGRA_CSI_PIXEL_PARSER_STATUS 0x%08x\n", val);
 828
 829        val = cil_read(csi, portno, TEGRA_CSI_CIL_STATUS);
 830        dev_dbg(csi->dev, "TEGRA_CSI_CIL_STATUS 0x%08x\n", val);
 831
 832        val = cil_read(csi, portno, TEGRA_CSI_CILX_STATUS);
 833        dev_dbg(csi->dev, "TEGRA_CSI_CILX_STATUS 0x%08x\n", val);
 834
 835        if (csi_chan->numlanes == 4) {
 836                /* reset CSI CIL sensor */
 837                cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
 838                cil_write(csi, portno + 1, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
 839                /*
 840                 * SW_STATUS_RESET resets all status bits of PPA, PPB, CILA,
 841                 * CILB status registers and debug counters.
 842                 * So, SW_STATUS_RESET can be used only when CSI brick is in
 843                 * x4 mode.
 844                 */
 845                csi_write(csi, portno, TEGRA_CSI_CSI_SW_STATUS_RESET, 0x1);
 846
 847                /* sleep for 20 clock cycles to drain the FIFO */
 848                usleep_range(10, 20);
 849
 850                cil_write(csi, portno + 1, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
 851                cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
 852                csi_write(csi, portno, TEGRA_CSI_CSI_SW_STATUS_RESET, 0x0);
 853        } else {
 854                /* reset CSICIL sensor */
 855                cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
 856                usleep_range(10, 20);
 857                cil_write(csi, portno, TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
 858
 859                /* clear the errors */
 860                pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS,
 861                         0xffffffff);
 862                cil_write(csi, portno, TEGRA_CSI_CIL_STATUS, 0xffffffff);
 863                cil_write(csi, portno, TEGRA_CSI_CILX_STATUS, 0xffffffff);
 864        }
 865}
 866
 867static void tegra210_csi_error_recover(struct tegra_csi_channel *csi_chan)
 868{
 869        u8 *portnos = csi_chan->csi_port_nums;
 870        int i;
 871
 872        for (i = 0; i < csi_chan->numgangports; i++)
 873                tegra210_csi_port_recover(csi_chan, portnos[i]);
 874}
 875
 876static int
 877tegra210_csi_port_start_streaming(struct tegra_csi_channel *csi_chan,
 878                                  u8 portno)
 879{
 880        struct tegra_csi *csi = csi_chan->csi;
 881        u8 clk_settle_time = 0;
 882        u8 ths_settle_time = 10;
 883        u32 val;
 884
 885        if (!csi_chan->pg_mode)
 886                tegra_csi_calc_settle_time(csi_chan, portno, &clk_settle_time,
 887                                           &ths_settle_time);
 888
 889        csi_write(csi, portno, TEGRA_CSI_CLKEN_OVERRIDE, 0);
 890
 891        /* clean up status */
 892        pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS, 0xffffffff);
 893        cil_write(csi, portno, TEGRA_CSI_CIL_STATUS, 0xffffffff);
 894        cil_write(csi, portno, TEGRA_CSI_CILX_STATUS, 0xffffffff);
 895        cil_write(csi, portno, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
 896
 897        /* CIL PHY registers setup */
 898        cil_write(csi, portno, TEGRA_CSI_CIL_PAD_CONFIG0, 0x0);
 899        cil_write(csi, portno, TEGRA_CSI_CIL_PHY_CONTROL,
 900                  FIELD_PREP(CLK_SETTLE_MASK, clk_settle_time) |
 901                  FIELD_PREP(THS_SETTLE_MASK, ths_settle_time));
 902
 903        /*
 904         * The CSI unit provides for connection of up to six cameras in
 905         * the system and is organized as three identical instances of
 906         * two MIPI support blocks, each with a separate 4-lane
 907         * interface that can be configured as a single camera with 4
 908         * lanes or as a dual camera with 2 lanes available for each
 909         * camera.
 910         */
 911        if (csi_chan->numlanes == 4) {
 912                cil_write(csi, portno + 1, TEGRA_CSI_CIL_STATUS, 0xffffffff);
 913                cil_write(csi, portno + 1, TEGRA_CSI_CILX_STATUS, 0xffffffff);
 914                cil_write(csi, portno + 1, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
 915
 916                cil_write(csi, portno, TEGRA_CSI_CIL_PAD_CONFIG0,
 917                          BRICK_CLOCK_A_4X);
 918                cil_write(csi, portno + 1, TEGRA_CSI_CIL_PAD_CONFIG0, 0x0);
 919                cil_write(csi, portno + 1, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
 920                cil_write(csi, portno + 1, TEGRA_CSI_CIL_PHY_CONTROL,
 921                          FIELD_PREP(CLK_SETTLE_MASK, clk_settle_time) |
 922                          FIELD_PREP(THS_SETTLE_MASK, ths_settle_time));
 923                csi_write(csi, portno, TEGRA_CSI_PHY_CIL_COMMAND,
 924                          CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_ENABLE);
 925        } else {
 926                val = ((portno & 1) == PORT_A) ?
 927                      CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_NOP :
 928                      CSI_B_PHY_CIL_ENABLE | CSI_A_PHY_CIL_NOP;
 929                csi_write(csi, portno, TEGRA_CSI_PHY_CIL_COMMAND, val);
 930        }
 931
 932        /* CSI pixel parser registers setup */
 933        pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
 934                 (0xf << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
 935                 CSI_PP_SINGLE_SHOT_ENABLE | CSI_PP_RST);
 936        pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0);
 937        pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_CONTROL0,
 938                 CSI_PP_PACKET_HEADER_SENT |
 939                 CSI_PP_DATA_IDENTIFIER_ENABLE |
 940                 CSI_PP_WORD_COUNT_SELECT_HEADER |
 941                 CSI_PP_CRC_CHECK_ENABLE |  CSI_PP_WC_CHECK |
 942                 CSI_PP_OUTPUT_FORMAT_STORE | CSI_PPA_PAD_LINE_NOPAD |
 943                 CSI_PP_HEADER_EC_DISABLE | CSI_PPA_PAD_FRAME_NOPAD |
 944                 (portno & 1));
 945        pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_CONTROL1,
 946                 (0x1 << CSI_PP_TOP_FIELD_FRAME_OFFSET) |
 947                 (0x1 << CSI_PP_TOP_FIELD_FRAME_MASK_OFFSET));
 948        pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_GAP,
 949                 0x14 << PP_FRAME_MIN_GAP_OFFSET);
 950        pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME, 0x0);
 951        pp_write(csi, portno, TEGRA_CSI_INPUT_STREAM_CONTROL,
 952                 (0x3f << CSI_SKIP_PACKET_THRESHOLD_OFFSET) |
 953                 (csi_chan->numlanes - 1));
 954
 955        /* TPG setup */
 956        if (csi_chan->pg_mode) {
 957                tpg_write(csi, portno, TEGRA_CSI_PATTERN_GENERATOR_CTRL,
 958                          ((csi_chan->pg_mode - 1) << PG_MODE_OFFSET) |
 959                          PG_ENABLE);
 960                tpg_write(csi, portno, TEGRA_CSI_PG_BLANK,
 961                          csi_chan->v_blank << PG_VBLANK_OFFSET |
 962                          csi_chan->h_blank);
 963                tpg_write(csi, portno, TEGRA_CSI_PG_PHASE, 0x0);
 964                tpg_write(csi, portno, TEGRA_CSI_PG_RED_FREQ,
 965                          (0x10 << PG_RED_VERT_INIT_FREQ_OFFSET) |
 966                          (0x10 << PG_RED_HOR_INIT_FREQ_OFFSET));
 967                tpg_write(csi, portno, TEGRA_CSI_PG_RED_FREQ_RATE, 0x0);
 968                tpg_write(csi, portno, TEGRA_CSI_PG_GREEN_FREQ,
 969                          (0x10 << PG_GREEN_VERT_INIT_FREQ_OFFSET) |
 970                          (0x10 << PG_GREEN_HOR_INIT_FREQ_OFFSET));
 971                tpg_write(csi, portno, TEGRA_CSI_PG_GREEN_FREQ_RATE, 0x0);
 972                tpg_write(csi, portno, TEGRA_CSI_PG_BLUE_FREQ,
 973                          (0x10 << PG_BLUE_VERT_INIT_FREQ_OFFSET) |
 974                          (0x10 << PG_BLUE_HOR_INIT_FREQ_OFFSET));
 975                tpg_write(csi, portno, TEGRA_CSI_PG_BLUE_FREQ_RATE, 0x0);
 976        }
 977
 978        pp_write(csi, portno, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
 979                 (0xf << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
 980                 CSI_PP_SINGLE_SHOT_ENABLE | CSI_PP_ENABLE);
 981
 982        return 0;
 983}
 984
 985static void
 986tegra210_csi_port_stop_streaming(struct tegra_csi_channel *csi_chan, u8 portno)
 987{
 988        struct tegra_csi *csi = csi_chan->csi;
 989        u32 val;
 990
 991        val = pp_read(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS);
 992
 993        dev_dbg(csi->dev, "TEGRA_CSI_PIXEL_PARSER_STATUS 0x%08x\n", val);
 994        pp_write(csi, portno, TEGRA_CSI_PIXEL_PARSER_STATUS, val);
 995
 996        val = cil_read(csi, portno, TEGRA_CSI_CIL_STATUS);
 997        dev_dbg(csi->dev, "TEGRA_CSI_CIL_STATUS 0x%08x\n", val);
 998        cil_write(csi, portno, TEGRA_CSI_CIL_STATUS, val);
 999
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
1026static 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
1039stream_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
1046static 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 */
1061static 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
1106static 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 */
1117static 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 */
1124const 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};
1132