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