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