]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/media/platform/soc_camera/tegra_camera/vi.c
media: tegra_camera: introduce 2 kthreads for capture
[sojka/nv-tegra/linux-3.10.git] / drivers / media / platform / soc_camera / tegra_camera / vi.c
1 /*
2  * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
3  *
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.
7  *
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
11  * more details.
12  *
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/>.
15  */
16
17 #include <linux/delay.h>
18 #include <linux/clk.h>
19 #include <linux/platform_device.h>
20
21 #include <media/soc_camera.h>
22 #include <media/soc_mediabus.h>
23 #include <media/tegra_v4l2_camera.h>
24
25 #include <mach/clk.h>
26
27 #include "nvhost_syncpt.h"
28 #include "common.h"
29
30 #define TEGRA_SYNCPT_VI_WAIT_TIMEOUT                    200
31 #define TEGRA_SYNCPT_CSI_WAIT_TIMEOUT                   200
32
33 #define TEGRA_VIP_H_ACTIVE_START                        0x98
34 #define TEGRA_VIP_V_ACTIVE_START                        0x10
35
36 /* Tegra CSI-MIPI registers. */
37 #define TEGRA_VI_OUT_1_INCR_SYNCPT                      0x000
38 #define TEGRA_VI_OUT_1_INCR_SYNCPT_CNTRL                0x004
39 #define TEGRA_VI_OUT_1_INCR_SYNCPT_ERROR                0x008
40 #define TEGRA_VI_OUT_2_INCR_SYNCPT                      0x020
41 #define TEGRA_VI_OUT_2_INCR_SYNCPT_CNTRL                0x024
42 #define TEGRA_VI_OUT_2_INCR_SYNCPT_ERROR                0x028
43 #define TEGRA_VI_MISC_INCR_SYNCPT                       0x040
44 #define TEGRA_VI_MISC_INCR_SYNCPT_CNTRL                 0x044
45 #define TEGRA_VI_MISC_INCR_SYNCPT_ERROR                 0x048
46 #define TEGRA_VI_CONT_SYNCPT_OUT_1                      0x060
47 #define TEGRA_VI_CONT_SYNCPT_OUT_2                      0x064
48 #define TEGRA_VI_CONT_SYNCPT_VIP_VSYNC                  0x068
49 #define TEGRA_VI_CONT_SYNCPT_VI2EPP                     0x06c
50 #define TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_START        0x070
51 #define TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END          0x074
52 #define TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_START        0x078
53 #define TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END          0x07c
54 #define TEGRA_VI_CTXSW                                  0x080
55 #define TEGRA_VI_INTSTATUS                              0x084
56 #define TEGRA_VI_VI_INPUT_CONTROL                       0x088
57 #define TEGRA_VI_VI_CORE_CONTROL                        0x08c
58 #define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL                0x090
59 #define TEGRA_VI_VI_SECOND_OUTPUT_CONTROL               0x094
60 #define TEGRA_VI_HOST_INPUT_FRAME_SIZE                  0x098
61 #define TEGRA_VI_HOST_H_ACTIVE                          0x09c
62 #define TEGRA_VI_HOST_V_ACTIVE                          0x0a0
63 #define TEGRA_VI_VIP_H_ACTIVE                           0x0a4
64 #define TEGRA_VI_VIP_V_ACTIVE                           0x0a8
65 #define TEGRA_VI_VI_PEER_CONTROL                        0x0ac
66 #define TEGRA_VI_VI_DMA_SELECT                          0x0b0
67 #define TEGRA_VI_HOST_DMA_WRITE_BUFFER                  0x0b4
68 #define TEGRA_VI_HOST_DMA_BASE_ADDRESS                  0x0b8
69 #define TEGRA_VI_HOST_DMA_WRITE_BUFFER_STATUS           0x0bc
70 #define TEGRA_VI_HOST_DMA_WRITE_PEND_BUFCOUNT           0x0c0
71 #define TEGRA_VI_VB0_START_ADDRESS_FIRST                0x0c4
72 #define TEGRA_VI_VB0_BASE_ADDRESS_FIRST                 0x0c8
73 #define TEGRA_VI_VB0_START_ADDRESS_U                    0x0cc
74 #define TEGRA_VI_VB0_BASE_ADDRESS_U                     0x0d0
75 #define TEGRA_VI_VB0_START_ADDRESS_V                    0x0d4
76 #define TEGRA_VI_VB0_BASE_ADDRESS_V                     0x0d8
77 #define TEGRA_VI_VB_SCRATCH_ADDRESS_UV                  0x0dc
78 #define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE                0x0e0
79 #define TEGRA_VI_VB0_COUNT_FIRST                        0x0e4
80 #define TEGRA_VI_VB0_SIZE_FIRST                         0x0e8
81 #define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST                0x0ec
82 #define TEGRA_VI_VB0_START_ADDRESS_SECOND               0x0f0
83 #define TEGRA_VI_VB0_BASE_ADDRESS_SECOND                0x0f4
84 #define TEGRA_VI_SECOND_OUTPUT_FRAME_SIZE               0x0f8
85 #define TEGRA_VI_VB0_COUNT_SECOND                       0x0fc
86 #define TEGRA_VI_VB0_SIZE_SECOND                        0x100
87 #define TEGRA_VI_VB0_BUFFER_STRIDE_SECOND               0x104
88 #define TEGRA_VI_H_LPF_CONTROL                          0x108
89 #define TEGRA_VI_H_DOWNSCALE_CONTROL                    0x10c
90 #define TEGRA_VI_V_DOWNSCALE_CONTROL                    0x110
91 #define TEGRA_VI_CSC_Y                                  0x114
92 #define TEGRA_VI_CSC_UV_R                               0x118
93 #define TEGRA_VI_CSC_UV_G                               0x11c
94 #define TEGRA_VI_CSC_UV_B                               0x120
95 #define TEGRA_VI_CSC_ALPHA                              0x124
96 #define TEGRA_VI_HOST_VSYNC                             0x128
97 #define TEGRA_VI_COMMAND                                0x12c
98 #define TEGRA_VI_HOST_FIFO_STATUS                       0x130
99 #define TEGRA_VI_INTERRUPT_MASK                         0x134
100 #define TEGRA_VI_INTERRUPT_TYPE_SELECT                  0x138
101 #define TEGRA_VI_INTERRUPT_POLARITY_SELECT              0x13c
102 #define TEGRA_VI_INTERRUPT_STATUS                       0x140
103 #define TEGRA_VI_VIP_INPUT_STATUS                       0x144
104 #define TEGRA_VI_VIDEO_BUFFER_STATUS                    0x148
105 #define TEGRA_VI_SYNC_OUTPUT                            0x14c
106 #define TEGRA_VI_VVS_OUTPUT_DELAY                       0x150
107 #define TEGRA_VI_PWM_CONTROL                            0x154
108 #define TEGRA_VI_PWM_SELECT_PULSE_A                     0x158
109 #define TEGRA_VI_PWM_SELECT_PULSE_B                     0x15c
110 #define TEGRA_VI_PWM_SELECT_PULSE_C                     0x160
111 #define TEGRA_VI_PWM_SELECT_PULSE_D                     0x164
112 #define TEGRA_VI_VI_DATA_INPUT_CONTROL                  0x168
113 #define TEGRA_VI_PIN_INPUT_ENABLE                       0x16c
114 #define TEGRA_VI_PIN_OUTPUT_ENABLE                      0x170
115 #define TEGRA_VI_PIN_INVERSION                          0x174
116 #define TEGRA_VI_PIN_INPUT_DATA                         0x178
117 #define TEGRA_VI_PIN_OUTPUT_DATA                        0x17c
118 #define TEGRA_VI_PIN_OUTPUT_SELECT                      0x180
119 #define TEGRA_VI_RAISE_VIP_BUFFER_FIRST_OUTPUT          0x184
120 #define TEGRA_VI_RAISE_VIP_FRAME_FIRST_OUTPUT           0x188
121 #define TEGRA_VI_RAISE_VIP_BUFFER_SECOND_OUTPUT         0x18c
122 #define TEGRA_VI_RAISE_VIP_FRAME_SECOND_OUTPUT          0x190
123 #define TEGRA_VI_RAISE_HOST_FIRST_OUTPUT                0x194
124 #define TEGRA_VI_RAISE_HOST_SECOND_OUTPUT               0x198
125 #define TEGRA_VI_RAISE_EPP                              0x19c
126 #define TEGRA_VI_CAMERA_CONTROL                         0x1a0
127 #define TEGRA_VI_VI_ENABLE                              0x1a4
128 #define TEGRA_VI_VI_ENABLE_2                            0x1a8
129 #define TEGRA_VI_VI_RAISE                               0x1ac
130 #define TEGRA_VI_Y_FIFO_WRITE                           0x1b0
131 #define TEGRA_VI_U_FIFO_WRITE                           0x1b4
132 #define TEGRA_VI_V_FIFO_WRITE                           0x1b8
133 #define TEGRA_VI_VI_MCCIF_FIFOCTRL                      0x1bc
134 #define TEGRA_VI_TIMEOUT_WCOAL_VI                       0x1c0
135 #define TEGRA_VI_MCCIF_VIRUV_HP                         0x1c4
136 #define TEGRA_VI_MCCIF_VIWSB_HP                         0x1c8
137 #define TEGRA_VI_MCCIF_VIWU_HP                          0x1cc
138 #define TEGRA_VI_MCCIF_VIWV_HP                          0x1d0
139 #define TEGRA_VI_MCCIF_VIWY_HP                          0x1d4
140 #define TEGRA_VI_CSI_PPA_RAISE_FRAME_START              0x1d8
141 #define TEGRA_VI_CSI_PPA_RAISE_FRAME_END                0x1dc
142 #define TEGRA_VI_CSI_PPB_RAISE_FRAME_START              0x1e0
143 #define TEGRA_VI_CSI_PBB_RAISE_FRAME_END                0x1e4
144 #define TEGRA_VI_CSI_PPA_H_ACTIVE                       0x1e8
145 #define TEGRA_VI_CSI_PPA_V_ACTIVE                       0x1ec
146 #define TEGRA_VI_CSI_PPB_H_ACTIVE                       0x1f0
147 #define TEGRA_VI_CSI_PPB_V_ACTIVE                       0x1f4
148 #define TEGRA_VI_ISP_H_ACTIVE                           0x1f8
149 #define TEGRA_VI_ISP_V_ACTIVE                           0x1fc
150 #define TEGRA_VI_STREAM_1_RESOURCE_DEFINE               0x200
151 #define TEGRA_VI_STREAM_2_RESOURCE_DEFINE               0x204
152 #define TEGRA_VI_RAISE_STREAM_1_DONE                    0x208
153 #define TEGRA_VI_RAISE_STREAM_2_DONE                    0x20c
154 #define TEGRA_VI_TS_MODE                                0x210
155 #define TEGRA_VI_TS_CONTROL                             0x214
156 #define TEGRA_VI_TS_PACKET_COUNT                        0x218
157 #define TEGRA_VI_TS_ERROR_COUNT                         0x21c
158 #define TEGRA_VI_TS_CPU_FLOW_CTL                        0x220
159 #define TEGRA_VI_VB0_CHROMA_BUFFER_STRIDE_FIRST         0x224
160 #define TEGRA_VI_VB0_CHROMA_LINE_STRIDE_FIRST           0x228
161 #define TEGRA_VI_EPP_LINES_PER_BUFFER                   0x22c
162 #define TEGRA_VI_BUFFER_RELEASE_OUTPUT1                 0x230
163 #define TEGRA_VI_BUFFER_RELEASE_OUTPUT2                 0x234
164 #define TEGRA_VI_DEBUG_FLOW_CONTROL_COUNTER_OUTPUT1     0x238
165 #define TEGRA_VI_DEBUG_FLOW_CONTROL_COUNTER_OUTPUT2     0x23c
166 #define TEGRA_VI_TERMINATE_BW_FIRST                     0x240
167 #define TEGRA_VI_TERMINATE_BW_SECOND                    0x244
168 #define TEGRA_VI_VB0_FIRST_BUFFER_ADDR_MODE             0x248
169 #define TEGRA_VI_VB0_SECOND_BUFFER_ADDR_MODE            0x24c
170 #define TEGRA_VI_RESERVE                        0x250
171 #define TEGRA_VI_RESERVE_1                              0x254
172 #define TEGRA_VI_RESERVE_2                              0x258
173 #define TEGRA_VI_RESERVE_3                              0x25c
174 #define TEGRA_VI_RESERVE_4                              0x260
175 #define TEGRA_VI_MCCIF_VIRUV_HYST                       0x264
176 #define TEGRA_VI_MCCIF_VIWSB_HYST                       0x268
177 #define TEGRA_VI_MCCIF_VIWU_HYST                        0x26c
178 #define TEGRA_VI_MCCIF_VIWV_HYST                        0x270
179 #define TEGRA_VI_MCCIF_VIWY_HYST                        0x274
180
181 #define TEGRA_CSI_VI_INPUT_STREAM_CONTROL               0x800
182 #define TEGRA_CSI_HOST_INPUT_STREAM_CONTROL             0x808
183 #define TEGRA_CSI_INPUT_STREAM_A_CONTROL                0x810
184 #define TEGRA_CSI_PIXEL_STREAM_A_CONTROL0               0x818
185 #define TEGRA_CSI_PIXEL_STREAM_A_CONTROL1               0x81c
186 #define TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT             0x820
187 #define TEGRA_CSI_PIXEL_STREAM_A_GAP                    0x824
188 #define TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND              0x828
189 #define TEGRA_CSI_INPUT_STREAM_B_CONTROL                0x83c
190 #define TEGRA_CSI_PIXEL_STREAM_B_CONTROL0               0x844
191 #define TEGRA_CSI_PIXEL_STREAM_B_CONTROL1               0x848
192 #define TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT             0x84c
193 #define TEGRA_CSI_PIXEL_STREAM_B_GAP                    0x850
194 #define TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND              0x854
195 #define TEGRA_CSI_PHY_CIL_COMMAND                       0x868
196 #define TEGRA_CSI_PHY_CILA_CONTROL0                     0x86c
197 #define TEGRA_CSI_PHY_CILB_CONTROL0                     0x870
198 #define TEGRA_CSI_CSI_PIXEL_PARSER_STATUS               0x878
199 #define TEGRA_CSI_CSI_CIL_STATUS                        0x87c
200 #define TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK       0x880
201 #define TEGRA_CSI_CSI_CIL_INTERRUPT_MASK                0x884
202 #define TEGRA_CSI_CSI_READONLY_STATUS                   0x888
203 #define TEGRA_CSI_ESCAPE_MODE_COMMAND                   0x88c
204 #define TEGRA_CSI_ESCAPE_MODE_DATA                      0x890
205 #define TEGRA_CSI_CILA_PAD_CONFIG0                      0x894
206 #define TEGRA_CSI_CILA_PAD_CONFIG1                      0x898
207 #define TEGRA_CSI_CILB_PAD_CONFIG0                      0x89c
208 #define TEGRA_CSI_CILB_PAD_CONFIG1                      0x8a0
209 #define TEGRA_CSI_CIL_PAD_CONFIG                        0x8a4
210 #define TEGRA_CSI_CILA_MIPI_CAL_CONFIG                  0x8a8
211 #define TEGRA_CSI_CILB_MIPI_CAL_CONFIG                  0x8ac
212 #define TEGRA_CSI_CIL_MIPI_CAL_STATUS                   0x8b0
213 #define TEGRA_CSI_CLKEN_OVERRIDE                        0x8b4
214 #define TEGRA_CSI_DEBUG_CONTROL                         0x8b8
215 #define TEGRA_CSI_DEBUG_COUNTER                         0x8bc
216 #define TEGRA_CSI_DEBUG_COUNTER_1                       0x8c0
217 #define TEGRA_CSI_DEBUG_COUNTER_2                       0x8c4
218 #define TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME         0x8c8
219 #define TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME         0x8cc
220 #define TEGRA_CSI_DSI_MIPI_CAL_CONFIG                   0x8d0
221
222 /* Test Pattern Generator of CSI */
223 #define TEGRA_CSI_PATTERN_GENERATOR_CTRL_A              0x940
224 #define TEGRA_CSI_PG_BLANK_A                            0x944
225 #define TEGRA_CSI_PG_PHASE_A                            0x948
226 #define TEGRA_CSI_PG_RED_FREQ_A                         0x94c
227 #define TEGRA_CSI_PG_RED_FREQ_RATE_A                    0x950
228 #define TEGRA_CSI_PG_GREEN_FREQ_A                       0x954
229 #define TEGRA_CSI_PG_GREEN_FREQ_RATE_A                  0x958
230 #define TEGRA_CSI_PG_BLUE_FREQ_A                        0x95c
231 #define TEGRA_CSI_PG_BLUE_FREQ_RATE_A                   0x960
232 #define TEGRA_CSI_PATTERN_GENERATOR_CTRL_B              0x974
233 #define TEGRA_CSI_PG_BLANK_B                            0x978
234 #define TEGRA_CSI_PG_PHASE_B                            0x97c
235 #define TEGRA_CSI_PG_RED_FREQ_B                         0x980
236 #define TEGRA_CSI_PG_RED_FREQ_RATE_B                    0x984
237 #define TEGRA_CSI_PG_GREEN_FREQ_B                       0x988
238 #define TEGRA_CSI_PG_GREEN_FREQ_RATE_B                  0x98c
239 #define TEGRA_CSI_PG_BLUE_FREQ_B                        0x990
240 #define TEGRA_CSI_PG_BLUE_FREQ_RATE_B                   0x994
241
242 static int vi_port_is_valid(int port)
243 {
244         return (((port) >= TEGRA_CAMERA_PORT_CSI_A) &&
245                 ((port) <= TEGRA_CAMERA_PORT_VIP));
246 }
247
248 static int vi_port_is_csi(int port)
249 {
250         return (((port) == TEGRA_CAMERA_PORT_CSI_A) ||
251                 ((port) == TEGRA_CAMERA_PORT_CSI_B));
252 }
253
254 /* Clock settings for camera */
255 static struct tegra_camera_clk vi_clks[] = {
256         {
257                 .name = "vi",
258                 .freq = 150000000,
259         },
260         {
261                 .name = "vi_sensor",
262                 .freq = 24000000,
263         },
264         {
265                 .name = "csi",
266                 .freq = 0,
267         },
268         {
269                 .name = "isp",
270                 .freq = 0,
271         },
272         {
273                 .name = "csus",
274                 .freq = 0,
275         },
276         {
277                 .name = "sclk",
278                 .freq = 80000000,
279         },
280         {
281                 .name = "emc",
282                 .freq = 375000000,
283         },
284 #ifdef TEGRA_11X_OR_HIGHER_CONFIG
285         {
286                 .name = "cilab",
287                 .freq = 102000000,
288         },
289         {
290                 .name = "cilcd",
291                 .freq = 0,
292         },
293         {
294                 .name = "cile",
295                 .freq = 0,
296         },
297         /* Always put "p11_d2" at the end */
298         {
299                 .name = "pll_d2",
300                 .freq = 0,
301         },
302 #endif
303 };
304
305 static int vi_clks_init(struct tegra_camera_dev *cam, int port)
306 {
307         struct platform_device *pdev = cam->ndev;
308         struct tegra_camera_clk *clks;
309         int i;
310
311         cam->num_clks = ARRAY_SIZE(vi_clks);
312         cam->clks = vi_clks;
313
314         for (i = 0; i < cam->num_clks; i++) {
315                 clks = &cam->clks[i];
316                 clks->clk = devm_clk_get(&pdev->dev, clks->name);
317                 if (IS_ERR_OR_NULL(clks->clk)) {
318                         clks->clk = NULL;
319                         dev_err(&pdev->dev, "Failed to get clock %s.\n",
320                                 clks->name);
321                         return PTR_ERR(clks->clk);
322                 }
323
324                 if (clks->freq > 0)
325                         clk_set_rate(clks->clk, clks->freq);
326         }
327
328         return 0;
329 }
330
331 static void vi_clks_deinit(struct tegra_camera_dev *cam)
332 {
333         /* We don't need cleanup for devm_clk_get() */
334         return;
335 }
336
337 static void vi_clks_enable(struct tegra_camera_dev *cam)
338 {
339         struct tegra_camera_clk *clks;
340         int i;
341
342         for (i = 0; i < cam->num_clks - 1; i++) {
343                 clks = &cam->clks[i];
344                 if (clks->clk)
345                         clk_prepare_enable(clks->clk);
346         }
347
348 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
349 #define TEGRA_APB_MISC_BASE             0x70000000
350         {
351                 u32 val;
352                 void __iomem *apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE);
353
354                 val = readl(apb_misc + 0x42c);
355                 writel(val | 0x1, apb_misc + 0x42c);
356         }
357 #endif
358
359         if (cam->tpg_mode) {
360                 clks = &cam->clks[i];
361                 if (clks->clk) {
362                         clk_prepare_enable(clks->clk);
363 #ifdef TEGRA_11X_OR_HIGHER_CONFIG
364                         tegra_clk_cfg_ex(clks->clk,
365                                          TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
366                         tegra_clk_cfg_ex(clks->clk,
367                                          TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
368 #else
369                         /*
370                          * bit 25: 0 = pd2vi_Clk,
371                          *         1 = vi_sensor_clk
372                          * bit 24: 0 = internal clock,
373                          *         1 = external clock (pd2vi_clk)
374                          */
375                         tegra_clk_cfg_ex(clks->clk, TEGRA_CLK_VI_INP_SEL, 2);
376 #endif
377                 }
378         }
379 }
380
381 static void vi_clks_disable(struct tegra_camera_dev *cam)
382 {
383         struct tegra_camera_clk *clks;
384         int i;
385
386         for (i = 0; i < cam->num_clks - 1; i++) {
387                 clks = &cam->clks[i];
388                 if (clks->clk)
389                         clk_disable_unprepare(clks->clk);
390         }
391
392         if (cam->tpg_mode) {
393                 clks = &cam->clks[i];
394                 if (clks->clk) {
395 #ifdef TEGRA_11X_OR_HIGHER_CONFIG
396                         tegra_clk_cfg_ex(clks->clk,
397                                          TEGRA_CLK_PLLD_CSI_OUT_ENB, 0);
398                         tegra_clk_cfg_ex(clks->clk,
399                                          TEGRA_CLK_PLLD_DSI_OUT_ENB, 0);
400 #endif
401                         clk_disable_unprepare(clks->clk);
402                 }
403         }
404 }
405
406 static void vi_init_syncpts(struct tegra_camera_dev *cam)
407 {
408         cam->syncpt_id_csi_a = nvhost_get_syncpt_client_managed("vi_csi_A");
409
410         cam->syncpt_id_csi_b = nvhost_get_syncpt_client_managed("vi_csi_B");
411
412         cam->syncpt_id_vip = nvhost_get_syncpt_client_managed("vi_vip");
413 }
414
415 static void vi_free_syncpts(struct tegra_camera_dev *cam)
416 {
417         nvhost_free_syncpt(cam->syncpt_id_csi_a);
418
419         nvhost_free_syncpt(cam->syncpt_id_csi_b);
420
421         nvhost_free_syncpt(cam->syncpt_id_vip);
422 }
423
424 static void vi_save_syncpts(struct tegra_camera_dev *cam)
425 {
426         u32 val;
427
428         if (!nvhost_syncpt_read_ext_check(cam->ndev,
429                         cam->syncpt_id_csi_a, &val))
430                 cam->syncpt_csi_a = val;
431
432         if (!nvhost_syncpt_read_ext_check(cam->ndev,
433                         cam->syncpt_id_csi_b, &val))
434                 cam->syncpt_csi_b = val;
435
436         if (!nvhost_syncpt_read_ext_check(cam->ndev,
437                         cam->syncpt_id_vip, &val))
438                 cam->syncpt_vip = val;
439 }
440
441 static void vi_incr_syncpts(struct tegra_camera_dev *cam)
442 {
443         nvhost_syncpt_cpu_incr_ext(cam->ndev, cam->syncpt_id_csi_a);
444
445         nvhost_syncpt_cpu_incr_ext(cam->ndev, cam->syncpt_id_csi_b);
446
447         nvhost_syncpt_cpu_incr_ext(cam->ndev, cam->syncpt_id_vip);
448 }
449
450 static void vi_capture_clean(struct tegra_camera_dev *cam)
451 {
452         TC_VI_REG_WT(cam, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0x00000000);
453         TC_VI_REG_WT(cam, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0x00000000);
454
455         TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, 0x0);
456         TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_STATUS, 0x0);
457         TC_VI_REG_WT(cam, TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0);
458         TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_INTERRUPT_MASK, 0x0);
459         TC_VI_REG_WT(cam, TEGRA_CSI_CSI_READONLY_STATUS, 0x0);
460         TC_VI_REG_WT(cam, TEGRA_CSI_ESCAPE_MODE_COMMAND, 0x0);
461         TC_VI_REG_WT(cam, TEGRA_CSI_ESCAPE_MODE_DATA, 0x0);
462
463         TC_VI_REG_WT(cam, TEGRA_CSI_CIL_PAD_CONFIG, 0x00000000);
464         TC_VI_REG_WT(cam, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0x00000000);
465         TC_VI_REG_WT(cam, TEGRA_CSI_CLKEN_OVERRIDE, 0x00000000);
466
467         TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_CONTROL, 0x0);
468         TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_COUNTER, 0x0);
469         TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_COUNTER_1, 0x0);
470         TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_COUNTER_2, 0x0);
471 }
472
473 static void vi_capture_setup_csi_a(struct tegra_camera_dev *cam,
474                                    struct soc_camera_device *icd,
475                                    u32 hdr)
476 {
477         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
478         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
479         int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
480                         icd->current_fmt->host_fmt);
481
482         TC_VI_REG_WT(cam, TEGRA_CSI_INPUT_STREAM_A_CONTROL, 0x00000000);
483         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0, 0x00000000);
484         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1, 0x00000000);
485         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT, 0x00000000);
486         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00000000);
487         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x00000000);
488         TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILA_CONTROL0, 0x00000000);
489         TC_VI_REG_WT(cam, TEGRA_CSI_CILA_PAD_CONFIG0, 0x00000000);
490         TC_VI_REG_WT(cam, TEGRA_CSI_CILA_PAD_CONFIG1, 0x00000000);
491         TC_VI_REG_WT(cam, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, 0x00000000);
492         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME, 0x0);
493
494         TC_VI_REG_WT(cam, TEGRA_VI_VI_CORE_CONTROL, 0x02000000);
495
496         /* CSI-A H_ACTIVE and V_ACTIVE */
497         TC_VI_REG_WT(cam, TEGRA_VI_CSI_PPA_H_ACTIVE,
498                      (icd->user_width << 16));
499         TC_VI_REG_WT(cam, TEGRA_VI_CSI_PPA_V_ACTIVE,
500                      (icd->user_height << 16));
501
502         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL1,
503                 0x1); /* Frame # for top field detect for interlaced */
504
505         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_WORD_COUNT,
506                 bytes_per_line);
507         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_GAP, 0x00140000);
508
509         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_EXPECTED_FRAME,
510                         ((icd->user_height + cam->tpg_mode) << 16));
511
512         /* pad 0s enabled, virtual channel ID 00 */
513         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_A_CONTROL0,
514                 (0x1 << 16) | /* Output 1 pixel per clock */
515                 (hdr << 8) | /* If hdr shows wrong fmt, use right value */
516                 (0x1 << 7) | /* Check header CRC */
517                 (0x1 << 6) | /* Use word count field in the header */
518                 (0x1 << 5) | /* Look at data identifier byte in hdr */
519                 (0x1 << 4));  /* Expect packet header */
520
521         TC_VI_REG_WT(cam, TEGRA_CSI_INPUT_STREAM_A_CONTROL,
522                      (0x3f << 16) | /* Skip packet threshold */
523                      (pdata->lanes - 1));
524
525         /* Use 0x00000022 for continuous clock mode. */
526         TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILA_CONTROL0,
527                 (pdata->continuous_clk << 5) |
528                 0x5); /* Clock settle time */
529
530         TC_VI_REG_WT(cam, TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END,
531                 (0x1 << 8) | /* Enable continuous syncpt */
532                 cam->syncpt_id_csi_a);
533
534         TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x00020001);
535
536         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, 0x0000f002);
537
538         if (cam->tpg_mode) {
539                 TC_VI_REG_WT(cam, TEGRA_CSI_PATTERN_GENERATOR_CTRL_A,
540                                 ((cam->tpg_mode - 1) << 2) | 0x1);
541                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_PHASE_A, 0x0);
542                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_RED_FREQ_A, 0x00800080);
543                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_RED_FREQ_RATE_A, 0x0);
544                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_GREEN_FREQ_A, 0x00800080);
545                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_GREEN_FREQ_RATE_A, 0x0);
546                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLUE_FREQ_A, 0x00800080);
547                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLUE_FREQ_RATE_A, 0x0);
548                 TC_VI_REG_WT(cam, TEGRA_CSI_PG_BLANK_A, 0x0000FFFF);
549         }
550
551 }
552
553 static void vi_capture_setup_csi_b(struct tegra_camera_dev *cam,
554                                    struct soc_camera_device *icd,
555                                    u32 hdr)
556 {
557         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
558         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
559         int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
560                                                 icd->current_fmt->host_fmt);
561
562         TC_VI_REG_WT(cam, TEGRA_CSI_INPUT_STREAM_B_CONTROL, 0x00000000);
563         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0, 0x00000000);
564         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1, 0x00000000);
565         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT, 0x00000000);
566         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00000000);
567         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x00000000);
568         TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILB_CONTROL0, 0x00000000);
569         TC_VI_REG_WT(cam, TEGRA_CSI_CILB_PAD_CONFIG0, 0x00000000);
570         TC_VI_REG_WT(cam, TEGRA_CSI_CILB_PAD_CONFIG1, 0x00000000);
571         TC_VI_REG_WT(cam, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, 0x00000000);
572         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME, 0x0);
573
574         TC_VI_REG_WT(cam, TEGRA_VI_VI_CORE_CONTROL, 0x04000000);
575
576         /* CSI-B H_ACTIVE and V_ACTIVE */
577         TC_VI_REG_WT(cam, TEGRA_VI_CSI_PPB_H_ACTIVE,
578                 (icd->user_width << 16));
579         TC_VI_REG_WT(cam, TEGRA_VI_CSI_PPB_V_ACTIVE,
580                 (icd->user_height << 16));
581
582         /* pad 0s enabled, virtual channel ID 00 */
583         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL0,
584                 (0x1 << 16) | /* Output 1 pixel per clock */
585                 (hdr << 8) | /* If hdr shows wrong fmt, use right value */
586                 (0x1 << 7) | /* Check header CRC */
587                 (0x1 << 6) | /* Use word count field in the header */
588                 (0x1 << 5) | /* Look at data identifier byte in hdr */
589                 (0x1 << 4) | /* Expect packet header */
590                 0x1); /* Set PPB stream source to CSI B */
591
592         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_CONTROL1,
593                 0x1); /* Frame # for top field detect for interlaced */
594
595         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_WORD_COUNT,
596                 bytes_per_line);
597         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_GAP, 0x00140000);
598
599         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_B_EXPECTED_FRAME,
600                 (icd->user_height << 16) |
601                 (0x100 << 4) | /* Wait 0x100 vi clks for timeout */
602                 0x1); /* Enable line timeout */
603
604         TC_VI_REG_WT(cam, TEGRA_CSI_INPUT_STREAM_B_CONTROL,
605                      (0x3f << 16) | /* Skip packet threshold */
606                      (pdata->lanes - 1));
607
608         /* Use 0x00000022 for continuous clock mode. */
609         TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CILB_CONTROL0,
610                 (pdata->continuous_clk << 5) |
611                 0x5); /* Clock settle time */
612
613         TC_VI_REG_WT(cam, TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END,
614                 (0x1 << 8) | /* Enable continuous syncpt */
615                 cam->syncpt_id_csi_b);
616
617         TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x00010002);
618
619         TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, 0x0000f002);
620 }
621
622 static void vi_capture_setup_vip(struct tegra_camera_dev *cam,
623                                            struct soc_camera_device *icd,
624                                            u32 input_control)
625 {
626         TC_VI_REG_WT(cam, TEGRA_VI_VI_CORE_CONTROL, 0x00000000);
627
628         TC_VI_REG_WT(cam, TEGRA_VI_VI_INPUT_CONTROL,
629                 (1 << 27) | /* field detect */
630                 (1 << 25) | /* hsync/vsync decoded from data (BT.656) */
631                 (1 << 1) | /* VIP_INPUT_ENABLE */
632                 input_control);
633
634         TC_VI_REG_WT(cam, TEGRA_VI_H_DOWNSCALE_CONTROL, 0x00000000);
635         TC_VI_REG_WT(cam, TEGRA_VI_V_DOWNSCALE_CONTROL, 0x00000000);
636
637         /* VIP H_ACTIVE and V_ACTIVE */
638         TC_VI_REG_WT(cam, TEGRA_VI_VIP_H_ACTIVE,
639                 (icd->user_width << 16) |
640                 TEGRA_VIP_H_ACTIVE_START);
641         TC_VI_REG_WT(cam, TEGRA_VI_VIP_V_ACTIVE,
642                 (icd->user_height << 16) |
643                 TEGRA_VIP_V_ACTIVE_START);
644
645         /*
646          * For VIP, D9..D2 is mapped to the video decoder's P7..P0.
647          * Disable/mask out the other Dn wires.
648          */
649         TC_VI_REG_WT(cam, TEGRA_VI_PIN_INPUT_ENABLE, 0x000003fc);
650         TC_VI_REG_WT(cam, TEGRA_VI_VI_DATA_INPUT_CONTROL, 0x000003fc);
651         TC_VI_REG_WT(cam, TEGRA_VI_PIN_INVERSION, 0x00000000);
652
653         TC_VI_REG_WT(cam, TEGRA_VI_CONT_SYNCPT_VIP_VSYNC,
654                 (0x1 << 8) | /* Enable continuous syncpt */
655                 cam->syncpt_id_vip);
656
657         TC_VI_REG_WT(cam, TEGRA_VI_CAMERA_CONTROL, 0x00000004);
658 }
659
660 static int vi_capture_output_channel_setup(
661                 struct tegra_camera_dev *cam,
662                 struct soc_camera_device *icd)
663 {
664         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
665         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
666         int port = pdata->port;
667         int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
668                                                 icd->current_fmt->host_fmt);
669         const struct soc_camera_format_xlate *current_fmt = icd->current_fmt;
670         u32 output_fourcc = current_fmt->host_fmt->fourcc;
671         u32 output_format, output_control;
672         struct tegra_camera_buffer *buf = to_tegra_vb(cam->active);
673
674         switch (output_fourcc) {
675         case V4L2_PIX_FMT_UYVY:
676                 output_format = 0x3; /* Default to YUV422 */
677                 break;
678         case V4L2_PIX_FMT_VYUY:
679                 output_format = (0x1 << 17) | 0x3;
680                 break;
681         case V4L2_PIX_FMT_YUYV:
682                 output_format = (0x2 << 17) | 0x3;
683                 break;
684         case V4L2_PIX_FMT_YVYU:
685                 output_format = (0x3 << 17) | 0x3;
686                 break;
687         case V4L2_PIX_FMT_YUV420:
688         case V4L2_PIX_FMT_YVU420:
689                 output_format = 0x6; /* YUV420 planar */
690                 break;
691         case V4L2_PIX_FMT_SBGGR8:
692         case V4L2_PIX_FMT_SGBRG8:
693         case V4L2_PIX_FMT_SBGGR10:
694                 /* Use second output channel for RAW8/RAW10 */
695                 buf->output_channel = 1;
696
697                 if (port == TEGRA_CAMERA_PORT_CSI_A)
698                         output_format = 0x7;
699                 else if (port == TEGRA_CAMERA_PORT_CSI_B)
700                         output_format = 0x8;
701                 else
702                         output_format = 0x9;
703                 break;
704         default:
705                 dev_err(&cam->ndev->dev, "Wrong output format %d\n",
706                         output_fourcc);
707                 return -EINVAL;
708         }
709
710         output_control = (pdata->flip_v ? (0x1 << 20) : 0) |
711                         (pdata->flip_h ? (0x1 << 19) : 0) |
712                         output_format;
713
714         if (buf->output_channel == 0) {
715                 TC_VI_REG_WT(cam, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
716                                 output_control);
717                 /*
718                  * Set up frame size.  Bits 31:16 are the number of lines, and
719                  * bits 15:0 are the number of pixels per line.
720                  */
721                 TC_VI_REG_WT(cam, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
722                                 (icd->user_height << 16) | icd->user_width);
723
724                 /* First output memory enabled */
725                 TC_VI_REG_WT(cam, TEGRA_VI_VI_ENABLE, 0x00000000);
726
727                 /* Set the number of frames in the buffer. */
728                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_COUNT_FIRST, 0x00000001);
729
730                 /* Set up buffer frame size. */
731                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_SIZE_FIRST,
732                                 (icd->user_height << 16) | icd->user_width);
733
734                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
735                                 (icd->user_height * bytes_per_line));
736
737                 TC_VI_REG_WT(cam, TEGRA_VI_CONT_SYNCPT_OUT_1,
738                                 (0x1 << 8) | /* Enable continuous syncpt */
739                                 cam->syncpt_id_vip);
740
741                 TC_VI_REG_WT(cam, TEGRA_VI_VI_ENABLE, 0x00000000);
742         } else if (buf->output_channel == 1) {
743                 TC_VI_REG_WT(cam, TEGRA_VI_VI_SECOND_OUTPUT_CONTROL,
744                                 output_control);
745
746                 TC_VI_REG_WT(cam, TEGRA_VI_SECOND_OUTPUT_FRAME_SIZE,
747                                 (icd->user_height << 16) | icd->user_width);
748
749                 TC_VI_REG_WT(cam, TEGRA_VI_VI_ENABLE_2, 0x00000000);
750
751                 /* Set the number of frames in the buffer. */
752                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_COUNT_SECOND, 0x00000001);
753
754                 /* Set up buffer frame size. */
755                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_SIZE_SECOND,
756                                 (icd->user_height << 16) | icd->user_width);
757
758                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_BUFFER_STRIDE_SECOND,
759                                 (icd->user_height * bytes_per_line));
760
761                 TC_VI_REG_WT(cam, TEGRA_VI_CONT_SYNCPT_OUT_2,
762                                 (0x1 << 8) | /* Enable continuous syncpt */
763                                 cam->syncpt_id_vip);
764
765                 TC_VI_REG_WT(cam, TEGRA_VI_VI_ENABLE_2, 0x00000000);
766         } else {
767                 dev_err(&cam->ndev->dev, "Wrong output channel %d\n",
768                         buf->output_channel);
769                 return -EINVAL;
770         }
771
772         return 0;
773 }
774
775
776 static int vi_capture_setup(struct tegra_camera_dev *cam,
777                             struct tegra_camera_buffer *buf)
778 {
779         struct soc_camera_device *icd = buf->icd;
780         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
781         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
782         int port = pdata->port;
783         const struct soc_camera_format_xlate *current_fmt = icd->current_fmt;
784         enum v4l2_mbus_pixelcode input_code = current_fmt->code;
785         u32 hdr, input_control = 0x0;
786
787         switch (input_code) {
788         case V4L2_MBUS_FMT_UYVY8_2X8:
789                 input_control |= 0x2 << 8;
790                 hdr = 30;
791                 break;
792         case V4L2_MBUS_FMT_VYUY8_2X8:
793                 input_control |= 0x3 << 8;
794                 hdr = 30;
795                 break;
796         case V4L2_MBUS_FMT_YUYV8_2X8:
797                 input_control |= 0x0;
798                 hdr = 30;
799                 break;
800         case V4L2_MBUS_FMT_YVYU8_2X8:
801                 input_control |= 0x1 << 8;
802                 hdr = 30;
803                 break;
804         case V4L2_MBUS_FMT_SBGGR8_1X8:
805         case V4L2_MBUS_FMT_SGBRG8_1X8:
806                 input_control |= 0x2 << 2;      /* Input Format = Bayer */
807                 hdr = 42;
808                 break;
809         case V4L2_MBUS_FMT_SBGGR10_1X10:
810                 input_control |= 0x2 << 2;      /* Input Format = Bayer */
811                 hdr = 43;
812                 break;
813         default:
814                 dev_err(&cam->ndev->dev, "Input format %d is not supported\n",
815                         input_code);
816                 return -EINVAL;
817         }
818
819         /*
820          * Set up low pass filter.  Use 0x240 for chromaticity and 0x240
821          * for luminance, which is the default and means not to touch
822          * anything.
823          */
824         TC_VI_REG_WT(cam, TEGRA_VI_H_LPF_CONTROL, 0x02400240);
825
826         /* Set up raise-on-edge, so we get an interrupt on end of frame. */
827         TC_VI_REG_WT(cam, TEGRA_VI_VI_RAISE, 0x00000001);
828
829         /* Setup registers for CSI-A, CSI-B and VIP inputs */
830         if (port == TEGRA_CAMERA_PORT_CSI_A)
831                 vi_capture_setup_csi_a(cam, icd, hdr);
832         else if (port == TEGRA_CAMERA_PORT_CSI_B)
833                 vi_capture_setup_csi_b(cam, icd, hdr);
834         else
835                 vi_capture_setup_vip(cam, icd, input_control);
836
837         /* Setup registers for output channels */
838         return vi_capture_output_channel_setup(cam, icd);
839 }
840
841 static int vi_capture_buffer_setup(struct tegra_camera_dev *cam,
842                         struct tegra_camera_buffer *buf)
843 {
844         struct soc_camera_device *icd = buf->icd;
845
846         switch (icd->current_fmt->host_fmt->fourcc) {
847         case V4L2_PIX_FMT_YUV420:
848         case V4L2_PIX_FMT_YVU420:
849                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_BASE_ADDRESS_U,
850                              buf->buffer_addr_u);
851                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_START_ADDRESS_U,
852                              buf->start_addr_u);
853
854                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_BASE_ADDRESS_V,
855                              buf->buffer_addr_v);
856                 TC_VI_REG_WT(cam, TEGRA_VI_VB0_START_ADDRESS_V,
857                              buf->start_addr_v);
858
859         case V4L2_PIX_FMT_UYVY:
860         case V4L2_PIX_FMT_VYUY:
861         case V4L2_PIX_FMT_YUYV:
862         case V4L2_PIX_FMT_YVYU:
863         case V4L2_PIX_FMT_SBGGR8:
864         case V4L2_PIX_FMT_SGBRG8:
865         case V4L2_PIX_FMT_SBGGR10:
866         case V4L2_PIX_FMT_RGB32:
867                 /* output 1 */
868                 if (buf->output_channel == 0) {
869                         TC_VI_REG_WT(cam, TEGRA_VI_VB0_BASE_ADDRESS_FIRST,
870                                         buf->buffer_addr);
871                         TC_VI_REG_WT(cam, TEGRA_VI_VB0_START_ADDRESS_FIRST,
872                                         buf->start_addr);
873                 /* output 2 */
874                 } else if (buf->output_channel == 1) {
875                         TC_VI_REG_WT(cam, TEGRA_VI_VB0_BASE_ADDRESS_SECOND,
876                                         buf->buffer_addr);
877                         TC_VI_REG_WT(cam, TEGRA_VI_VB0_START_ADDRESS_SECOND,
878                                         buf->start_addr);
879                 } else {
880                         dev_err(&cam->ndev->dev, "Wrong output channel %d\n",
881                                 buf->output_channel);
882                         return -EINVAL;
883                 }
884         break;
885
886         default:
887                 dev_err(&cam->ndev->dev, "Wrong host format %d\n",
888                         icd->current_fmt->host_fmt->fourcc);
889                 return -EINVAL;
890         }
891
892         return 0;
893 }
894
895 static int vi_capture_start(struct tegra_camera_dev *cam,
896                                       struct tegra_camera_buffer *buf)
897 {
898         struct soc_camera_device *icd = buf->icd;
899         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
900         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
901         int port = pdata->port;
902         int err;
903
904         err = vi_capture_buffer_setup(cam, buf);
905         if (err < 0)
906                 return err;
907         /*
908          * Only wait on CSI frame end syncpt if we're using CSI.  Otherwise,
909          * wait on VIP VSYNC syncpt.
910          */
911         if (port == TEGRA_CAMERA_PORT_CSI_A) {
912                 cam->syncpt_csi_a++;
913                 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
914                                 0x0000f005);
915                 err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
916                                 cam->syncpt_id_csi_a,
917                                 cam->syncpt_csi_a,
918                                 TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
919                                 NULL,
920                                 NULL);
921         } else if (port == TEGRA_CAMERA_PORT_CSI_B) {
922                 cam->syncpt_csi_b++;
923                 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
924                                 0x0000f005);
925                 err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
926                                 cam->syncpt_id_csi_b,
927                                 cam->syncpt_csi_b,
928                                 TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
929                                 NULL,
930                                 NULL);
931         } else {
932                 cam->syncpt_vip++;
933                 TC_VI_REG_WT(cam, TEGRA_VI_CAMERA_CONTROL,
934                                 0x00000001);
935                 err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
936                                 cam->syncpt_id_vip,
937                                 cam->syncpt_csi_a,
938                                 TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
939                                 NULL,
940                                 NULL);
941         }
942
943         if (!err)
944                 return 0;
945
946         if (vi_port_is_csi(port)) {
947                 u32 ppstatus;
948                 u32 cilstatus;
949                 u32 rostatus;
950
951                 dev_warn(&icd->vdev->dev, "Timeout on CSI syncpt\n");
952                 dev_warn(&icd->vdev->dev, "buffer_addr = 0x%08x\n",
953                         buf->buffer_addr);
954
955                 ppstatus = TC_VI_REG_RD(cam,
956                         TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
957                 cilstatus = TC_VI_REG_RD(cam,
958                          TEGRA_CSI_CSI_CIL_STATUS);
959                 rostatus = TC_VI_REG_RD(cam,
960                         TEGRA_CSI_CSI_READONLY_STATUS);
961
962                 dev_warn(&icd->vdev->dev,
963                         "PPSTATUS = 0x%08x, "
964                         "CILSTATUS = 0x%08x, "
965                         "ROSTATUS = 0x%08x\n",
966                         ppstatus, cilstatus, rostatus);
967         } else {
968                 u32 vip_input_status;
969
970                 dev_warn(&cam->ndev->dev, "Timeout on VI syncpt\n");
971                 dev_warn(&cam->ndev->dev, "buffer_addr = 0x%08x\n",
972                         buf->buffer_addr);
973
974                 vip_input_status = TC_VI_REG_RD(cam,
975                         TEGRA_VI_VIP_INPUT_STATUS);
976
977                 dev_warn(&cam->ndev->dev,
978                         "VIP_INPUT_STATUS = 0x%08x\n",
979                         vip_input_status);
980         }
981
982         return err;
983 }
984
985 static int vi_capture_stop(struct tegra_camera_dev *cam, int port)
986 {
987         int err = 0;
988
989         if (vi_port_is_csi(port))
990                 err = nvhost_syncpt_wait_timeout_ext(cam->ndev,
991                         cam->syncpt_id_vip,
992                         cam->syncpt_vip,
993                         TEGRA_SYNCPT_VI_WAIT_TIMEOUT,
994                         NULL,
995                         NULL);
996
997         if (err) {
998                 u32 buffer_addr;
999                 u32 ppstatus;
1000                 u32 cilstatus;
1001
1002                 dev_warn(&cam->ndev->dev, "Timeout on VI syncpt\n");
1003
1004                 buffer_addr = TC_VI_REG_RD(cam,
1005                                            TEGRA_VI_VB0_BASE_ADDRESS_FIRST);
1006                 dev_warn(&cam->ndev->dev, "buffer_addr = 0x%08x\n",
1007                         buffer_addr);
1008
1009                 ppstatus = TC_VI_REG_RD(cam,
1010                                         TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
1011                 cilstatus = TC_VI_REG_RD(cam,
1012                                          TEGRA_CSI_CSI_CIL_STATUS);
1013                 dev_warn(&cam->ndev->dev,
1014                         "PPSTATUS = 0x%08x, CILSTATUS = 0x%08x\n",
1015                         ppstatus, cilstatus);
1016         }
1017
1018         return err;
1019 }
1020
1021 static void vi_unpowergate(struct tegra_camera_dev *cam)
1022 {
1023         /*
1024          * Powergating DIS must powergate VE partition. Camera
1025          * module needs to increase the ref-count of disa to
1026          * avoid itself powergated by DIS inadvertently.
1027          */
1028 #if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
1029         tegra_unpowergate_partition(TEGRA_POWERGATE_DISA);
1030 #endif
1031 }
1032
1033 static void vi_powergate(struct tegra_camera_dev *cam)
1034 {
1035 #if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
1036         tegra_powergate_partition(TEGRA_POWERGATE_DISA);
1037 #endif
1038 }
1039
1040 struct tegra_camera_ops vi_ops = {
1041         .clks_init = vi_clks_init,
1042         .clks_deinit = vi_clks_deinit,
1043         .clks_enable = vi_clks_enable,
1044         .clks_disable = vi_clks_disable,
1045
1046         .capture_clean = vi_capture_clean,
1047         .capture_setup = vi_capture_setup,
1048         .capture_start = vi_capture_start,
1049         .capture_stop = vi_capture_stop,
1050
1051         .activate = vi_unpowergate,
1052         .deactivate = vi_powergate,
1053
1054         .init_syncpts = vi_init_syncpts,
1055         .free_syncpts = vi_free_syncpts,
1056         .save_syncpts = vi_save_syncpts,
1057         .incr_syncpts = vi_incr_syncpts,
1058
1059         .port_is_valid = vi_port_is_valid,
1060 };
1061
1062 int vi_register(struct tegra_camera_dev *cam)
1063 {
1064         /* Init regulator */
1065 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
1066         cam->regulator_name = "vcsi";
1067 #else
1068         cam->regulator_name = "avdd_dsi_csi";
1069 #endif
1070
1071         /* Init VI/CSI ops */
1072         cam->ops = &vi_ops;
1073
1074         return 0;
1075 }