2 * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include <linux/delay.h>
18 #include <linux/clk.h>
19 #include <linux/platform_device.h>
21 #include <media/soc_camera.h>
22 #include <media/soc_mediabus.h>
23 #include <media/tegra_v4l2_camera.h>
27 #include "nvhost_syncpt.h"
30 #define TEGRA_SYNCPT_CSI_WAIT_TIMEOUT 200
32 #define TEGRA_VI_CFG_VI_INCR_SYNCPT 0x000
33 #define TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL 0x004
34 #define TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR 0x008
35 #define TEGRA_VI_CFG_CTXSW 0x020
36 #define TEGRA_VI_CFG_INTSTATUS 0x024
37 #define TEGRA_VI_CFG_PWM_CONTROL 0x038
38 #define TEGRA_VI_CFG_PWM_HIGH_PULSE 0x03c
39 #define TEGRA_VI_CFG_PWM_LOW_PULSE 0x040
40 #define TEGRA_VI_CFG_PWM_SELECT_PULSE_A 0x044
41 #define TEGRA_VI_CFG_PWM_SELECT_PULSE_B 0x048
42 #define TEGRA_VI_CFG_PWM_SELECT_PULSE_C 0x04c
43 #define TEGRA_VI_CFG_PWM_SELECT_PULSE_D 0x050
44 #define TEGRA_VI_CFG_VGP1 0x064
45 #define TEGRA_VI_CFG_VGP2 0x068
46 #define TEGRA_VI_CFG_VGP3 0x06c
47 #define TEGRA_VI_CFG_VGP4 0x070
48 #define TEGRA_VI_CFG_VGP5 0x074
49 #define TEGRA_VI_CFG_VGP6 0x078
50 #define TEGRA_VI_CFG_INTERRUPT_MASK 0x08c
51 #define TEGRA_VI_CFG_INTERRUPT_TYPE_SELECT 0x090
52 #define TEGRA_VI_CFG_INTERRUPT_POLARITY_SELECT 0x094
53 #define TEGRA_VI_CFG_INTERRUPT_STATUS 0x098
54 #define TEGRA_VI_CFG_VGP_SYNCPT_CONFIG 0x0ac
55 #define TEGRA_VI_CFG_VI_SW_RESET 0x0b4
56 #define TEGRA_VI_CFG_CG_CTRL 0x0b8
57 #define TEGRA_VI_CFG_VI_MCCIF_FIFOCTRL 0x0e4
58 #define TEGRA_VI_CFG_TIMEOUT_WCOAL_VI 0x0e8
59 #define TEGRA_VI_CFG_DVFS 0x0f0
60 #define TEGRA_VI_CFG_RESERVE 0x0f4
61 #define TEGRA_VI_CFG_RESERVE_1 0x0f8
63 #define TEGRA_VI_CSI_0_SW_RESET 0x100
64 #define TEGRA_VI_CSI_0_SINGLE_SHOT 0x104
65 #define TEGRA_VI_CSI_0_SINGLE_SHOT_STATE_UPDATE 0x108
66 #define TEGRA_VI_CSI_0_IMAGE_DEF 0x10c
67 #define TEGRA_VI_CSI_0_RGB2Y_CTRL 0x110
68 #define TEGRA_VI_CSI_0_MEM_TILING 0x114
69 #define TEGRA_VI_CSI_0_CSI_IMAGE_SIZE 0x118
70 #define TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC 0x11c
71 #define TEGRA_VI_CSI_0_CSI_IMAGE_DT 0x120
72 #define TEGRA_VI_CSI_0_SURFACE0_OFFSET_MSB 0x124
73 #define TEGRA_VI_CSI_0_SURFACE0_OFFSET_LSB 0x128
74 #define TEGRA_VI_CSI_0_SURFACE1_OFFSET_MSB 0x12c
75 #define TEGRA_VI_CSI_0_SURFACE1_OFFSET_LSB 0x130
76 #define TEGRA_VI_CSI_0_SURFACE2_OFFSET_MSB 0x134
77 #define TEGRA_VI_CSI_0_SURFACE2_OFFSET_LSB 0x138
78 #define TEGRA_VI_CSI_0_SURFACE0_BF_OFFSET_MSB 0x13c
79 #define TEGRA_VI_CSI_0_SURFACE0_BF_OFFSET_LSB 0x140
80 #define TEGRA_VI_CSI_0_SURFACE1_BF_OFFSET_MSB 0x144
81 #define TEGRA_VI_CSI_0_SURFACE1_BF_OFFSET_LSB 0x148
82 #define TEGRA_VI_CSI_0_SURFACE2_BF_OFFSET_MSB 0x14c
83 #define TEGRA_VI_CSI_0_SURFACE2_BF_OFFSET_LSB 0x150
84 #define TEGRA_VI_CSI_0_SURFACE0_STRIDE 0x154
85 #define TEGRA_VI_CSI_0_SURFACE1_STRIDE 0x158
86 #define TEGRA_VI_CSI_0_SURFACE2_STRIDE 0x15c
87 #define TEGRA_VI_CSI_0_SURFACE_HEIGHT0 0x160
88 #define TEGRA_VI_CSI_0_ISPINTF_CONFIG 0x164
89 #define TEGRA_VI_CSI_0_ERROR_STATUS 0x184
90 #define TEGRA_VI_CSI_0_ERROR_INT_MASK 0x188
91 #define TEGRA_VI_CSI_0_WD_CTRL 0x18c
92 #define TEGRA_VI_CSI_0_WD_PERIOD 0x190
94 #define TEGRA_VI_CSI_1_SW_RESET 0x200
95 #define TEGRA_VI_CSI_1_SINGLE_SHOT 0x204
96 #define TEGRA_VI_CSI_1_SINGLE_SHOT_STATE_UPDATE 0x208
97 #define TEGRA_VI_CSI_1_IMAGE_DEF 0x20c
98 #define TEGRA_VI_CSI_1_RGB2Y_CTRL 0x210
99 #define TEGRA_VI_CSI_1_MEM_TILING 0x214
100 #define TEGRA_VI_CSI_1_CSI_IMAGE_SIZE 0x218
101 #define TEGRA_VI_CSI_1_CSI_IMAGE_SIZE_WC 0x21c
102 #define TEGRA_VI_CSI_1_CSI_IMAGE_DT 0x220
103 #define TEGRA_VI_CSI_1_SURFACE0_OFFSET_MSB 0x224
104 #define TEGRA_VI_CSI_1_SURFACE0_OFFSET_LSB 0x228
105 #define TEGRA_VI_CSI_1_SURFACE1_OFFSET_MSB 0x22c
106 #define TEGRA_VI_CSI_1_SURFACE1_OFFSET_LSB 0x230
107 #define TEGRA_VI_CSI_1_SURFACE2_OFFSET_MSB 0x234
108 #define TEGRA_VI_CSI_1_SURFACE2_OFFSET_LSB 0x238
109 #define TEGRA_VI_CSI_1_SURFACE0_BF_OFFSET_MSB 0x23c
110 #define TEGRA_VI_CSI_1_SURFACE0_BF_OFFSET_LSB 0x240
111 #define TEGRA_VI_CSI_1_SURFACE1_BF_OFFSET_MSB 0x244
112 #define TEGRA_VI_CSI_1_SURFACE1_BF_OFFSET_LSB 0x248
113 #define TEGRA_VI_CSI_1_SURFACE2_BF_OFFSET_MSB 0x24c
114 #define TEGRA_VI_CSI_1_SURFACE2_BF_OFFSET_LSB 0x250
115 #define TEGRA_VI_CSI_1_SURFACE0_STRIDE 0x254
116 #define TEGRA_VI_CSI_1_SURFACE1_STRIDE 0x258
117 #define TEGRA_VI_CSI_1_SURFACE2_STRIDE 0x25c
118 #define TEGRA_VI_CSI_1_SURFACE_HEIGHT0 0x260
119 #define TEGRA_VI_CSI_1_ISPINTF_CONFIG 0x264
120 #define TEGRA_VI_CSI_1_ERROR_STATUS 0x284
121 #define TEGRA_VI_CSI_1_ERROR_INT_MASK 0x288
122 #define TEGRA_VI_CSI_1_WD_CTRL 0x28c
123 #define TEGRA_VI_CSI_1_WD_PERIOD 0x290
125 #define TEGRA_CSI_CSI_CAP_CIL 0x808
126 #define TEGRA_CSI_CSI_CAP_CSI 0x818
127 #define TEGRA_CSI_CSI_CAP_PP 0x828
128 #define TEGRA_CSI_INPUT_STREAM_A_CONTROL 0x838
129 #define TEGRA_CSI_PIXEL_STREAM_A_CONTROL0 0x83c
130 #define TEGRA_CSI_PIXEL_STREAM_A_CONTROL1 0x840
131 #define TEGRA_CSI_PIXEL_STREAM_A_GAP 0x844
132 #define TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND 0x848
133 #define TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME 0x84c
134 #define TEGRA_CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK 0x850
135 #define TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS 0x854
136 #define TEGRA_CSI_CSI_SW_SENSOR_A_RESET 0x858
137 #define TEGRA_CSI_INPUT_STREAM_B_CONTROL 0x86c
138 #define TEGRA_CSI_PIXEL_STREAM_B_CONTROL0 0x870
139 #define TEGRA_CSI_PIXEL_STREAM_B_CONTROL1 0x874
140 #define TEGRA_CSI_PIXEL_STREAM_B_GAP 0x878
141 #define TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND 0x87c
142 #define TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME 0x880
143 #define TEGRA_CSI_CSI_PIXEL_PARSER_B_INTERRUPT_MASK 0x884
144 #define TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS 0x888
145 #define TEGRA_CSI_CSI_SW_SENSOR_B_RESET 0x88c
146 #define TEGRA_CSI_PHY_CIL_COMMAND 0x908
147 #define TEGRA_CSI_CIL_PAD_CONFIG0 0x90c
149 #define TEGRA_CSI_CILA_PAD_CONFIG0 0x92c
150 #define TEGRA_CSI_CILA_PAD_CONFIG1 0x930
151 #define TEGRA_CSI_PHY_CILA_CONTROL0 0x934
152 #define TEGRA_CSI_CSI_CIL_A_INTERRUPT_MASK 0x938
153 #define TEGRA_CSI_CSI_CIL_A_STATUS 0x93c
154 #define TEGRA_CSI_CSI_CILA_STATUS 0x940
155 #define TEGRA_CSI_CIL_A_ESCAPE_MODE_COMMAND 0x944
156 #define TEGRA_CSI_CIL_A_ESCAPE_MODE_DATA 0x948
157 #define TEGRA_CSI_CSICIL_SW_SENSOR_A_RESET 0x94c
159 #define TEGRA_CSI_CILB_PAD_CONFIG0 0x960
160 #define TEGRA_CSI_CILB_PAD_CONFIG1 0x964
161 #define TEGRA_CSI_PHY_CILB_CONTROL0 0x968
162 #define TEGRA_CSI_CSI_CIL_B_INTERRUPT_MASK 0x96c
163 #define TEGRA_CSI_CSI_CIL_B_STATUS 0x970
164 #define TEGRA_CSI_CSI_CILB_STATUS 0x974
165 #define TEGRA_CSI_CIL_B_ESCAPE_MODE_COMMAND 0x978
166 #define TEGRA_CSI_CIL_B_ESCAPE_MODE_DATA 0x97c
167 #define TEGRA_CSI_CSICIL_SW_SENSOR_B_RESET 0x980
169 #define TEGRA_CSI_CILC_PAD_CONFIG0 0x994
170 #define TEGRA_CSI_CILC_PAD_CONFIG1 0x998
171 #define TEGRA_CSI_PHY_CILC_CONTROL0 0x99c
172 #define TEGRA_CSI_CSI_CIL_C_INTERRUPT_MASK 0x9a0
173 #define TEGRA_CSI_CSI_CIL_C_STATUS 0x9a4
174 #define TEGRA_CSI_CSI_CILC_STATUS 0x9a8
175 #define TEGRA_CSI_CIL_C_ESCAPE_MODE_COMMAND 0x9ac
176 #define TEGRA_CSI_CIL_C_ESCAPE_MODE_DATA 0x9b0
177 #define TEGRA_CSI_CSICIL_SW_SENSOR_C_RESET 0x9b4
179 #define TEGRA_CSI_CILD_PAD_CONFIG0 0x9c8
180 #define TEGRA_CSI_CILD_PAD_CONFIG1 0x9cc
181 #define TEGRA_CSI_PHY_CILD_CONTROL0 0x9d0
182 #define TEGRA_CSI_CSI_CIL_D_INTERRUPT_MASK 0x9d4
183 #define TEGRA_CSI_CSI_CIL_D_STATUS 0x9d8
184 #define TEGRA_CSI_CSI_CILD_STATUS 0x9dc
185 #define TEGRA_CSI_CIL_D_ESCAPE_MODE_COMMAND 0x9ec
186 #define TEGRA_CSI_CIL_D_ESCAPE_MODE_DATA 0x9f0
187 #define TEGRA_CSI_CSICIL_SW_SENSOR_D_RESET 0x9f4
189 #define TEGRA_CSI_CILE_PAD_CONFIG0 0xa08
190 #define TEGRA_CSI_CILE_PAD_CONFIG1 0xa0c
191 #define TEGRA_CSI_PHY_CILE_CONTROL0 0xa10
192 #define TEGRA_CSI_CSI_CIL_E_INTERRUPT_MASK 0xa14
193 #define TEGRA_CSI_CSI_CIL_E_STATUS 0xa18
194 #define TEGRA_CSI_CIL_E_ESCAPE_MODE_COMMAND 0xa1c
195 #define TEGRA_CSI_CIL_E_ESCAPE_MODE_DATA 0xa20
196 #define TEGRA_CSI_CSICIL_SW_SENSOR_E_RESET 0xa24
198 #define TEGRA_CSI_PATTERN_GENERATOR_CTRL_A 0xa68
199 #define TEGRA_CSI_PG_BLANK_A 0xa6c
200 #define TEGRA_CSI_PG_PHASE_A 0xa70
201 #define TEGRA_CSI_PG_RED_FREQ_A 0xa74
202 #define TEGRA_CSI_PG_RED_FREQ_RATE_A 0xa78
203 #define TEGRA_CSI_PG_GREEN_FREQ_A 0xa7c
204 #define TEGRA_CSI_PG_GREEN_FREQ_RATE_A 0xa80
205 #define TEGRA_CSI_PG_BLUE_FREQ_A 0xa84
206 #define TEGRA_CSI_PG_BLUE_FREQ_RATE_A 0xa88
208 #define TEGRA_CSI_PATTERN_GENERATOR_CTRL_B 0xa9c
209 #define TEGRA_CSI_PG_BLANK_B 0xaa0
210 #define TEGRA_CSI_PG_PHASE_B 0xaa4
211 #define TEGRA_CSI_PG_RED_FREQ_B 0xaa8
212 #define TEGRA_CSI_PG_RED_FREQ_RATE_B 0xaac
213 #define TEGRA_CSI_PG_GREEN_FREQ_B 0xab0
214 #define TEGRA_CSI_PG_GREEN_FREQ_RATE_B 0xab4
215 #define TEGRA_CSI_PG_BLUE_FREQ_B 0xab8
216 #define TEGRA_CSI_PG_BLUE_FREQ_RATE_B 0xabc
218 #define TEGRA_CSI_DPCM_CTRL_A 0xad0
219 #define TEGRA_CSI_DPCM_CTRL_B 0xad4
220 #define TEGRA_CSI_STALL_COUNTER 0xae8
221 #define TEGRA_CSI_CSI_READONLY_STATUS 0xaec
222 #define TEGRA_CSI_CSI_SW_STATUS_RESET 0xaf0
223 #define TEGRA_CSI_CLKEN_OVERRIDE 0xaf4
224 #define TEGRA_CSI_DEBUG_CONTROL 0xaf8
225 #define TEGRA_CSI_DEBUG_COUNTER_0 0xafc
226 #define TEGRA_CSI_DEBUG_COUNTER_1 0xb00
227 #define TEGRA_CSI_DEBUG_COUNTER_2 0xb04
229 static int vi2_port_is_valid(int port)
231 return (((port) >= TEGRA_CAMERA_PORT_CSI_A) &&
232 ((port) <= TEGRA_CAMERA_PORT_CSI_E));
235 /* Clock settings for camera */
236 static struct tegra_camera_clk vi2_clks0[] = {
273 /* Always put "p11_d" at the end */
280 static struct tegra_camera_clk vi2_clks1[] = {
317 /* Always put "p11_d" at the end */
324 #define MAX_DEVID_LENGTH 16
326 static int vi2_clks_init(struct tegra_camera_dev *cam)
328 struct platform_device *pdev = cam->ndev;
329 struct tegra_camera_clk *clks;
334 cam->num_clks = ARRAY_SIZE(vi2_clks0);
335 cam->clks = vi2_clks0;
338 cam->num_clks = ARRAY_SIZE(vi2_clks1);
339 cam->clks = vi2_clks1;
342 dev_err(&pdev->dev, "Wrong device ID %d\n", pdev->id);
346 for (i = 0; i < cam->num_clks; i++) {
347 clks = &cam->clks[i];
349 if (clks->use_devname) {
350 char devname[MAX_DEVID_LENGTH];
351 snprintf(devname, MAX_DEVID_LENGTH,
352 "tegra_%s", dev_name(&pdev->dev));
353 clks->clk = clk_get_sys(devname, clks->name);
355 clks->clk = clk_get(&pdev->dev, clks->name);
356 if (IS_ERR_OR_NULL(clks->clk)) {
357 dev_err(&pdev->dev, "Failed to get clock %s.\n",
359 return PTR_ERR(clks->clk);
366 static void vi2_clks_deinit(struct tegra_camera_dev *cam)
368 struct tegra_camera_clk *clks;
371 for (i = 0; i < cam->num_clks; i++) {
372 clks = &cam->clks[i];
378 static void vi2_clks_enable(struct tegra_camera_dev *cam)
380 struct tegra_camera_clk *clks;
383 for (i = 0; i < cam->num_clks - 1; i++) {
384 clks = &cam->clks[i];
386 clk_prepare_enable(clks->clk);
388 clk_set_rate(clks->clk, clks->freq);
392 clks = &cam->clks[i];
394 clk_prepare_enable(clks->clk);
396 clk_set_rate(clks->clk, clks->freq);
397 tegra_clk_cfg_ex(clks->clk,
398 TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
399 tegra_clk_cfg_ex(clks->clk,
400 TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
401 tegra_clk_cfg_ex(clks->clk,
402 TEGRA_CLK_MIPI_CSI_OUT_ENB, 0);
407 static void vi2_clks_disable(struct tegra_camera_dev *cam)
409 struct tegra_camera_clk *clks;
412 for (i = 0; i < cam->num_clks - 1; i++) {
413 clks = &cam->clks[i];
415 clk_disable_unprepare(clks->clk);
419 clks = &cam->clks[i];
421 tegra_clk_cfg_ex(clks->clk,
422 TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
423 tegra_clk_cfg_ex(clks->clk,
424 TEGRA_CLK_PLLD_CSI_OUT_ENB, 0);
425 tegra_clk_cfg_ex(clks->clk,
426 TEGRA_CLK_PLLD_DSI_OUT_ENB, 0);
427 clk_disable_unprepare(clks->clk);
432 static void vi2_init_syncpts(struct tegra_camera_dev *cam)
434 cam->syncpt_id_csi_a = nvhost_get_syncpt_client_managed("vi_csi_A");
436 cam->syncpt_id_csi_b = nvhost_get_syncpt_client_managed("vi_csi_B");
439 static void vi2_free_syncpts(struct tegra_camera_dev *cam)
441 nvhost_free_syncpt(cam->syncpt_id_csi_a);
443 nvhost_free_syncpt(cam->syncpt_id_csi_b);
446 static void vi2_incr_syncpts(struct tegra_camera_dev *cam)
450 if (!nvhost_syncpt_read_ext_check(cam->ndev,
451 cam->syncpt_id_csi_a, &val))
452 cam->syncpt_csi_a = nvhost_syncpt_incr_max_ext(cam->ndev,
453 cam->syncpt_id_csi_a, 1);
455 if (!nvhost_syncpt_read_ext_check(cam->ndev,
456 cam->syncpt_id_csi_b, &val))
457 cam->syncpt_csi_b = nvhost_syncpt_incr_max_ext(cam->ndev,
458 cam->syncpt_id_csi_b, 1);
461 static void vi2_capture_clean(struct tegra_camera_dev *cam)
463 /* Clean up status */
464 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_A_STATUS, 0xFFFFFFFF);
465 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_B_STATUS, 0xFFFFFFFF);
466 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_C_STATUS, 0xFFFFFFFF);
467 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_D_STATUS, 0xFFFFFFFF);
468 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_E_STATUS, 0xFFFFFFFF);
469 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILA_STATUS, 0xFFFFFFFF);
470 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILB_STATUS, 0xFFFFFFFF);
471 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILC_STATUS, 0xFFFFFFFF);
472 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CILD_STATUS, 0xFFFFFFFF);
473 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS, 0xFFFFFFFF);
474 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS, 0xFFFFFFFF);
475 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_ERROR_STATUS, 0xFFFFFFFF);
476 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_ERROR_STATUS, 0xFFFFFFFF);
479 static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
480 struct soc_camera_device *icd)
482 struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
483 struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
485 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0xf007);
486 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK, 0x0);
487 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, 0x280301f0);
488 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0xf007);
489 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1, 0x11);
490 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x140000);
492 TC_VI_REG_WT(cam, TEGRA_CSI_INPUT_STREAM_A_CONTROL,
493 0x3f0000 | (pdata->lanes - 1));
494 if (pdata->lanes == 4)
495 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020101);
497 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020201);
500 TC_VI_REG_WT(cam, TEGRA_CSI_PATTERN_GENERATOR_CTRL_A,
501 ((cam->tpg_mode - 1) << 2) | 0x1);
502 TC_VI_REG_WT(cam, TEGRA_CSI_PG_PHASE_A, 0x0);
503 TC_VI_REG_WT(cam, TEGRA_CSI_PG_RED_FREQ_A, 0x100010);
504 TC_VI_REG_WT(cam, TEGRA_CSI_PG_RED_FREQ_RATE_A, 0x0);
505 TC_VI_REG_WT(cam, TEGRA_CSI_PG_GREEN_FREQ_A, 0x100010);
506 TC_VI_REG_WT(cam, TEGRA_CSI_PG_GREEN_FREQ_RATE_A, 0x0);
507 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLUE_FREQ_A, 0x100010);
508 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLUE_FREQ_RATE_A, 0x0);
509 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020202);
511 /* output format A8B8G8R8, only support direct to mem */
512 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_IMAGE_DEF, (64 << 16) | 0x1);
513 /* input format is RGB888 */
514 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_DT, 36);
516 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
517 icd->user_width * 3);
519 /* output format RAW10 T_R16_I, only support direct to mem */
520 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_IMAGE_DEF, (32 << 16) | 0x1);
521 /* input format is RAW10 */
522 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_DT, 43);
524 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
525 icd->user_width * 10 / 8);
528 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE,
529 (icd->user_height << 16) | icd->user_width);
534 static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
535 struct soc_camera_device *icd)
537 struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
538 struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
540 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0xf007);
541 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_INTERRUPT_MASK, 0x0);
542 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x280301f0);
543 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0xf007);
544 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x11);
545 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x140000);
547 TC_VI_REG_WT(cam, TEGRA_CSI_INPUT_STREAM_B_CONTROL,
548 0x3f0000 | (pdata->lanes - 1));
549 if (pdata->lanes == 4)
550 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x21010202);
551 else if (pdata->lanes == 1 && pdata->port == TEGRA_CAMERA_PORT_CSI_E)
552 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x12020202);
554 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22010202);
557 TC_VI_REG_WT(cam, TEGRA_CSI_PATTERN_GENERATOR_CTRL_B,
558 ((cam->tpg_mode - 1) << 2) | 0x1);
559 TC_VI_REG_WT(cam, TEGRA_CSI_PG_PHASE_B, 0x0);
560 TC_VI_REG_WT(cam, TEGRA_CSI_PG_RED_FREQ_B, 0x100010);
561 TC_VI_REG_WT(cam, TEGRA_CSI_PG_RED_FREQ_RATE_B, 0x0);
562 TC_VI_REG_WT(cam, TEGRA_CSI_PG_GREEN_FREQ_B, 0x100010);
563 TC_VI_REG_WT(cam, TEGRA_CSI_PG_GREEN_FREQ_RATE_B, 0x0);
564 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLUE_FREQ_B, 0x100010);
565 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLUE_FREQ_RATE_B, 0x0);
566 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020202);
568 /* output format A8B8G8R8, only support direct to mem */
569 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_IMAGE_DEF, (64 << 16) | 0x1);
570 /* input format is RGB888 */
571 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_DT, 36);
574 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE,
575 (icd->user_height << 16) | icd->user_width);
577 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE_WC,
578 icd->user_width * 3);
583 static int vi2_capture_setup(struct tegra_camera_dev *cam)
585 struct vb2_buffer *vb = cam->active;
586 struct tegra_camera_buffer *buf = to_tegra_vb(vb);
587 struct soc_camera_device *icd = buf->icd;
588 struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
589 struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
590 int port = pdata->port;
592 /* Skip VI2/CSI2 setup for second and later frame capture */
597 TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_CONTROL,
598 0x3 | (0x1 << 5) | (0x40 << 8));
602 * PAD_CILA_PDVCLAMP 0, PAD_CILA_PDIO_CLK 0,
603 * PAD_CILA_PDIO 0, PAD_AB_BK_MODE 1
605 TC_VI_REG_WT(cam, TEGRA_CSI_CILA_PAD_CONFIG0, 0x10000);
607 /* PAD_CILB_PDVCLAMP 0, PAD_CILB_PDIO_CLK 0, PAD_CILB_PDIO 0 */
608 TC_VI_REG_WT(cam, TEGRA_CSI_CILB_PAD_CONFIG0, 0x0);
611 * PAD_CILC_PDVCLAMP 0, PAD_CILC_PDIO_CLK 0,
612 * PAD_CILC_PDIO 0, PAD_CD_BK_MODE 1
614 TC_VI_REG_WT(cam, TEGRA_CSI_CILC_PAD_CONFIG0, 0x10000);
616 /* PAD_CILD_PDVCLAMP 0, PAD_CILD_PDIO_CLK 0, PAD_CILD_PDIO 0 */
617 TC_VI_REG_WT(cam, TEGRA_CSI_CILD_PAD_CONFIG0, 0x0);
619 /* PAD_CILE_PDVCLAMP 0, PAD_CILE_PDIO_CLK 0, PAD_CILE_PDIO 0 */
620 TC_VI_REG_WT(cam, TEGRA_CSI_CILE_PAD_CONFIG0, 0x0);
622 /* Common programming set for any config */
623 TC_VI_REG_WT(cam, TEGRA_CSI_CLKEN_OVERRIDE, 0x0);
624 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020202);
625 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_A_INTERRUPT_MASK, 0x0);
626 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_B_INTERRUPT_MASK, 0x0);
627 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_C_INTERRUPT_MASK, 0x0);
628 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_D_INTERRUPT_MASK, 0x0);
629 TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_E_INTERRUPT_MASK, 0x0);
632 * TODO: these values should be different with different
634 * Hardcode THS settle value just for TPG testing
636 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILA_CONTROL0, 0x8);
637 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILB_CONTROL0, 0x8);
638 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILC_CONTROL0, 0xa);
639 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILD_CONTROL0, 0xa);
640 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILE_CONTROL0, 0xa);
642 /* Setup registers for CSI-A and CSI-B inputs */
643 if (port == TEGRA_CAMERA_PORT_CSI_A)
644 return vi2_capture_setup_csi_0(cam, icd);
645 else if (port == TEGRA_CAMERA_PORT_CSI_B)
646 return vi2_capture_setup_csi_1(cam, icd);
651 static int vi2_capture_buffer_setup(struct tegra_camera_dev *cam,
652 struct tegra_camera_buffer *buf)
654 struct soc_camera_device *icd = buf->icd;
655 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
656 icd->current_fmt->host_fmt);
658 switch (icd->current_fmt->host_fmt->fourcc) {
659 case V4L2_PIX_FMT_YUV420:
660 case V4L2_PIX_FMT_YVU420:
661 /* FIXME: Setup YUV buffer */
663 case V4L2_PIX_FMT_UYVY:
664 case V4L2_PIX_FMT_VYUY:
665 case V4L2_PIX_FMT_YUYV:
666 case V4L2_PIX_FMT_YVYU:
667 case V4L2_PIX_FMT_SBGGR8:
668 case V4L2_PIX_FMT_SGBRG8:
669 case V4L2_PIX_FMT_SBGGR10:
670 case V4L2_PIX_FMT_SRGGB10:
671 case V4L2_PIX_FMT_RGB32:
672 switch (buf->output_channel) {
674 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_OFFSET_MSB,
676 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_OFFSET_LSB,
678 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_STRIDE,
682 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_OFFSET_MSB,
684 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_OFFSET_LSB,
686 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_STRIDE,
690 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_OFFSET_MSB,
692 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_OFFSET_LSB,
694 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_STRIDE,
701 dev_err(&cam->ndev->dev, "Wrong host format %d\n",
702 icd->current_fmt->host_fmt->fourcc);
709 static int vi2_capture_error_status(struct tegra_camera_dev *cam)
714 err = TC_VI_REG_RD(cam, TEGRA_CSI_DEBUG_COUNTER_0);
716 pr_err("TEGRA_CSI_DEBUG_COUNTER_0 0x%08x\n", err);
718 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
720 pr_err("TEGRA_CSI_CSI_CIL_A_STATUS 0x%08x\n", err);
721 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CILA_STATUS);
723 pr_err("TEGRA_CSI_CSI_CILA_STATUS 0x%08x\n", err);
724 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_B_STATUS);
726 pr_err("TEGRA_CSI_CSI_CIL_B_STATUS 0x%08x\n", err);
727 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_C_STATUS);
729 pr_err("TEGRA_CSI_CSI_CIL_C_STATUS 0x%08x\n", err);
730 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_D_STATUS);
732 pr_err("TEGRA_CSI_CSI_CIL_D_STATUS 0x%08x\n", err);
733 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_E_STATUS);
735 pr_err("TEGRA_CSI_CSI_CIL_E_STATUS 0x%08x\n", err);
736 err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS);
738 pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS 0x%08x\n", err);
739 err = TC_VI_REG_RD(cam, TEGRA_VI_CSI_0_ERROR_STATUS);
741 pr_err("TEGRA_VI_CSI_0_ERROR_STATUS 0x%08x\n", err);
746 static int vi2_capture_start(struct tegra_camera_dev *cam,
747 struct tegra_camera_buffer *buf)
749 struct soc_camera_device *icd = buf->icd;
750 struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
751 struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
752 int port = pdata->port;
755 err = vi2_capture_buffer_setup(cam, buf);
759 /* Only wait on CSI frame end syncpt if we're using CSI. */
760 if (port == TEGRA_CAMERA_PORT_CSI_A) {
761 TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
762 (6 << 8) | cam->syncpt_id_csi_a);
763 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
765 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SINGLE_SHOT, 0x1);
766 err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
767 cam->syncpt_id_csi_a,
769 TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
772 } else if (port == TEGRA_CAMERA_PORT_CSI_B) {
773 TC_VI_REG_WT(cam, TEGRA_VI_CFG_VI_INCR_SYNCPT,
774 (7 << 8) | cam->syncpt_id_csi_b);
775 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
777 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_SINGLE_SHOT, 0x1);
778 err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
779 cam->syncpt_id_csi_b,
781 TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
786 /* Mark SOF flag to Zero after we captured the FIRST frame */
790 /* Capture syncpt timeout err, then dump error status */
792 err = vi2_capture_error_status(cam);
797 static int vi2_capture_stop(struct tegra_camera_dev *cam, int port)
799 if (port == TEGRA_CAMERA_PORT_CSI_A)
800 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
802 else if (port == TEGRA_CAMERA_PORT_CSI_B)
803 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
809 /* Reset VI2/CSI2 when activating, no sepecial ops for deactiving */
810 static void vi2_sw_reset(struct tegra_camera_dev *cam)
812 /* T12_CG_2ND_LEVEL_EN */
813 TC_VI_REG_WT(cam, TEGRA_VI_CFG_CG_CTRL, 1);
814 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SW_RESET, 0x1F);
815 TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_SW_RESET, 0x1F);
820 struct tegra_camera_ops vi2_ops = {
821 .clks_init = vi2_clks_init,
822 .clks_deinit = vi2_clks_deinit,
823 .clks_enable = vi2_clks_enable,
824 .clks_disable = vi2_clks_disable,
826 .capture_clean = vi2_capture_clean,
827 .capture_setup = vi2_capture_setup,
828 .capture_start = vi2_capture_start,
829 .capture_stop = vi2_capture_stop,
831 .activate = vi2_sw_reset,
833 .init_syncpts = vi2_init_syncpts,
834 .free_syncpts = vi2_free_syncpts,
835 .incr_syncpts = vi2_incr_syncpts,
837 .port_is_valid = vi2_port_is_valid,
840 int vi2_register(struct tegra_camera_dev *cam)
843 cam->regulator_name = "avdd_dsi_csi";
845 /* Init VI2/CSI2 ops */