]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/media/platform/soc_camera/tegra_camera/vi2.c
media: tegra_v4l2_camera: set clock rate for pll_d
[sojka/nv-tegra/linux-3.10.git] / drivers / media / platform / soc_camera / tegra_camera / vi2.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_CSI_WAIT_TIMEOUT                   200
31
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
62
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
93
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
124
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
148
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
158
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
168
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
178
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
188
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
197
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
207
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
217
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
228
229 static int vi2_port_is_valid(int port)
230 {
231         return (((port) >= TEGRA_CAMERA_PORT_CSI_A) &&
232                 ((port) <= TEGRA_CAMERA_PORT_CSI_E));
233 }
234
235 /* Clock settings for camera */
236 static struct tegra_camera_clk vi2_clks0[] = {
237         {
238                 .name = "vi",
239                 .freq = 408000000,
240                 .use_devname = 1,
241         },
242         {
243                 .name = "vi_sensor",
244                 .freq = 24000000,
245         },
246         {
247                 .name = "csi",
248                 .freq = 408000000,
249                 .use_devname = 1,
250         },
251         {
252                 .name = "isp",
253                 .freq = 0,
254         },
255         {
256                 .name = "csus",
257                 .freq = 0,
258                 .use_devname = 1,
259         },
260         {
261                 .name = "sclk",
262                 .freq = 80000000,
263         },
264         {
265                 .name = "emc",
266                 .freq = 300000000,
267         },
268         {
269                 .name = "cilab",
270                 .freq = 102000000,
271                 .use_devname = 1,
272         },
273         /* Always put "p11_d" at the end */
274         {
275                 .name = "pll_d",
276                 .freq = 927000000,
277         },
278 };
279
280 static struct tegra_camera_clk vi2_clks1[] = {
281         {
282                 .name = "vi",
283                 .freq = 408000000,
284                 .use_devname = 1,
285         },
286         {
287                 .name = "vi_sensor",
288                 .freq = 24000000,
289         },
290         {
291                 .name = "csi",
292                 .freq = 408000000,
293                 .use_devname = 1,
294         },
295         {
296                 .name = "isp",
297                 .freq = 0,
298         },
299         {
300                 .name = "sclk",
301                 .freq = 80000000,
302         },
303         {
304                 .name = "emc",
305                 .freq = 300000000,
306         },
307         {
308                 .name = "cilcd",
309                 .freq = 0,
310                 .use_devname = 1,
311         },
312         {
313                 .name = "cile",
314                 .freq = 0,
315                 .use_devname = 1,
316         },
317         /* Always put "p11_d" at the end */
318         {
319                 .name = "pll_d",
320                 .freq = 927000000,
321         },
322 };
323
324 #define MAX_DEVID_LENGTH        16
325
326 static int vi2_clks_init(struct tegra_camera_dev *cam)
327 {
328         struct platform_device *pdev = cam->ndev;
329         struct tegra_camera_clk *clks;
330         int i;
331
332         switch (pdev->id) {
333         case 0:
334                 cam->num_clks = ARRAY_SIZE(vi2_clks0);
335                 cam->clks = vi2_clks0;
336                 break;
337         case 1:
338                 cam->num_clks = ARRAY_SIZE(vi2_clks1);
339                 cam->clks = vi2_clks1;
340                 break;
341         default:
342                 dev_err(&pdev->dev, "Wrong device ID %d\n", pdev->id);
343                 return -ENODEV;
344         }
345
346         for (i = 0; i < cam->num_clks; i++) {
347                 clks = &cam->clks[i];
348
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);
354                 } else
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",
358                                 clks->name);
359                         return PTR_ERR(clks->clk);
360                 }
361         }
362
363         return 0;
364 }
365
366 static void vi2_clks_deinit(struct tegra_camera_dev *cam)
367 {
368         struct tegra_camera_clk *clks;
369         int i;
370
371         for (i = 0; i < cam->num_clks; i++) {
372                 clks = &cam->clks[i];
373                 if (clks->clk)
374                         clk_put(clks->clk);
375         }
376 }
377
378 static void vi2_clks_enable(struct tegra_camera_dev *cam)
379 {
380         struct tegra_camera_clk *clks;
381         int i;
382
383         for (i = 0; i < cam->num_clks - 1; i++) {
384                 clks = &cam->clks[i];
385                 if (clks->clk)
386                         clk_prepare_enable(clks->clk);
387                 if (clks->freq > 0)
388                         clk_set_rate(clks->clk, clks->freq);
389         }
390
391         if (cam->tpg_mode) {
392                 clks = &cam->clks[i];
393                 if (clks->clk) {
394                         clk_prepare_enable(clks->clk);
395                         if (clks->freq > 0)
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);
403                 }
404         }
405 }
406
407 static void vi2_clks_disable(struct tegra_camera_dev *cam)
408 {
409         struct tegra_camera_clk *clks;
410         int i;
411
412         for (i = 0; i < cam->num_clks - 1; i++) {
413                 clks = &cam->clks[i];
414                 if (clks->clk)
415                         clk_disable_unprepare(clks->clk);
416         }
417
418         if (cam->tpg_mode) {
419                 clks = &cam->clks[i];
420                 if (clks->clk) {
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);
428                 }
429         }
430 }
431
432 static void vi2_init_syncpts(struct tegra_camera_dev *cam)
433 {
434         cam->syncpt_id_csi_a = nvhost_get_syncpt_client_managed("vi_csi_A");
435
436         cam->syncpt_id_csi_b = nvhost_get_syncpt_client_managed("vi_csi_B");
437 }
438
439 static void vi2_free_syncpts(struct tegra_camera_dev *cam)
440 {
441         nvhost_free_syncpt(cam->syncpt_id_csi_a);
442
443         nvhost_free_syncpt(cam->syncpt_id_csi_b);
444 }
445
446 static void vi2_incr_syncpts(struct tegra_camera_dev *cam)
447 {
448         u32 val;
449
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);
454
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);
459 }
460
461 static void vi2_capture_clean(struct tegra_camera_dev *cam)
462 {
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);
477 }
478
479 static int vi2_capture_setup_csi_0(struct tegra_camera_dev *cam,
480                                     struct soc_camera_device *icd)
481 {
482         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
483         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
484
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);
491
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);
496         else
497                 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22020201);
498
499         if (cam->tpg_mode) {
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);
510
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);
515
516                 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
517                                 icd->user_width * 3);
518         } else {
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);
523
524                 TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE_WC,
525                                 icd->user_width * 10 / 8);
526         }
527
528         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_CSI_IMAGE_SIZE,
529                         (icd->user_height << 16) | icd->user_width);
530
531         return 0;
532 }
533
534 static int vi2_capture_setup_csi_1(struct tegra_camera_dev *cam,
535                                      struct soc_camera_device *icd)
536 {
537         struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc;
538         struct tegra_camera_platform_data *pdata = ssdesc->drv_priv;
539
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);
546
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);
553         else
554                 TC_VI_REG_WT(cam, TEGRA_CSI_PHY_CIL_COMMAND, 0x22010202);
555
556         if (cam->tpg_mode) {
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);
567
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);
572         }
573
574         TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE,
575                      (icd->user_height << 16) | icd->user_width);
576
577         TC_VI_REG_WT(cam, TEGRA_VI_CSI_1_CSI_IMAGE_SIZE_WC,
578                      icd->user_width * 3);
579
580         return 0;
581 }
582
583 static int vi2_capture_setup(struct tegra_camera_dev *cam)
584 {
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;
591
592         /* Skip VI2/CSI2 setup for second and later frame capture */
593         if (!cam->sof)
594                 return 0;
595
596 #ifdef DEBUG
597         TC_VI_REG_WT(cam, TEGRA_CSI_DEBUG_CONTROL,
598                         0x3 | (0x1 << 5) | (0x40 << 8));
599 #endif
600
601         /*
602          * PAD_CILA_PDVCLAMP 0, PAD_CILA_PDIO_CLK 0,
603          * PAD_CILA_PDIO 0, PAD_AB_BK_MODE 1
604          */
605         TC_VI_REG_WT(cam, TEGRA_CSI_CILA_PAD_CONFIG0, 0x10000);
606
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);
609
610         /*
611          * PAD_CILC_PDVCLAMP 0, PAD_CILC_PDIO_CLK 0,
612          * PAD_CILC_PDIO 0, PAD_CD_BK_MODE 1
613          */
614         TC_VI_REG_WT(cam, TEGRA_CSI_CILC_PAD_CONFIG0, 0x10000);
615
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);
618
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);
621
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);
630
631         /*
632          * TODO: these values should be different with different
633          * sensor connected.
634          * Hardcode THS settle value just for TPG testing
635          */
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);
641
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);
647         else
648                 return -ENODEV;
649 }
650
651 static int vi2_capture_buffer_setup(struct tegra_camera_dev *cam,
652                         struct tegra_camera_buffer *buf)
653 {
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);
657
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 */
662
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) {
673                 case 0:
674                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_OFFSET_MSB,
675                                      0x0);
676                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_OFFSET_LSB,
677                                      buf->buffer_addr);
678                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE0_STRIDE,
679                                      bytes_per_line);
680                         break;
681                 case 1:
682                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_OFFSET_MSB,
683                                      0x0);
684                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_OFFSET_LSB,
685                                      buf->buffer_addr);
686                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE1_STRIDE,
687                                      bytes_per_line);
688                         break;
689                 case 2:
690                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_OFFSET_MSB,
691                                      0x0);
692                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_OFFSET_LSB,
693                                      buf->buffer_addr);
694                         TC_VI_REG_WT(cam, TEGRA_VI_CSI_0_SURFACE2_STRIDE,
695                                      bytes_per_line);
696                         break;
697                 }
698                 break;
699
700         default:
701                 dev_err(&cam->ndev->dev, "Wrong host format %d\n",
702                         icd->current_fmt->host_fmt->fourcc);
703                 return -EINVAL;
704         }
705
706         return 0;
707 }
708
709 static int vi2_capture_error_status(struct tegra_camera_dev *cam)
710 {
711         int err;
712
713 #ifdef DEBUG
714         err = TC_VI_REG_RD(cam, TEGRA_CSI_DEBUG_COUNTER_0);
715         if (err)
716                 pr_err("TEGRA_CSI_DEBUG_COUNTER_0 0x%08x\n", err);
717 #endif
718         err = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
719         if (err)
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);
722         if (err)
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);
725         if (err)
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);
728         if (err)
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);
731         if (err)
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);
734         if (err)
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);
737         if (err)
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);
740         if (err)
741                 pr_err("TEGRA_VI_CSI_0_ERROR_STATUS 0x%08x\n", err);
742
743         return err;
744 }
745
746 static int vi2_capture_start(struct tegra_camera_dev *cam,
747                                       struct tegra_camera_buffer *buf)
748 {
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;
753         int err;
754
755         err = vi2_capture_buffer_setup(cam, buf);
756         if (err < 0)
757                 return err;
758
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,
764                                 0x0000f005);
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,
768                                 cam->syncpt_csi_a,
769                                 TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
770                                 NULL,
771                                 NULL);
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,
776                                 0x0000f005);
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,
780                                 cam->syncpt_csi_b,
781                                 TEGRA_SYNCPT_CSI_WAIT_TIMEOUT,
782                                 NULL,
783                                 NULL);
784         }
785
786         /* Mark SOF flag to Zero after we captured the FIRST frame */
787         if (cam->sof)
788                 cam->sof = 0;
789
790         /* Capture syncpt timeout err, then dump error status */
791         if (err)
792                 err = vi2_capture_error_status(cam);
793
794         return err;
795 }
796
797 static int vi2_capture_stop(struct tegra_camera_dev *cam, int port)
798 {
799         if (port == TEGRA_CAMERA_PORT_CSI_A)
800                 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND,
801                              0x0000f002);
802         else if (port == TEGRA_CAMERA_PORT_CSI_B)
803                 TC_VI_REG_WT(cam, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND,
804                              0x0000f002);
805
806         return 0;
807 }
808
809 /* Reset VI2/CSI2 when activating, no sepecial ops for deactiving  */
810 static void vi2_sw_reset(struct tegra_camera_dev *cam)
811 {
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);
816
817         udelay(10);
818 }
819
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,
825
826         .capture_clean = vi2_capture_clean,
827         .capture_setup = vi2_capture_setup,
828         .capture_start = vi2_capture_start,
829         .capture_stop = vi2_capture_stop,
830
831         .activate = vi2_sw_reset,
832
833         .init_syncpts = vi2_init_syncpts,
834         .free_syncpts = vi2_free_syncpts,
835         .incr_syncpts = vi2_incr_syncpts,
836
837         .port_is_valid = vi2_port_is_valid,
838 };
839
840 int vi2_register(struct tegra_camera_dev *cam)
841 {
842         /* Init regulator */
843         cam->regulator_name = "avdd_dsi_csi";
844
845         /* Init VI2/CSI2 ops */
846         cam->ops = &vi2_ops;
847
848         return 0;
849 }