0001
0002
0003
0004
0005
0006
0007
0008
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
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
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
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
0086
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
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
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
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
0187
0188
0189
0190
0191
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
0199
0200
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
0223 tegra_vi_write(chan, TEGRA_VI_CFG_CG_CTRL, 0);
0224
0225
0226
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
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
0244
0245
0246
0247
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
0259 tegra_channel_vi_soft_reset(chan, portno);
0260 tegra_channel_capture_setup(chan, portno);
0261
0262
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
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
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
0339
0340
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
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361 thresh = host1x_syncpt_incr_max(chan->frame_start_sp[i], 1);
0362 fs_thresh[i] = thresh;
0363
0364
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
0371 thresh = host1x_syncpt_incr_max(chan->mw_ack_sp[i], 1);
0372 buf->mw_ack_sp_thresh[i] = thresh;
0373
0374
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
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
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
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
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
0412 spin_lock(&chan->done_lock);
0413 list_add_tail(&buf->queue, &chan->done);
0414 spin_unlock(&chan->done_lock);
0415
0416
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
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
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
0463
0464
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
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
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
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
0541
0542
0543
0544
0545
0546 tegra_vi_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL,
0547 VI_INCR_SYNCPT_NO_STALL);
0548
0549
0550 ret = media_pipeline_start(&chan->video.entity, pipe);
0551 if (ret < 0)
0552 goto error_pipeline_start;
0553
0554
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
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
0625
0626
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
0687 static const struct tegra_video_format tegra210_video_formats[] = {
0688
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
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
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
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
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
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
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
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
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
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
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
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
0823
0824
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
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
0841
0842
0843
0844
0845 csi_write(csi, portno, TEGRA_CSI_CSI_SW_STATUS_RESET, 0x1);
0846
0847
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
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
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
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
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
0905
0906
0907
0908
0909
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
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
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
1057
1058
1059
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
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
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 };