summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/tegra')
-rw-r--r--drivers/media/platform/tegra/Makefile12
-rw-r--r--drivers/media/platform/tegra/camera/Makefile10
-rw-r--r--drivers/media/platform/tegra/camera/camera_common.c858
-rw-r--r--drivers/media/platform/tegra/camera/camera_gpio.c160
-rw-r--r--drivers/media/platform/tegra/camera/camera_gpio.h30
-rw-r--r--drivers/media/platform/tegra/camera/csi/Makefile8
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi.c784
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi.h158
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi2_fops.c455
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi2_fops.h27
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi4_fops.c506
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi4_fops.h41
-rw-r--r--drivers/media/platform/tegra/camera/csi/csi4_registers.h196
-rw-r--r--drivers/media/platform/tegra/camera/sensor_common.c329
-rw-r--r--drivers/media/platform/tegra/camera/vi/Makefile21
-rw-r--r--drivers/media/platform/tegra/camera/vi/capture.c880
-rw-r--r--drivers/media/platform/tegra/camera/vi/channel.c1650
-rw-r--r--drivers/media/platform/tegra/camera/vi/core.c173
-rw-r--r--drivers/media/platform/tegra/camera/vi/core.h127
-rw-r--r--drivers/media/platform/tegra/camera/vi/graph.c602
-rw-r--r--drivers/media/platform/tegra/camera/vi/mc_common.c346
-rw-r--r--drivers/media/platform/tegra/camera/vi/mc_common.h352
-rw-r--r--drivers/media/platform/tegra/camera/vi/registers.h223
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi2_fops.c825
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi2_fops.h34
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi2_formats.h131
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi4_fops.c1056
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi4_fops.h37
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi4_formats.h140
-rw-r--r--drivers/media/platform/tegra/camera/vi/vi4_registers.h272
-rw-r--r--drivers/media/platform/tegra/mipical/Kconfig11
-rw-r--r--drivers/media/platform/tegra/mipical/Makefile6
-rw-r--r--drivers/media/platform/tegra/mipical/mipi_cal.c1096
-rw-r--r--drivers/media/platform/tegra/mipical/mipi_cal.h50
-rw-r--r--drivers/media/platform/tegra/mipical/registers.h99
-rw-r--r--drivers/media/platform/tegra/mipical/vmipi/vmipi.c246
-rw-r--r--drivers/media/platform/tegra/mipical/vmipi/vmipi.h66
-rw-r--r--drivers/media/platform/tegra/regmap_util.c173
-rw-r--r--drivers/media/platform/tegra/tpg/Makefile14
-rw-r--r--drivers/media/platform/tegra/tpg/tpg_t18x.c199
-rw-r--r--drivers/media/platform/tegra/tpg/tpg_t21x.c210
-rw-r--r--drivers/media/platform/tegra/vi/Makefile17
-rw-r--r--drivers/media/platform/tegra/vi/tegra_vi.c515
-rw-r--r--drivers/media/platform/tegra/vi/vi.c611
-rw-r--r--drivers/media/platform/tegra/vi/vi.h128
-rw-r--r--drivers/media/platform/tegra/vi/vi_irq.c244
-rw-r--r--drivers/media/platform/tegra/vi/vi_irq.h26
47 files changed, 14154 insertions, 0 deletions
diff --git a/drivers/media/platform/tegra/Makefile b/drivers/media/platform/tegra/Makefile
new file mode 100644
index 000000000..414f22f69
--- /dev/null
+++ b/drivers/media/platform/tegra/Makefile
@@ -0,0 +1,12 @@
1GCOV_PROFILE := y
2
3#subdir-ccflags-y := -Werror
4#
5# Makefile for the video capture/playback device drivers.
6#
7obj-y += camera/
8obj-y += vi/
9obj-$(CONFIG_VIDEO_CAMERA) += regmap_util.o
10obj-$(CONFIG_VIDEO_TEGRA_VI_TPG) += tpg/
11
12obj-$(CONFIG_TEGRA_MIPI_CAL) += mipical/
diff --git a/drivers/media/platform/tegra/camera/Makefile b/drivers/media/platform/tegra/camera/Makefile
new file mode 100644
index 000000000..8474f451a
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/Makefile
@@ -0,0 +1,10 @@
1GCOV_PROFILE := y
2obj-y += vi/
3obj-y += csi/
4ccflags-y += -I../nvhost/drivers/video/tegra/host
5ccflags-y += -Idrivers/video/tegra/host
6ccflags-y += -Idrivers/video/tegra/camera
7ccflags-y += -Idrivers/media/platform/tegra
8ccflags-y += -Werror
9
10obj-y += camera_common.o camera_gpio.o sensor_common.o
diff --git a/drivers/media/platform/tegra/camera/camera_common.c b/drivers/media/platform/tegra/camera/camera_common.c
new file mode 100644
index 000000000..17a253640
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/camera_common.c
@@ -0,0 +1,858 @@
1/*
2 * camera_common.c - utilities for tegra camera driver
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18#include <media/camera_common.h>
19#include <linux/of_graph.h>
20#include <linux/string.h>
21#include <soc/tegra/pmc.h>
22#include "camera/vi/mc_common.h"
23
24#define has_s_op(master, op) \
25 (master->ops && master->ops->op)
26#define call_s_op(master, op) \
27 (has_s_op(master, op) ? \
28 master->ops->op(master) : 0)
29#define call_s_ops(master, op, ...) \
30 (has_s_op(master, op) ? \
31 master->ops->op(master, __VA_ARGS__) : 0)
32
33static const struct camera_common_colorfmt camera_common_color_fmts[] = {
34 {
35 MEDIA_BUS_FMT_SRGGB12_1X12,
36 V4L2_COLORSPACE_SRGB,
37 V4L2_PIX_FMT_SRGGB12,
38 },
39 {
40 MEDIA_BUS_FMT_SRGGB10_1X10,
41 V4L2_COLORSPACE_SRGB,
42 V4L2_PIX_FMT_SRGGB10,
43 },
44 {
45 MEDIA_BUS_FMT_SBGGR10_1X10,
46 V4L2_COLORSPACE_SRGB,
47 V4L2_PIX_FMT_SBGGR10,
48 },
49 {
50 MEDIA_BUS_FMT_SRGGB8_1X8,
51 V4L2_COLORSPACE_SRGB,
52 V4L2_PIX_FMT_SRGGB8,
53 },
54 /*
55 * The below two formats are not supported by VI4,
56 * keep them at the last to ensure they get discarded
57 */
58 {
59 MEDIA_BUS_FMT_XRGGB10P_3X10,
60 V4L2_COLORSPACE_SRGB,
61 V4L2_PIX_FMT_XRGGB10P,
62 },
63 {
64 MEDIA_BUS_FMT_XBGGR10P_3X10,
65 V4L2_COLORSPACE_SRGB,
66 V4L2_PIX_FMT_XRGGB10P,
67 },
68};
69
70static const char *camera_common_csi_io_pads[] = {
71 "csia",
72 "csib",
73 "csic",
74 "csid",
75 "csie",
76 "csif",
77};
78
79bool camera_common_verify_code(struct tegra_channel *chan, unsigned int code)
80{
81 int i;
82
83 for (i = 0; i < chan->num_video_formats; i++) {
84 if (chan->video_formats[i]->code == code)
85 return true;
86 }
87
88 return false;
89}
90
91int camera_common_g_ctrl(struct camera_common_data *s_data,
92 struct v4l2_control *control)
93{
94 int i;
95
96 for (i = 0; i < s_data->numctrls; i++) {
97 if (s_data->ctrls[i]->id == control->id) {
98 control->value = s_data->ctrls[i]->val;
99 dev_dbg(&s_data->i2c_client->dev,
100 "%s: found control %s\n", __func__,
101 s_data->ctrls[i]->name);
102 return 0;
103 }
104 }
105
106 return -EFAULT;
107}
108
109int camera_common_regulator_get(struct i2c_client *client,
110 struct regulator **vreg, const char *vreg_name)
111{
112 struct regulator *reg = NULL;
113 int err = 0;
114
115 reg = devm_regulator_get(&client->dev, vreg_name);
116 if (unlikely(IS_ERR(reg))) {
117 dev_err(&client->dev, "%s %s ERR: %p\n",
118 __func__, vreg_name, reg);
119 err = PTR_ERR(reg);
120 reg = NULL;
121 } else
122 dev_dbg(&client->dev, "%s: %s\n",
123 __func__, vreg_name);
124
125 *vreg = reg;
126 return err;
127}
128
129int camera_common_parse_clocks(struct i2c_client *client,
130 struct camera_common_pdata *pdata)
131{
132 struct device_node *np = client->dev.of_node;
133 const char *prop;
134 int proplen = 0;
135 int i = 0;
136 int numclocks = 0;
137 int mclk_index = 0;
138 int parentclk_index = -1;
139 int err = 0;
140
141
142 pdata->mclk_name = NULL;
143 pdata->parentclk_name = NULL;
144 err = of_property_read_string(np, "mclk", &pdata->mclk_name);
145 if (!err) {
146 dev_dbg(&client->dev, "mclk in DT %s\n", pdata->mclk_name);
147 of_property_read_string(np, "parent-clk",
148 &pdata->parentclk_name);
149 return 0;
150 }
151
152 prop = (const char *)of_get_property(np, "clock-names", &proplen);
153 if (!prop)
154 return -ENODATA;
155
156 /* find length of clock-names string array */
157 for (i = 0; i < proplen; i++) {
158 if (prop[i] == '\0')
159 numclocks++;
160 }
161
162 if (numclocks > 1) {
163 err = of_property_read_u32(np, "mclk-index", &mclk_index);
164 if (err) {
165 dev_err(&client->dev, "Failed to find mclk index\n");
166 return err;
167 }
168 err = of_property_read_u32(np, "parent-clk-index",
169 &parentclk_index);
170 }
171
172 for (i = 0; i < numclocks; i++) {
173 if (i == mclk_index) {
174 pdata->mclk_name = prop;
175 dev_dbg(&client->dev, "%s: mclk_name is %s\n",
176 __func__, pdata->mclk_name);
177 } else if (i == parentclk_index) {
178 pdata->parentclk_name = prop;
179 dev_dbg(&client->dev, "%s: parentclk_name is %s\n",
180 __func__, pdata->parentclk_name);
181 } else
182 dev_dbg(&client->dev, "%s: %s\n", __func__, prop);
183 prop += strlen(prop) + 1;
184 }
185
186 return 0;
187}
188
189int camera_common_parse_ports(struct i2c_client *client,
190 struct camera_common_data *s_data)
191{
192 struct device_node *node = client->dev.of_node;
193 struct device_node *ep = NULL;
194 struct device_node *next;
195 int bus_width = 0;
196 int err = 0;
197 int port = 0;
198
199 /* Parse all the remote entities and put them into the list */
200 next = of_graph_get_next_endpoint(node, ep);
201 if (!next)
202 return -ENODATA;
203
204 of_node_put(ep);
205 ep = next;
206
207 err = of_property_read_u32(ep, "bus-width", &bus_width);
208 if (err) {
209 dev_err(&client->dev,
210 "Failed to find num of lanes\n");
211 return err;
212 }
213 s_data->numlanes = bus_width;
214
215 err = of_property_read_u32(ep, "csi-port", &port);
216 if (err) {
217 dev_err(&client->dev,
218 "Failed to find CSI port\n");
219 return err;
220 }
221 s_data->csi_port = port;
222
223 dev_dbg(&client->dev, "%s: csi port %d num of lanes %d\n",
224 __func__, s_data->csi_port, s_data->numlanes);
225
226 return 0;
227}
228
229int camera_common_debugfs_show(struct seq_file *s, void *unused)
230{
231 struct camera_common_data *s_data = s->private;
232
233 dev_dbg(&s_data->i2c_client->dev, "%s: ++\n", __func__);
234
235 return 0;
236}
237
238ssize_t camera_common_debugfs_write(
239 struct file *file,
240 char const __user *buf,
241 size_t count,
242 loff_t *offset)
243{
244 struct camera_common_data *s_data =
245 ((struct seq_file *)file->private_data)->private;
246 struct i2c_client *client = s_data->i2c_client;
247 int err = 0;
248 char buffer[MAX_BUFFER_SIZE];
249 u32 address;
250 u32 data;
251 u8 readback = 0;
252
253 dev_dbg(&client->dev, "%s: ++\n", __func__);
254
255 if (copy_from_user(&buffer, buf, sizeof(buffer)))
256 goto debugfs_write_fail;
257
258 if (sscanf(buf, "0x%x 0x%x", &address, &data) == 2)
259 goto set_attr;
260 if (sscanf(buf, "0X%x 0X%x", &address, &data) == 2)
261 goto set_attr;
262 if (sscanf(buf, "%d %d", &address, &data) == 2)
263 goto set_attr;
264
265 if (sscanf(buf, "0x%x 0x%x", &address, &data) == 1)
266 goto read;
267 if (sscanf(buf, "0X%x 0X%x", &address, &data) == 1)
268 goto read;
269 if (sscanf(buf, "%d %d", &address, &data) == 1)
270 goto read;
271
272 dev_err(&client->dev, "SYNTAX ERROR: %s\n", buf);
273 return -EFAULT;
274
275set_attr:
276 dev_dbg(&client->dev,
277 "new address = %x, data = %x\n", address, data);
278 err |= call_s_ops(s_data, write_reg, address, data);
279read:
280 err |= call_s_ops(s_data, read_reg, address, &readback);
281 dev_dbg(&client->dev,
282 "wrote to address 0x%x with value 0x%x\n",
283 address, readback);
284
285 if (err)
286 goto debugfs_write_fail;
287
288 return count;
289
290debugfs_write_fail:
291 dev_err(&client->dev,
292 "%s: test pattern write failed\n", __func__);
293 return -EFAULT;
294}
295
296int camera_common_debugfs_open(struct inode *inode, struct file *file)
297{
298 struct camera_common_data *s_data = inode->i_private;
299 struct i2c_client *client = s_data->i2c_client;
300
301 dev_dbg(&client->dev, "%s: ++\n", __func__);
302
303 return single_open(file, camera_common_debugfs_show, inode->i_private);
304}
305
306static const struct file_operations camera_common_debugfs_fops = {
307 .open = camera_common_debugfs_open,
308 .read = seq_read,
309 .write = camera_common_debugfs_write,
310 .llseek = seq_lseek,
311 .release = single_release,
312};
313
314void camera_common_remove_debugfs(
315 struct camera_common_data *s_data)
316{
317 struct i2c_client *client = s_data->i2c_client;
318
319 dev_dbg(&client->dev, "%s: ++\n", __func__);
320
321 debugfs_remove_recursive(s_data->debugdir);
322 s_data->debugdir = NULL;
323}
324
325void camera_common_create_debugfs(
326 struct camera_common_data *s_data,
327 const char *name)
328{
329 struct dentry *err;
330 struct i2c_client *client = s_data->i2c_client;
331
332 dev_dbg(&client->dev, "%s %s\n", __func__, name);
333
334 s_data->debugdir =
335 debugfs_create_dir(name, NULL);
336 if (!s_data->debugdir)
337 goto remove_debugfs;
338
339 err = debugfs_create_file("d",
340 S_IWUSR | S_IRUGO,
341 s_data->debugdir, s_data,
342 &camera_common_debugfs_fops);
343 if (!err)
344 goto remove_debugfs;
345
346 return;
347remove_debugfs:
348 dev_err(&client->dev, "couldn't create debugfs\n");
349 camera_common_remove_debugfs(s_data);
350}
351
352/* Find a data format by a pixel code in an array */
353const struct camera_common_colorfmt *camera_common_find_datafmt(
354 unsigned int code)
355{
356 int i;
357
358 for (i = 0; i < ARRAY_SIZE(camera_common_color_fmts); i++)
359 if (camera_common_color_fmts[i].code == code)
360 return camera_common_color_fmts + i;
361
362 return NULL;
363}
364EXPORT_SYMBOL(camera_common_find_datafmt);
365
366int camera_common_enum_mbus_code(struct v4l2_subdev *sd,
367 struct v4l2_subdev_pad_config *cfg,
368 struct v4l2_subdev_mbus_code_enum *code)
369{
370 struct i2c_client *client = v4l2_get_subdevdata(sd);
371 struct camera_common_data *s_data = to_camera_common_data(client);
372 struct tegra_channel *chan = v4l2_get_subdev_hostdata(sd);
373 unsigned int mbus_code;
374
375 if (s_data->num_color_fmts < 1 || !s_data->color_fmts) {
376 s_data->color_fmts = camera_common_color_fmts;
377 s_data->num_color_fmts = ARRAY_SIZE(camera_common_color_fmts);
378 }
379
380 if ((unsigned int)code->index >= s_data->num_color_fmts)
381 return -EINVAL;
382
383 mbus_code = s_data->color_fmts[code->index].code;
384 if (!camera_common_verify_code(chan, mbus_code))
385 return -EINVAL;
386
387 code->code = mbus_code;
388 return 0;
389}
390EXPORT_SYMBOL(camera_common_enum_mbus_code);
391
392int camera_common_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
393 unsigned int *code)
394{
395 struct i2c_client *client = v4l2_get_subdevdata(sd);
396 struct camera_common_data *s_data = to_camera_common_data(client);
397
398 if (s_data->num_color_fmts < 1 || !s_data->color_fmts) {
399 s_data->color_fmts = camera_common_color_fmts;
400 s_data->num_color_fmts = ARRAY_SIZE(camera_common_color_fmts);
401 }
402
403 if ((unsigned int)index >= s_data->num_color_fmts)
404 return -EINVAL;
405 *code = s_data->color_fmts[index].code;
406 return 0;
407}
408
409int camera_common_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
410{
411 struct i2c_client *client = v4l2_get_subdevdata(sd);
412 struct camera_common_data *s_data = to_camera_common_data(client);
413 struct tegra_channel *chan = v4l2_get_subdev_hostdata(sd);
414 struct v4l2_control hdr_control;
415 const struct camera_common_frmfmt *frmfmt = s_data->frmfmt;
416 int hdr_en;
417 int err = 0;
418 int i;
419
420 dev_dbg(&client->dev, "%s: size %i x %i\n", __func__,
421 mf->width, mf->height);
422
423 /* check hdr enable ctrl */
424 hdr_control.id = V4L2_CID_HDR_EN;
425
426 err = v4l2_g_ctrl(s_data->ctrl_handler, &hdr_control);
427 if (err < 0) {
428 dev_err(&client->dev, "could not find device ctrl.\n");
429 return err;
430 }
431
432 hdr_en = switch_ctrl_qmenu[hdr_control.value];
433
434 s_data->mode = s_data->def_mode;
435 s_data->fmt_width = s_data->def_width;
436 s_data->fmt_height = s_data->def_height;
437
438 if (s_data->use_sensor_mode_id &&
439 s_data->sensor_mode_id >= 0 &&
440 s_data->sensor_mode_id < s_data->numfmts) {
441 dev_dbg(&client->dev, "%s: use_sensor_mode_id %d\n",
442 __func__, s_data->sensor_mode_id);
443 s_data->mode = frmfmt[s_data->sensor_mode_id].mode;
444 s_data->fmt_width = mf->width;
445 s_data->fmt_height = mf->height;
446 } else {
447 for (i = 0; i < s_data->numfmts; i++) {
448 if (mf->width == frmfmt[i].size.width &&
449 mf->height == frmfmt[i].size.height &&
450 hdr_en == frmfmt[i].hdr_en) {
451 s_data->mode = frmfmt[i].mode;
452 s_data->fmt_width = mf->width;
453 s_data->fmt_height = mf->height;
454 break;
455 }
456 }
457
458 if (i == s_data->numfmts) {
459 mf->width = s_data->fmt_width;
460 mf->height = s_data->fmt_height;
461 dev_dbg(&client->dev,
462 "%s: invalid resolution supplied to set mode %d %d\n",
463 __func__, mf->width, mf->height);
464 }
465 }
466
467 if (!camera_common_verify_code(chan, mf->code))
468 err = -EINVAL;
469
470 mf->field = V4L2_FIELD_NONE;
471 mf->colorspace = V4L2_COLORSPACE_SRGB;
472
473 return err;
474}
475
476int camera_common_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
477{
478 struct i2c_client *client = v4l2_get_subdevdata(sd);
479 struct camera_common_data *s_data = to_camera_common_data(client);
480 int ret;
481
482 dev_dbg(&client->dev, "%s(%u) size %i x %i\n", __func__,
483 mf->code, mf->width, mf->height);
484
485 /* MIPI CSI could have changed the format, double-check */
486 if (!camera_common_find_datafmt(mf->code))
487 return -EINVAL;
488
489 ret = camera_common_try_fmt(sd, mf);
490
491 s_data->colorfmt = camera_common_find_datafmt(mf->code);
492
493 return ret;
494}
495
496int camera_common_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
497{
498 struct i2c_client *client = v4l2_get_subdevdata(sd);
499 struct camera_common_data *s_data = to_camera_common_data(client);
500 const struct camera_common_colorfmt *fmt = s_data->colorfmt;
501
502 dev_dbg(&client->dev, "%s++\n", __func__);
503
504 mf->code = fmt->code;
505 mf->colorspace = fmt->colorspace;
506 mf->width = s_data->fmt_width;
507 mf->height = s_data->fmt_height;
508 mf->field = V4L2_FIELD_NONE;
509
510 return 0;
511}
512
513static int camera_common_evaluate_color_format(struct v4l2_subdev *sd,
514 int pixelformat)
515{
516 struct i2c_client *client = v4l2_get_subdevdata(sd);
517 struct camera_common_data *s_data = to_camera_common_data(client);
518 int i;
519
520 if (!s_data)
521 return -EINVAL;
522
523 if (s_data->num_color_fmts < 1 || !s_data->color_fmts) {
524 s_data->color_fmts = camera_common_color_fmts;
525 s_data->num_color_fmts = ARRAY_SIZE(camera_common_color_fmts);
526 }
527
528 for (i = 0; i < s_data->num_color_fmts; i++) {
529 if (s_data->color_fmts[i].pix_fmt == pixelformat)
530 break;
531 }
532
533 if (i >= s_data->num_color_fmts)
534 return -EINVAL;
535
536 return 0;
537}
538
539int camera_common_enum_framesizes(struct v4l2_subdev *sd,
540 struct v4l2_subdev_pad_config *cfg,
541 struct v4l2_subdev_frame_size_enum *fse)
542{
543 struct i2c_client *client = v4l2_get_subdevdata(sd);
544 struct camera_common_data *s_data = to_camera_common_data(client);
545 int ret;
546
547 if (!s_data || !s_data->frmfmt)
548 return -EINVAL;
549
550 if (fse->index >= s_data->numfmts)
551 return -EINVAL;
552
553 ret = camera_common_evaluate_color_format(sd, fse->code);
554 if (ret)
555 return ret;
556
557 fse->min_width = fse->max_width =
558 s_data->frmfmt[fse->index].size.width;
559 fse->min_height = fse->max_height =
560 s_data->frmfmt[fse->index].size.height;
561 return 0;
562}
563EXPORT_SYMBOL(camera_common_enum_framesizes);
564
565int camera_common_enum_frameintervals(struct v4l2_subdev *sd,
566 struct v4l2_subdev_pad_config *cfg,
567 struct v4l2_subdev_frame_interval_enum *fie)
568{
569 struct i2c_client *client = v4l2_get_subdevdata(sd);
570 struct camera_common_data *s_data = to_camera_common_data(client);
571 int i, ret;
572
573 if (!s_data || !s_data->frmfmt)
574 return -EINVAL;
575
576 /* Check color format */
577 ret = camera_common_evaluate_color_format(sd, fie->code);
578 if (ret)
579 return ret;
580
581 /* Check resolution sizes */
582 for (i = 0; i < s_data->numfmts; i++) {
583 if (s_data->frmfmt[i].size.width == fie->width &&
584 s_data->frmfmt[i].size.height == fie->height)
585 break;
586 }
587 if (i >= s_data->numfmts)
588 return -EINVAL;
589
590 /* Check index is in the rage of framerates array index */
591 if (fie->index >= s_data->frmfmt[i].num_framerates)
592 return -EINVAL;
593
594 fie->interval.numerator = 1;
595 fie->interval.denominator =
596 s_data->frmfmt[i].framerates[fie->index];
597
598 return 0;
599}
600EXPORT_SYMBOL(camera_common_enum_frameintervals);
601
602static void camera_common_mclk_disable(struct camera_common_data *s_data)
603{
604 struct camera_common_power_rail *pw = s_data->power;
605
606 if (!pw) {
607 dev_err(&s_data->i2c_client->dev, "%s: no device power rail\n",
608 __func__);
609 return;
610 }
611
612 dev_dbg(&s_data->i2c_client->dev, "%s: disable MCLK\n", __func__);
613 clk_disable_unprepare(pw->mclk);
614}
615
616static int camera_common_mclk_enable(struct camera_common_data *s_data)
617{
618 int err;
619 struct camera_common_power_rail *pw = s_data->power;
620 unsigned long mclk_init_rate = s_data->def_clk_freq;
621
622 if (!pw) {
623 dev_err(s_data->dev, "%s: no device power rail\n",
624 __func__);
625 return -ENODEV;
626 }
627
628 dev_dbg(s_data->dev, "%s: enable MCLK with %lu Hz\n",
629 __func__, mclk_init_rate);
630
631 err = clk_set_rate(pw->mclk, mclk_init_rate);
632 if (!err)
633 err = clk_prepare_enable(pw->mclk);
634
635 return err;
636}
637
638void camera_common_dpd_disable(struct camera_common_data *s_data)
639{
640 int i;
641 int io_idx;
642 /* 2 lanes per port, divide by two to get numports */
643 int numports = (s_data->numlanes + 1) >> 1;
644
645 /* disable CSI IOs DPD mode to turn on camera */
646 for (i = 0; i < numports; i++) {
647 io_idx = s_data->csi_port + i;
648 tegra_pmc_io_pad_low_power_disable(
649 camera_common_csi_io_pads[io_idx]);
650 dev_dbg(s_data->dev,
651 "%s: csi %d\n", __func__, io_idx);
652 }
653}
654
655void camera_common_dpd_enable(struct camera_common_data *s_data)
656{
657 int i;
658 int io_idx;
659 /* 2 lanes per port, divide by two to get numports */
660 int numports = (s_data->numlanes + 1) >> 1;
661
662 /* disable CSI IOs DPD mode to turn on camera */
663 for (i = 0; i < numports; i++) {
664 io_idx = s_data->csi_port + i;
665 tegra_pmc_io_pad_low_power_enable(
666 camera_common_csi_io_pads[io_idx]);
667 dev_dbg(s_data->dev,
668 "%s: csi %d\n", __func__, io_idx);
669 }
670}
671
672int camera_common_s_power(struct v4l2_subdev *sd, int on)
673{
674 int err = 0;
675 struct i2c_client *client = v4l2_get_subdevdata(sd);
676 struct camera_common_data *s_data = to_camera_common_data(client);
677
678 if (on) {
679 err = camera_common_mclk_enable(s_data);
680 if (err)
681 return err;
682
683 camera_common_dpd_disable(s_data);
684
685 err = call_s_op(s_data, power_on);
686 if (err) {
687 dev_err(s_data->dev,
688 "%s: error power on\n", __func__);
689 camera_common_dpd_enable(s_data);
690 camera_common_mclk_disable(s_data);
691 }
692 } else {
693 call_s_op(s_data, power_off);
694 camera_common_dpd_enable(s_data);
695 camera_common_mclk_disable(s_data);
696 }
697
698 return err;
699}
700
701int camera_common_g_mbus_config(struct v4l2_subdev *sd,
702 struct v4l2_mbus_config *cfg)
703{
704 cfg->type = V4L2_MBUS_CSI2;
705 cfg->flags = V4L2_MBUS_CSI2_4_LANE |
706 V4L2_MBUS_CSI2_CHANNEL_0 |
707 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
708
709 return 0;
710}
711
712int camera_common_focuser_s_power(struct v4l2_subdev *sd, int on)
713{
714 int err = 0;
715 struct i2c_client *client = v4l2_get_subdevdata(sd);
716 struct camera_common_focuser_data *s_data =
717 to_camera_common_focuser_data(client);
718
719 if (on) {
720 err = call_s_op(s_data, power_on);
721 if (err)
722 dev_err(&s_data->i2c_client->dev,
723 "%s: error power on\n", __func__);
724 } else
725 err = call_s_op(s_data, power_off);
726
727 return err;
728}
729
730int camera_common_focuser_init(struct camera_common_focuser_data *s_data)
731{
732 int err = 0;
733
734 /* power on */
735 err = call_s_op(s_data, power_on);
736 if (err) {
737 dev_err(&s_data->i2c_client->dev,
738 "%s: error power on\n", __func__);
739 return err;
740 }
741
742 /* load default configuration */
743 err = call_s_op(s_data, load_config);
744 if (err) {
745 dev_err(&s_data->i2c_client->dev,
746 "%s: error loading config\n", __func__);
747 goto fail;
748 }
749
750 /* set controls */
751 err = call_s_op(s_data, ctrls_init);
752 if (err)
753 dev_err(&s_data->i2c_client->dev,
754 "%s: error initializing controls\n", __func__);
755
756fail:
757 /* power off */
758 err |= call_s_op(s_data, power_off);
759
760 return err;
761}
762
763int camera_common_parse_sensor_mode(struct i2c_client *client,
764 struct camera_common_pdata *pdata)
765{
766 struct device_node *np = client->dev.of_node;
767 char temp_str[OF_MAX_STR_LEN];
768 const char *str;
769 struct device_node *node;
770 int num_modes = 0;
771 int err, i;
772
773 /* get number of modes */
774 for (i = 0; num_modes < MAX_NUM_SENSOR_MODES; i++) {
775 snprintf(temp_str, sizeof(temp_str), "%s%d",
776 OF_SENSORMODE_PREFIX, i);
777 of_node_get(np);
778 node = of_find_node_by_name(np, temp_str);
779 if (node == NULL)
780 break;
781 num_modes++;
782 }
783
784 pdata->mode_info = devm_kzalloc(&client->dev,
785 num_modes * sizeof(struct camera_common_mode_info),
786 GFP_KERNEL);
787 if (!pdata->mode_info) {
788 dev_err(&client->dev, "Failed to allocate memory for mode info\n");
789 return -ENOMEM;
790 }
791 memset(pdata->mode_info, 0, num_modes *
792 sizeof(struct camera_common_mode_info));
793
794 /* parse mode info */
795 for (i = 0; i < num_modes; i++) {
796 snprintf(temp_str, sizeof(temp_str), "%s%d",
797 OF_SENSORMODE_PREFIX, i);
798 of_node_get(np);
799 node = of_find_node_by_name(np, temp_str);
800 if (node == NULL) {
801 dev_err(&client->dev, "Failed to find mode\n");
802 return -ENODATA;
803 };
804
805 /* read mode width */
806 of_property_read_string(node, "active_w", &str);
807 if (str == NULL) {
808 dev_err(&client->dev, "Failed to read mode width\n");
809 return -ENODATA;
810 };
811 err = kstrtoint(str, 10, &pdata->mode_info[i].width);
812 if (err) {
813 dev_err(&client->dev, "Failed to convert mode width\n");
814 return -EFAULT;
815 }
816 /* read mode height */
817 of_property_read_string(node, "active_h", &str);
818 if (str == NULL) {
819 dev_err(&client->dev, "Failed to read mode height\n");
820 return -ENODATA;
821 };
822 err = kstrtoint(str, 10, &pdata->mode_info[i].height);
823 if (err) {
824 dev_err(&client->dev, "Failed to convert mode height\n");
825 return -EFAULT;
826 }
827 dev_info(&client->dev, "%s: mode %d x %d:\n", __func__,
828 pdata->mode_info[i].width, pdata->mode_info[i].height);
829
830 of_property_read_string(node, "line_length", &str);
831 if (str == NULL) {
832 dev_err(&client->dev, "Failed to read mode line_length\n");
833 return -ENODATA;
834 };
835 err = kstrtoint(str, 10, &pdata->mode_info[i].line_length);
836 if (err) {
837 dev_err(&client->dev, "Failed to convert mode line_length\n");
838 return -EFAULT;
839 }
840
841 of_property_read_string(node, "pix_clk_hz", &str);
842 if (str == NULL) {
843 dev_err(&client->dev, "Failed to read mode pix_clk_hz\n");
844 return -ENODATA;
845 };
846 err = kstrtoll(str, 10, &pdata->mode_info[i].pixel_clock);
847 if (err) {
848 dev_err(&client->dev, "Failed to convert mode pix_clk_hz\n");
849 return -EFAULT;
850 }
851 dev_info(&client->dev, "%s: line_length = %d, pixel_clock = %llu\n",
852 __func__, pdata->mode_info[i].line_length,
853 pdata->mode_info[i].pixel_clock);
854 }
855
856 return 0;
857}
858EXPORT_SYMBOL(camera_common_parse_sensor_mode);
diff --git a/drivers/media/platform/tegra/camera/camera_gpio.c b/drivers/media/platform/tegra/camera/camera_gpio.c
new file mode 100644
index 000000000..fcd53e3be
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/camera_gpio.c
@@ -0,0 +1,160 @@
1/*
2 * virtual.c - Camera GPIO driver
3 *
4 * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
5
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/list.h>
20#include <linux/debugfs.h>
21#include <linux/i2c.h>
22#include <linux/slab.h>
23#include <linux/gpio.h>
24
25#include "camera_gpio.h"
26
27struct camera_gpio {
28 struct list_head list;
29 unsigned gpio_num;
30 struct mutex mutex;
31 atomic_t state_cnt;
32 atomic_t use_cnt;
33};
34
35static DEFINE_MUTEX(g_mutex);
36static LIST_HEAD(cam_gpio_list);
37
38int cam_gpio_register(struct i2c_client *client,
39 unsigned pin_num) {
40 struct camera_gpio *new_gpio;
41 struct camera_gpio *next_gpio;
42
43 mutex_lock(&g_mutex);
44
45
46 list_for_each_entry(next_gpio, &cam_gpio_list, list) {
47 if (next_gpio->gpio_num == pin_num) {
48 dev_dbg(&client->dev,
49 "%s: gpio pin %u already registered.\n",
50 __func__, pin_num);
51
52 atomic_inc(&next_gpio->use_cnt);
53
54 mutex_unlock(&g_mutex);
55 return 0;
56 }
57 }
58
59 /* gpio is not present in the cam_gpio_list, add it */
60 new_gpio = kzalloc(sizeof(*new_gpio), GFP_KERNEL);
61 if (!new_gpio) {
62 dev_err(&client->dev, "%s: memory low!\n", __func__);
63 mutex_unlock(&g_mutex);
64 return -EFAULT;
65 }
66
67 dev_dbg(&client->dev, "%s: adding cam gpio %u\n",
68 __func__, pin_num);
69
70 new_gpio->gpio_num = pin_num;
71 mutex_init(&new_gpio->mutex);
72 atomic_inc(&new_gpio->use_cnt);
73
74 list_add(&new_gpio->list, &cam_gpio_list);
75
76 mutex_unlock(&g_mutex);
77 return 0;
78}
79EXPORT_SYMBOL(cam_gpio_register);
80
81void cam_gpio_deregister(struct i2c_client *client,
82 unsigned pin_num) {
83 struct camera_gpio *next_gpio;
84
85 mutex_lock(&g_mutex);
86
87
88 list_for_each_entry(next_gpio, &cam_gpio_list, list) {
89 if (next_gpio->gpio_num == pin_num) {
90 atomic_dec(&next_gpio->use_cnt);
91
92 if (atomic_read(&next_gpio->use_cnt) == 0) {
93 list_del(&next_gpio->list);
94 kfree(next_gpio);
95
96 dev_dbg(&client->dev,
97 "%s: removing cam gpio %u\n",
98 __func__, pin_num);
99 }
100
101 break;
102 }
103 }
104
105 mutex_unlock(&g_mutex);
106 return;
107}
108EXPORT_SYMBOL(cam_gpio_deregister);
109
110int cam_gpio_ctrl(struct i2c_client *client,
111 unsigned pin_num, int val,
112 bool active_high) /* val: 0=deassert, 1=assert */
113{
114 struct camera_gpio *next_gpio;
115 int err = -EINVAL;
116 int pin_val;
117 bool found = false;
118
119 list_for_each_entry(next_gpio, &cam_gpio_list, list) {
120 mutex_lock(&next_gpio->mutex);
121 if (next_gpio->gpio_num == pin_num) {
122 found = true;
123
124 if (!atomic_read(&next_gpio->state_cnt) &&
125 !val) {
126 dev_err(&client->dev,
127 "%s: state cnt can't be < 0\n",
128 __func__);
129 mutex_unlock(&next_gpio->mutex);
130 return err;
131 }
132
133 if (val)
134 atomic_inc(&next_gpio->state_cnt);
135 else
136 atomic_dec(&next_gpio->state_cnt);
137
138 pin_val = active_high ? val : !val;
139 pin_val &= 1;
140 err = pin_val;
141
142 /* subtract val allows a 0 check to be
143 * used to indicate that gpio can be written to*/
144 if (atomic_read(&next_gpio->state_cnt) - val == 0) {
145 gpio_set_value_cansleep(pin_num, pin_val);
146 dev_dbg(&client->dev, "%s %u %d\n",
147 __func__, pin_num, pin_val);
148 }
149 }
150 mutex_unlock(&next_gpio->mutex);
151 }
152
153 if (!found)
154 dev_dbg(&client->dev,
155 "WARNING %s: gpio %u not in list\n",
156 __func__, pin_num);
157
158 return err; /* return value written or error */
159}
160EXPORT_SYMBOL(cam_gpio_ctrl);
diff --git a/drivers/media/platform/tegra/camera/camera_gpio.h b/drivers/media/platform/tegra/camera/camera_gpio.h
new file mode 100644
index 000000000..b388e178d
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/camera_gpio.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (c) 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#ifndef __CAMERA_GPIO_H__
18#define __CAMERA_GPIO_H__
19
20int cam_gpio_register(struct i2c_client *client,
21 unsigned pin_num);
22
23void cam_gpio_deregister(struct i2c_client *client,
24 unsigned pin_num);
25
26int cam_gpio_ctrl(struct i2c_client *client,
27 unsigned pin_num, int ref_inc, bool active_high);
28
29#endif
30/* __CAMERA_GPIO_H__ */
diff --git a/drivers/media/platform/tegra/camera/csi/Makefile b/drivers/media/platform/tegra/camera/csi/Makefile
new file mode 100644
index 000000000..3d307cb83
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/Makefile
@@ -0,0 +1,8 @@
1GCOV_PROFILE := y
2ccflags-y += -I../nvhost/drivers/video/tegra/host
3ccflags-y += -I../nvhost/include
4ccflags-y += -Idrivers/video/tegra/camera
5ccflags-y += -Idrivers/media/platform/tegra
6ccflags-y += -Werror
7
8obj-y += csi.o csi2_fops.o csi4_fops.o
diff --git a/drivers/media/platform/tegra/camera/csi/csi.c b/drivers/media/platform/tegra/camera/csi/csi.c
new file mode 100644
index 000000000..f6c838ff2
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi.c
@@ -0,0 +1,784 @@
1/*
2 * NVIDIA Tegra CSI Device
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/clk.h>
14#include <linux/device.h>
15#include <linux/gpio/consumer.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/of_graph.h>
19#include <linux/platform_device.h>
20#include <linux/of_platform.h>
21
22#include <media/media-entity.h>
23#include <media/v4l2-async.h>
24#include <media/v4l2-ctrls.h>
25#include <media/camera_common.h>
26
27#include "dev.h"
28#include "vi/vi.h"
29#include "camera/csi/csi.h"
30#include "camera/vi/mc_common.h"
31#include "mipical/mipi_cal.h"
32#include "linux/nvhost.h"
33
34static int set_csi_properties(struct tegra_csi_device *csi,
35 struct platform_device *pdev)
36{
37 struct camera_common_data *s_data = &csi->s_data[0];
38
39 /*
40 * These values are only used for tpg mode
41 * With sensor, CSI power and clock info are provided
42 * by the sensor sub device
43 */
44 s_data->csi_port = 0;
45 s_data->numlanes = 12;
46 csi->clk_freq = TEGRA_CLOCK_CSI_PORT_MAX;
47
48 return 0;
49}
50
51static void update_blank_intervals(struct tegra_csi_channel *chan,
52 int portnum, int fmtindex)
53{
54 struct tegra_csi_port *port = &chan->ports[portnum];
55 const struct tpg_frmfmt *tegra_csi_tpg_frmfmt =
56 chan->csi->tpg_frmfmt_table;
57
58 port->framerate = tegra_csi_tpg_frmfmt[fmtindex].framerate;
59 port->h_blank = tegra_csi_tpg_frmfmt[fmtindex].h_blank;
60 port->v_blank = tegra_csi_tpg_frmfmt[fmtindex].v_blank;
61}
62
63void set_csi_portinfo(struct tegra_csi_device *csi,
64 unsigned int port, unsigned int numlanes)
65{
66 struct camera_common_data *s_data = &csi->s_data[port];
67
68 s_data->csi_port = port;
69 s_data->numlanes = numlanes;
70 s_data->def_clk_freq = TEGRA_CLOCK_CSI_PORT_MAX;
71}
72EXPORT_SYMBOL(set_csi_portinfo);
73
74int tegra_csi_power(struct tegra_csi_device *csi, int enable)
75{
76 int err = 0;
77
78 if (enable) {
79 err = csi->fops->csi_power_on(csi);
80 if (!err)
81 atomic_inc(&csi->power_ref);
82 } else {
83 err = csi->fops->csi_power_off(csi);
84 if (!err)
85 atomic_dec(&csi->power_ref);
86 }
87 return err;
88}
89EXPORT_SYMBOL(tegra_csi_power);
90
91int tegra_csi_s_power(struct v4l2_subdev *subdev, int enable)
92{
93 int err = 0;
94 struct tegra_csi_device *csi = to_csi(subdev);
95
96 err = tegra_csi_power(csi, enable);
97
98 return err;
99}
100
101/*
102 * -----------------------------------------------------------------------------
103 * CSI Subdevice Video Operations
104 * -----------------------------------------------------------------------------
105 */
106
107int tegra_csi_start_streaming(struct tegra_csi_channel *chan,
108 enum tegra_csi_port_num port_num)
109{
110 struct tegra_csi_device *csi = chan->csi;
111
112 return csi->fops->csi_start_streaming(chan, port_num);
113}
114EXPORT_SYMBOL(tegra_csi_start_streaming);
115
116void tegra_csi_stop_streaming(struct tegra_csi_channel *chan,
117 enum tegra_csi_port_num port_num)
118{
119 struct tegra_csi_device *csi = chan->csi;
120
121 csi->fops->csi_stop_streaming(chan, port_num);
122}
123EXPORT_SYMBOL(tegra_csi_stop_streaming);
124
125static int tegra_csi_s_stream(struct v4l2_subdev *subdev, int enable)
126{
127 struct tegra_csi_device *csi;
128 struct tegra_csi_channel *chan = to_csi_chan(subdev);
129 struct tegra_channel *tegra_chan = v4l2_get_subdev_hostdata(subdev);
130 int i, ret = 0;
131
132 csi = to_csi(subdev);
133 if (!csi)
134 return -EINVAL;
135 if (!chan->pg_mode) {
136 if (enable) {
137 tegra_mipi_bias_pad_enable();
138 csi->fops->mipical(chan);
139 } else
140 tegra_mipi_bias_pad_disable();
141 }
142 if (tegra_chan->bypass)
143 return 0;
144
145 for (i = 0; i < tegra_chan->valid_ports; i++) {
146 if (enable) {
147 ret = tegra_csi_start_streaming(chan, i);
148 if (ret)
149 tegra_csi_stop_streaming(chan, i);
150 } else
151 tegra_csi_stop_streaming(chan, i);
152 }
153 return ret;
154}
155
156/*
157 * Only use this subdevice media bus ops for test pattern generator,
158 * because CSI device is an separated subdevice which has 6 source
159 * pads to generate test pattern.
160 */
161static struct v4l2_mbus_framefmt tegra_csi_tpg_fmts[] = {
162 {
163 TEGRA_DEF_WIDTH,
164 TEGRA_DEF_HEIGHT,
165 MEDIA_BUS_FMT_SRGGB10_1X10,
166 V4L2_FIELD_NONE,
167 V4L2_COLORSPACE_SRGB
168 },
169 {
170 TEGRA_DEF_WIDTH,
171 TEGRA_DEF_HEIGHT,
172 MEDIA_BUS_FMT_RGB888_1X32_PADHI,
173 V4L2_FIELD_NONE,
174 V4L2_COLORSPACE_SRGB
175 }
176
177};
178
179static struct v4l2_frmsize_discrete tegra_csi_tpg_sizes[] = {
180 {1280, 720},
181 {1920, 1080},
182 {3840, 2160}
183};
184
185static int tegra_csi_enum_framesizes(struct v4l2_subdev *sd,
186 struct v4l2_subdev_pad_config *cfg,
187 struct v4l2_subdev_frame_size_enum *fse)
188{
189 int i;
190 struct tegra_csi_channel *chan = to_csi_chan(sd);
191 struct tegra_channel *vi_chan = v4l2_get_subdev_hostdata(sd);
192
193 if (!chan->pg_mode)
194 return -ENOIOCTLCMD;
195
196 if (fse->index >= ARRAY_SIZE(tegra_csi_tpg_sizes))
197 return -EINVAL;
198
199 for (i = 0; i < ARRAY_SIZE(tegra_csi_tpg_fmts); i++) {
200 const struct tegra_video_format *format =
201 tegra_core_get_format_by_code(vi_chan,
202 tegra_csi_tpg_fmts[i].code, 0);
203 if (format && format->fourcc == fse->code)
204 break;
205 }
206 if (i == ARRAY_SIZE(tegra_csi_tpg_fmts))
207 return -EINVAL;
208
209 fse->min_width = fse->max_width =
210 tegra_csi_tpg_sizes[fse->index].width;
211 fse->min_height = fse->max_height =
212 tegra_csi_tpg_sizes[fse->index].height;
213 return 0;
214}
215
216static int tegra_csi_get_fmtindex(struct tegra_csi_channel *chan,
217 int width, int height, int pixel_format)
218{
219 int i;
220 const struct tpg_frmfmt *tegra_csi_tpg_frmfmt =
221 chan->csi->tpg_frmfmt_table;
222
223 for (i = 0; i < chan->csi->tpg_frmfmt_table_size; i++) {
224 if (tegra_csi_tpg_frmfmt[i].frmsize.width == width &&
225 tegra_csi_tpg_frmfmt[i].frmsize.height == height &&
226 tegra_csi_tpg_frmfmt[i].pixel_format == pixel_format)
227 break;
228 }
229
230 if (i == chan->csi->tpg_frmfmt_table_size)
231 return -EINVAL;
232
233 return i;
234}
235
236static int tegra_csi_enum_frameintervals(struct v4l2_subdev *sd,
237 struct v4l2_subdev_pad_config *cfg,
238 struct v4l2_subdev_frame_interval_enum *fie)
239{
240 int index;
241 struct tegra_csi_channel *chan = to_csi_chan(sd);
242 const struct tegra_video_format *format;
243 const struct tpg_frmfmt *tegra_csi_tpg_frmfmt =
244 chan->csi->tpg_frmfmt_table;
245 struct tegra_channel *vi_chan = v4l2_get_subdev_hostdata(sd);
246
247 if (!chan->pg_mode)
248 return -ENOIOCTLCMD;
249
250 /* One resolution just one framerate */
251 if (fie->index > 0)
252 return -EINVAL;
253 format = tegra_core_get_format_by_fourcc(vi_chan, fie->code);
254 if (!format)
255 return -EINVAL;
256 index = tegra_csi_get_fmtindex(chan, fie->width, fie->height,
257 format->fourcc);
258 if (index < 0)
259 return -EINVAL;
260
261 fie->interval.numerator = 1;
262 fie->interval.denominator = tegra_csi_tpg_frmfmt[index].framerate;
263
264 return 0;
265}
266
267static int tegra_csi_try_mbus_fmt(struct v4l2_subdev *sd,
268 struct v4l2_mbus_framefmt *mf)
269{
270 int i, j;
271 struct tegra_csi_channel *chan = to_csi_chan(sd);
272 static struct v4l2_frmsize_discrete *sizes;
273
274 if (!chan->pg_mode)
275 return -ENOIOCTLCMD;
276
277 for (i = 0; i < ARRAY_SIZE(tegra_csi_tpg_fmts); i++) {
278 struct v4l2_mbus_framefmt *fmt = &tegra_csi_tpg_fmts[i];
279
280 if (mf->code == fmt->code && mf->field == fmt->field &&
281 mf->colorspace == fmt->colorspace) {
282 for (j = 0; j < ARRAY_SIZE(tegra_csi_tpg_sizes); j++) {
283 sizes = &tegra_csi_tpg_sizes[j];
284 if (mf->width == sizes->width &&
285 mf->height == sizes->height)
286 return 0;
287 }
288 }
289 }
290
291 memcpy(mf, tegra_csi_tpg_fmts, sizeof(struct v4l2_mbus_framefmt));
292
293 return 0;
294}
295
296static int tegra_csi_g_mbus_fmt(struct v4l2_subdev *sd,
297 struct v4l2_mbus_framefmt *fmt)
298{
299 struct tegra_csi_channel *chan = to_csi_chan(sd);
300 struct v4l2_mbus_framefmt *format = &chan->ports[0].format;
301
302 if (!chan->pg_mode) {
303 dev_err(chan->csi->dev, "CSI is not in TPG mode\n");
304 return -EINVAL;
305 }
306
307 mutex_lock(&chan->format_lock);
308 memcpy(fmt, format, sizeof(struct v4l2_mbus_framefmt));
309 mutex_unlock(&chan->format_lock);
310
311 return 0;
312}
313
314static int csi_is_power_on(struct tegra_csi_device *csi)
315{
316 return atomic_read(&csi->power_ref);
317}
318static int tegra_csi_g_input_status(struct v4l2_subdev *sd, u32 *status)
319{
320 struct tegra_csi_device *csi = to_csi(sd);
321
322 /* Set status to 0 if power is on
323 * Set status to 1 if power is off
324 */
325 *status = !csi_is_power_on(csi);
326
327 return 0;
328}
329
330/* -----------------------------------------------------------------------------
331 * V4L2 Subdevice Pad Operations
332 */
333
334static int tegra_csi_get_format(struct v4l2_subdev *subdev,
335 struct v4l2_subdev_pad_config *cfg,
336 struct v4l2_subdev_format *fmt)
337{
338 struct tegra_csi_channel *chan = to_csi_chan(subdev);
339 struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format;
340 int ret;
341
342 if (!chan->pg_mode)
343 return -ENOIOCTLCMD;
344 ret = tegra_csi_g_mbus_fmt(subdev, mbus_fmt);
345 if (ret)
346 return ret;
347
348 return 0;
349}
350
351static int tegra_csi_set_format(struct v4l2_subdev *subdev,
352 struct v4l2_subdev_pad_config *cfg,
353 struct v4l2_subdev_format *fmt)
354{
355 int ret;
356 struct tegra_csi_channel *chan = to_csi_chan(subdev);
357 struct v4l2_mbus_framefmt *format = &fmt->format;
358 const struct tegra_video_format *vf;
359 struct tegra_channel *vi_chan = v4l2_get_subdev_hostdata(subdev);
360 int index, i;
361
362 if (!chan->pg_mode)
363 return -ENOIOCTLCMD;
364
365 ret = tegra_csi_try_mbus_fmt(subdev, format);
366 if (ret)
367 return ret;
368
369 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
370 return 0;
371
372 vf = tegra_core_get_format_by_code(vi_chan, format->code, 0);
373 if (!vf) {
374 dev_err(chan->csi->dev, "Fail to find tegra video fmt");
375 mutex_unlock(&chan->format_lock);
376 return -EINVAL;
377 }
378 index = tegra_csi_get_fmtindex(chan, format->width,
379 format->height, vf->fourcc);
380 if (index < 0) {
381 dev_err(chan->csi->dev, "Fail to find matching fmt");
382 return -EINVAL;
383 }
384
385 mutex_lock(&chan->format_lock);
386 for (i = 0; i < vi_chan->valid_ports; i++) {
387 memcpy(&chan->ports[i].format,
388 &fmt->format, sizeof(struct v4l2_mbus_framefmt));
389 chan->ports[i].core_format = vf;
390 update_blank_intervals(chan, i, index);
391 }
392 mutex_unlock(&chan->format_lock);
393
394 return 0;
395}
396
397static int tegra_csi_g_frame_interval(struct v4l2_subdev *sd,
398 struct v4l2_subdev_frame_interval *vfi)
399{
400 struct tegra_csi_channel *chan = to_csi_chan(sd);
401 struct tegra_csi_port *port = &chan->ports[0];
402
403 if (!port->framerate)
404 return -EINVAL;
405
406 vfi->interval.numerator = 1;
407 vfi->interval.denominator = port->framerate;
408
409 return 0;
410}
411
412/* -----------------------------------------------------------------------------
413 * V4L2 Subdevice Operations
414 */
415static struct v4l2_subdev_video_ops tegra_csi_video_ops = {
416 .s_stream = tegra_csi_s_stream,
417 .g_input_status = tegra_csi_g_input_status,
418 .g_frame_interval = tegra_csi_g_frame_interval,
419};
420
421static struct v4l2_subdev_pad_ops tegra_csi_pad_ops = {
422 .get_fmt = tegra_csi_get_format,
423 .set_fmt = tegra_csi_set_format,
424 .enum_frame_size = tegra_csi_enum_framesizes,
425 .enum_frame_interval = tegra_csi_enum_frameintervals,
426};
427
428static struct v4l2_subdev_core_ops tegra_csi_core_ops = {
429 .s_power = tegra_csi_s_power,
430};
431
432static struct v4l2_subdev_ops tegra_csi_ops = {
433 .core = &tegra_csi_core_ops,
434 .video = &tegra_csi_video_ops,
435 .pad = &tegra_csi_pad_ops,
436};
437
438/* -----------------------------------------------------------------------------
439 * Media Operations
440 */
441
442static const struct media_entity_operations tegra_csi_media_ops = {
443 .link_validate = v4l2_subdev_link_validate,
444};
445
446/* -----------------------------------------------------------------------------
447 * Platform Device Driver
448 */
449
450static int tegra_csi_get_port_info(struct tegra_csi_channel *chan,
451 struct device_node *node, unsigned int index)
452{
453 struct device_node *ep = NULL;
454 struct device_node *ports;
455 struct device_node *port;
456 struct device_node *chan_dt;
457
458 int value = 0xFFFF;
459 int ret = 0, i;
460
461 memset(&chan->port[0], INVALID_CSI_PORT, TEGRA_CSI_BLOCKS);
462 for_each_child_of_node(node, chan_dt) {
463 if (!chan_dt->name || of_node_cmp(chan_dt->name, "channel"))
464 continue;
465 ret = of_property_read_u32(chan_dt, "reg", &value);
466 if (ret < 0)
467 return -EINVAL;
468 if (value == index)
469 break;
470 }
471
472 chan->subdev.of_node = chan_dt;
473 ports = of_get_child_by_name(chan_dt, "ports");
474 if (ports == NULL)
475 return -EINVAL;
476
477 for_each_child_of_node(ports, port) {
478 if (!port->name || of_node_cmp(port->name, "port"))
479 continue;
480 ret = of_property_read_u32(port, "reg", &value);
481 if (ret < 0)
482 continue;
483 if (value != 0)
484 continue;
485 for_each_child_of_node(port, ep) {
486 if (!ep->name || of_node_cmp(ep->name, "endpoint"))
487 continue;
488 ret = of_property_read_u32(ep, "csi-port", &value);
489 if (ret < 0)
490 dev_err(chan->csi->dev, "No csi port info\n");
491 chan->port[0] = value;
492
493 ret = of_property_read_u32(ep, "bus-width", &value);
494 if (ret < 0)
495 dev_err(chan->csi->dev, "No bus width info\n");
496 chan->numlanes = value;
497 if (value > 12) {
498 dev_err(chan->csi->dev, "Invalid num lanes\n");
499 return -EINVAL;
500 }
501 /*
502 * for numlanes greater than 4 multiple CSI bricks
503 * are needed to capture the image, the logic below
504 * checks for numlanes > 4 and add a new CSI brick
505 * as a valid port. Loops around the three CSI
506 * bricks to add as many ports necessary.
507 */
508 value -= 4;
509 for (i = 1; value > 0; i++, value -= 4) {
510 int next_port = chan->port[i-1] + 2;
511
512 next_port = (next_port % (PORT_F + 1));
513 chan->port[i] = next_port;
514 }
515 }
516 }
517
518 for (i = 0; csi_port_is_valid(chan->port[i]); i++)
519 chan->numports++;
520
521 return 0;
522}
523
524int tegra_csi_init(struct tegra_csi_device *csi,
525 struct platform_device *pdev)
526{
527 int err = 0;
528 struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
529
530 csi->dev = &pdev->dev;
531 err = set_csi_properties(csi, pdev);
532 if (err)
533 return err;
534
535 csi->iomem_base = pdata->aperture[0];
536 csi->fops->hw_init(csi);
537 return err;
538}
539
540static int tegra_csi_channel_init_one(struct tegra_csi_channel *chan)
541{
542 struct v4l2_subdev *sd;
543 int numlanes = 0;
544 struct tegra_csi_device *csi = chan->csi;
545 int i, ret;
546 const struct tegra_video_format *vf;
547
548 mutex_init(&chan->format_lock);
549
550 vf = tegra_core_get_default_format();
551 if (vf == NULL) {
552 dev_err(csi->dev, "Fail to find tegra video fmt");
553 return -EINVAL;
554 }
555
556 sd = &chan->subdev;
557 /* Initialize V4L2 subdevice and media entity */
558 v4l2_subdev_init(sd, &tegra_csi_ops);
559 sd->dev = chan->csi->dev;
560 v4l2_set_subdevdata(sd, csi);
561 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
562 sd->entity.ops = &tegra_csi_media_ops;
563 chan->ports = devm_kzalloc(csi->dev,
564 chan->numports * sizeof(struct tegra_csi_port),
565 GFP_KERNEL);
566 if (!chan->ports)
567 return -ENOMEM;
568
569 /* Initialize the default format */
570 for (i = 0; i < chan->numports; i++) {
571 chan->ports[i].format.code = vf->vf_code;
572 chan->ports[i].format.field = V4L2_FIELD_NONE;
573 chan->ports[i].format.colorspace = V4L2_COLORSPACE_SRGB;
574 chan->ports[i].format.width = TEGRA_DEF_WIDTH;
575 chan->ports[i].format.height = TEGRA_DEF_HEIGHT;
576 chan->ports[i].core_format = vf;
577 }
578 if (chan->pg_mode) {
579 /* If CSI has 2 existing channels, chan->id will start
580 * from 2 for the first TPG channel, which uses PORT_A(0).
581 * To get the correct PORT number, subtract existing number of
582 * channels from chan->id.
583 */
584 chan->port[0] = chan->id - csi->num_channels;
585 WARN_ON(chan->port[0] > TPG_CHANNELS);
586 chan->ports[0].num = chan->id - csi->num_channels;
587 chan->ports->lanes = 2;
588 chan->pads = devm_kzalloc(csi->dev, sizeof(*chan->pads),
589 GFP_KERNEL);
590 if (!chan->pads)
591 return -ENOMEM;
592 chan->pads[0].flags = MEDIA_PAD_FL_SOURCE;
593 } else {
594 chan->pads = devm_kzalloc(csi->dev, 2 * sizeof(*chan->pads),
595 GFP_KERNEL);
596 if (!chan->pads)
597 return -ENOMEM;
598 chan->pads[0].flags = MEDIA_PAD_FL_SINK;
599 chan->pads[1].flags = MEDIA_PAD_FL_SOURCE;
600 }
601 snprintf(sd->name, sizeof(sd->name), "%s-%d",
602 chan->pg_mode ? "tpg" :
603 (strlen(csi->devname) == 0 ?
604 dev_name(csi->dev) : csi->devname),
605 chan->port[0]);
606 /* Initialize media entity */
607 ret = media_entity_init(&sd->entity,
608 chan->pg_mode ? 1 : 2,
609 chan->pads, 0);
610 if (ret < 0)
611 return ret;
612
613 for (i = 0; i < chan->numports; i++) {
614 numlanes = chan->numlanes - (i * MAX_CSI_BLOCK_LANES);
615 WARN_ON(numlanes < 0);
616 numlanes = numlanes > MAX_CSI_BLOCK_LANES ?
617 MAX_CSI_BLOCK_LANES : numlanes;
618 chan->ports[i].lanes = numlanes;
619 chan->ports[i].num = chan->port[i];
620 }
621
622 if (!chan->pg_mode) {
623 ret = v4l2_async_register_subdev(sd);
624 if (ret < 0) {
625 dev_err(csi->dev, "failed to register subdev\n");
626 media_entity_cleanup(&sd->entity);
627 }
628 }
629 return ret;
630}
631
632static int tegra_csi_channels_init(struct tegra_csi_device *csi)
633{
634 int ret;
635 struct tegra_csi_channel *it;
636
637 list_for_each_entry(it, &csi->csi_chans, list) {
638 ret = tegra_csi_channel_init_one(it);
639 if (ret)
640 return ret;
641 }
642
643 return 0;
644}
645
646static int csi_parse_dt(struct tegra_csi_device *csi,
647 struct platform_device *pdev)
648{
649 int err = 0, i;
650 int num_channels = 0;
651 struct device_node *node = pdev->dev.of_node;
652 struct tegra_csi_channel *item;
653
654 if (strncmp(node->name, "nvcsi", 5)) {
655 node = of_find_node_by_name(node, "nvcsi");
656 strncpy(csi->devname, "nvcsi", 6);
657 }
658 if (!node)
659 return -EINVAL;
660 err = of_property_read_u32(node, "num-channels", &num_channels);
661 if (err) {
662 dev_dbg(csi->dev, " Failed to find num of channels, set to 0\n");
663 num_channels = 0;
664 }
665
666 csi->num_channels = num_channels;
667 for (i = 0; i < num_channels; i++) {
668 item = devm_kzalloc(csi->dev, sizeof(*item), GFP_KERNEL);
669 if (!item)
670 return -ENOMEM;
671 list_add_tail(&item->list, &csi->csi_chans);
672 item->csi = csi;
673 item->id = i;
674 err = tegra_csi_get_port_info(item, node, item->id);
675 if (err)
676 return err;
677 }
678
679 return 0;
680}
681
682int tpg_csi_media_controller_init(struct tegra_csi_device *csi, int pg_mode)
683{
684 int i, err;
685 struct tegra_csi_channel *item;
686
687 if (!csi)
688 return -EINVAL;
689 for (i = 0; i < TPG_CHANNELS; i++) {
690 item = devm_kzalloc(csi->dev, sizeof(*item), GFP_KERNEL);
691 if (!item) {
692 err = -ENOMEM;
693 goto channel_init_error;
694 }
695 if (i == 0)
696 csi->tpg_start = item;
697 list_add_tail(&item->list, &csi->csi_chans);
698 item->numlanes = 2;
699 item->numports = 1;
700 item->csi = csi;
701 item->pg_mode = pg_mode;
702 item->id = csi->num_channels + i;
703 err = tegra_csi_channel_init_one(item);
704 if (err)
705 goto channel_init_error;
706 }
707 csi->fops->hw_init(csi);
708 csi->num_channels += TPG_CHANNELS;
709
710 return err;
711
712channel_init_error:
713 if (csi->tpg_start)
714 tpg_csi_media_controller_cleanup(csi);
715 dev_err(csi->dev, "%s: Error\n", __func__);
716 return err;
717}
718EXPORT_SYMBOL(tpg_csi_media_controller_init);
719
720void tpg_csi_media_controller_cleanup(struct tegra_csi_device *csi)
721{
722 struct tegra_csi_channel *item;
723 struct tegra_csi_channel *itemn;
724 struct v4l2_subdev *sd;
725
726 list_for_each_entry_safe(item, itemn, &csi->csi_chans, list) {
727 if (!item->pg_mode)
728 continue;
729 sd = &item->subdev;
730 /* decrement media device entity count */
731 if (sd->entity.parent)
732 sd->entity.parent->entity_id--;
733 v4l2_device_unregister_subdev(sd);
734 media_entity_cleanup(&sd->entity);
735 list_del(&item->list);
736 devm_kfree(csi->dev, item);
737 }
738 csi->num_channels -= TPG_CHANNELS;
739 csi->tpg_start = NULL;
740}
741EXPORT_SYMBOL(tpg_csi_media_controller_cleanup);
742int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
743 struct platform_device *pdev)
744{
745 int ret;
746
747 csi->dev = &pdev->dev;
748 csi->pdev = pdev;
749 atomic_set(&csi->power_ref, 0);
750 atomic_set(&csi->tpg_enabled, 0);
751 INIT_LIST_HEAD(&csi->csi_chans);
752 ret = csi_parse_dt(csi, pdev);
753 if (ret < 0)
754 return ret;
755
756 /*
757 * if there is no csi channels listed in DT,
758 * no need to init the channel and graph
759 */
760 if (csi->num_channels == 0)
761 return 0;
762
763 ret = tegra_csi_channels_init(csi);
764 ret = tegra_csi_init(csi, pdev);
765 if (ret < 0)
766 dev_err(&pdev->dev, "Failed to init csi property,clks\n");
767
768 return 0;
769}
770EXPORT_SYMBOL(tegra_csi_media_controller_init);
771
772int tegra_csi_media_controller_remove(struct tegra_csi_device *csi)
773{
774 struct tegra_csi_channel *chan;
775 struct v4l2_subdev *sd;
776
777 list_for_each_entry(chan, &csi->csi_chans, list) {
778 sd = &chan->subdev;
779 v4l2_async_unregister_subdev(sd);
780 media_entity_cleanup(&sd->entity);
781 }
782 return 0;
783}
784EXPORT_SYMBOL(tegra_csi_media_controller_remove);
diff --git a/drivers/media/platform/tegra/camera/csi/csi.h b/drivers/media/platform/tegra/camera/csi/csi.h
new file mode 100644
index 000000000..208e15e42
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi.h
@@ -0,0 +1,158 @@
1/*
2 * NVIDIA Tegra CSI Device Header
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __CSI_H_
14#define __CSI_H_
15
16#include <media/media-entity.h>
17#include <media/v4l2-async.h>
18#include <media/v4l2-ctrls.h>
19#include <media/v4l2-subdev.h>
20#include <linux/platform_device.h>
21
22#include <media/camera_common.h>
23#include <linux/platform_device.h>
24
25#include "camera/vi/registers.h"
26#include "camera/csi/csi4_registers.h"
27
28#define MAX_CSI_BLOCK_LANES 4
29
30enum tegra_csi_port_num {
31 PORT_A = 0,
32 PORT_B = 1,
33 PORT_C = 2,
34 PORT_D = 3,
35 PORT_E = 4,
36 PORT_F = 5,
37};
38
39#define csi_port_is_valid(port) (port > PORT_F ? 0 : 1)
40
41enum camera_gang_mode {
42 CAMERA_NO_GANG_MODE = 0,
43 CAMERA_GANG_L_R = 1,
44 CAMERA_GANG_T_B,
45 CAMERA_GANG_R_L,
46 CAMERA_GANG_B_T
47};
48
49struct tegra_channel;
50
51struct tpg_frmfmt {
52 struct v4l2_frmsize_discrete frmsize;
53 int pixel_format;
54 int framerate;
55 int h_blank;
56 int v_blank;
57};
58
59struct tegra_csi_port {
60 void __iomem *pixel_parser;
61 void __iomem *cil;
62 void __iomem *tpg;
63
64 /* One pair of sink/source pad has one format */
65 struct v4l2_mbus_framefmt format;
66 const struct tegra_video_format *core_format;
67 unsigned int lanes;
68 unsigned int framerate;
69 unsigned int h_blank;
70 unsigned int v_blank;
71
72 enum tegra_csi_port_num num;
73};
74
75struct tegra_csi_device {
76 struct device *dev;
77 struct platform_device *pdev;
78 char devname[32];
79 void __iomem *iomem_base;
80 void __iomem *iomem[3];
81 struct clk *plld_dsi;
82 struct clk *plld;
83
84 struct camera_common_data s_data[6];
85 struct tegra_csi_port *ports;
86 struct media_pad *pads;
87
88 unsigned int clk_freq;
89 int num_ports;
90 int num_channels;
91 struct list_head csi_chans;
92 struct tegra_csi_channel *tpg_start;
93 struct tegra_csi_fops *fops;
94 const struct tpg_frmfmt *tpg_frmfmt_table;
95 unsigned int tpg_frmfmt_table_size;
96 atomic_t power_ref;
97
98 struct dentry *debugdir;
99 atomic_t tpg_enabled;
100};
101
102/*
103 * subdev: channel subdev
104 * numports: Number of CSI ports in use for this channel
105 * numlanes: Number of CIL lanes in use
106 */
107struct tegra_csi_channel {
108 struct list_head list;
109 struct v4l2_subdev subdev;
110 struct media_pad *pads;
111 struct media_pipeline pipe;
112
113 struct tegra_csi_device *csi;
114 struct tegra_csi_port *ports;
115 unsigned char port[TEGRA_CSI_BLOCKS];
116 struct mutex format_lock;
117 unsigned int numports;
118 unsigned int numlanes;
119 unsigned int pg_mode;
120 struct camera_common_data *s_data;
121 unsigned int id;
122};
123
124static inline struct tegra_csi_channel *to_csi_chan(struct v4l2_subdev *subdev)
125{
126 return container_of(subdev, struct tegra_csi_channel, subdev);
127}
128
129static inline struct tegra_csi_device *to_csi(struct v4l2_subdev *subdev)
130{
131 struct tegra_csi_channel *chan = to_csi_chan(subdev);
132
133 return chan->csi;
134}
135
136void set_csi_portinfo(struct tegra_csi_device *csi,
137 unsigned int port, unsigned int numlanes);
138void tegra_csi_status(struct tegra_csi_channel *chan,
139 enum tegra_csi_port_num port_num);
140int tegra_csi_error(struct tegra_csi_channel *chan,
141 enum tegra_csi_port_num port_num);
142int tegra_csi_start_streaming(struct tegra_csi_channel *chan,
143 enum tegra_csi_port_num port_num);
144void tegra_csi_stop_streaming(struct tegra_csi_channel *chan,
145 enum tegra_csi_port_num port_num);
146void tegra_csi_error_recover(struct tegra_csi_channel *chan,
147 enum tegra_csi_port_num port_num);
148int tegra_csi_power(struct tegra_csi_device *csi, int enable);
149#define tegra_csi_power_on(csi) tegra_csi_power(csi, 1)
150#define tegra_csi_power_off(csi) tegra_csi_power(csi, 0)
151int tegra_csi_init(struct tegra_csi_device *csi,
152 struct platform_device *pdev);
153int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
154 struct platform_device *pdev);
155int tegra_csi_media_controller_remove(struct tegra_csi_device *csi);
156int tpg_csi_media_controller_init(struct tegra_csi_device *csi, int pg_mode);
157void tpg_csi_media_controller_cleanup(struct tegra_csi_device *csi);
158#endif
diff --git a/drivers/media/platform/tegra/camera/csi/csi2_fops.c b/drivers/media/platform/tegra/camera/csi/csi2_fops.c
new file mode 100644
index 000000000..d633a6205
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi2_fops.c
@@ -0,0 +1,455 @@
1/*
2 * Tegra CSI2 device common APIs
3 *
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/device.h>
14#include <linux/clk/tegra.h>
15#include "camera/csi/csi.h"
16#include "camera/vi/mc_common.h"
17#include "mipical/mipi_cal.h"
18#include "nvhost_acm.h"
19#include <linux/clk/tegra.h>
20
21static void csi_write(struct tegra_csi_channel *chan, unsigned int addr,
22 u32 val, u8 port)
23{
24 struct tegra_csi_device *csi = chan->csi;
25
26 writel(val, (csi->iomem[port] + addr));
27}
28
29static u32 csi_read(struct tegra_csi_channel *chan, unsigned int addr,
30 u8 port)
31{
32 struct tegra_csi_device *csi = chan->csi;
33
34 return readl((csi->iomem[port] + addr));
35}
36
37/* Pixel parser registers accessors */
38static void pp_write(struct tegra_csi_port *port, u32 addr, u32 val)
39{
40 writel(val, port->pixel_parser + addr);
41}
42
43static u32 pp_read(struct tegra_csi_port *port, u32 addr)
44{
45 return readl(port->pixel_parser + addr);
46}
47
48/* CSI CIL registers accessors */
49static void cil_write(struct tegra_csi_port *port, u32 addr, u32 val)
50{
51 writel(val, port->cil + addr);
52}
53
54static u32 cil_read(struct tegra_csi_port *port, u32 addr)
55{
56 return readl(port->cil + addr);
57}
58
59/* Test pattern generator registers accessor */
60static void tpg_write(struct tegra_csi_port *port,
61 unsigned int addr, u32 val)
62{
63 writel(val, port->tpg + addr);
64}
65
66int tegra_csi_error(struct tegra_csi_channel *chan,
67 enum tegra_csi_port_num port_num)
68{
69 struct tegra_csi_port *port;
70 u32 val;
71 int err = 0;
72
73 port = &chan->ports[port_num];
74 /*
75 * only uncorrectable header error and multi-bit
76 * transmission errors are checked as they cannot be
77 * corrected automatically
78 */
79 val = pp_read(port, TEGRA_CSI_PIXEL_PARSER_STATUS);
80 err |= val & 0x4000;
81 pp_write(port, TEGRA_CSI_PIXEL_PARSER_STATUS, val);
82
83 val = cil_read(port, TEGRA_CSI_CIL_STATUS);
84 err |= val & 0x02;
85 cil_write(port, TEGRA_CSI_CIL_STATUS, val);
86
87 val = cil_read(port, TEGRA_CSI_CILX_STATUS);
88 err |= val & 0x00020020;
89 cil_write(port, TEGRA_CSI_CILX_STATUS, val);
90
91 return err;
92}
93
94void tegra_csi_status(struct tegra_csi_channel *chan,
95 enum tegra_csi_port_num port_num)
96{
97 int i;
98 u32 val;
99 struct tegra_csi_port *port;
100
101 for (i = 0; i < chan->numports; i++) {
102 port = &chan->ports[i];
103 val = pp_read(port, TEGRA_CSI_PIXEL_PARSER_STATUS);
104
105 dev_dbg(chan->csi->dev,
106 "TEGRA_CSI_PIXEL_PARSER_STATUS 0x%08x\n",
107 val);
108
109 val = cil_read(port, TEGRA_CSI_CIL_STATUS);
110 dev_dbg(chan->csi->dev,
111 "TEGRA_CSI_CIL_STATUS 0x%08x\n", val);
112
113 val = cil_read(port, TEGRA_CSI_CILX_STATUS);
114 dev_dbg(chan->csi->dev,
115 "TEGRA_CSI_CILX_STATUS 0x%08x\n", val);
116 }
117}
118EXPORT_SYMBOL(tegra_csi_status);
119
120void tegra_csi_error_recover(struct tegra_csi_channel *chan,
121 enum tegra_csi_port_num port_num)
122{
123 struct tegra_csi_port *port;
124 struct tegra_csi_device *csi;
125 int i;
126
127 csi = chan->csi;
128
129 for (i = 0; i < chan->numports; i++) {
130 port = &chan->ports[i];
131
132 if (port->lanes == 4) {
133 int port_val = ((port_num >> 1) << 1);
134 struct tegra_csi_port *port_a =
135 &chan->ports[port_val];
136 struct tegra_csi_port *port_b =
137 &chan->ports[port_val+1];
138
139 tpg_write(port_a,
140 TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_ENABLE);
141 tpg_write(port_b,
142 TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_ENABLE);
143 cil_write(port_a,
144 TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
145 cil_write(port_b,
146 TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
147 csi_write(chan, TEGRA_CSI_CSI_SW_STATUS_RESET, 0x1,
148 port_num >> 1);
149 /* sleep for clock cycles to drain the Rx FIFO */
150 usleep_range(10, 20);
151 cil_write(port_a,
152 TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
153 cil_write(port_b,
154 TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
155 csi_write(chan,
156 TEGRA_CSI_CSI_SW_STATUS_RESET,
157 0x0, port_num >> 1);
158 tpg_write(port_a,
159 TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_DISABLE);
160 tpg_write(port_b,
161 TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_DISABLE);
162 } else {
163 tpg_write(port,
164 TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_ENABLE);
165 cil_write(port,
166 TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x1);
167 csi_write(chan,
168 TEGRA_CSI_CSI_SW_STATUS_RESET,
169 0x1, port_num >> 1);
170 /* sleep for clock cycles to drain the Rx FIFO */
171 usleep_range(10, 20);
172 cil_write(port,
173 TEGRA_CSI_CIL_SW_SENSOR_RESET, 0x0);
174 csi_write(chan,
175 TEGRA_CSI_CSI_SW_STATUS_RESET,
176 0x0, port_num >> 1);
177 tpg_write(port,
178 TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_DISABLE);
179 }
180 }
181}
182
183
184static int tpg_clk_enable(struct tegra_csi_device *csi)
185{
186 int err = 0;
187
188 if (atomic_inc_return(&csi->tpg_enabled) != 1)
189 return 0;
190
191 clk_set_rate(csi->plld, TEGRA_CLOCK_TPG);
192 err = clk_prepare_enable(csi->plld);
193 if (err) {
194 dev_err(csi->dev, "pll_d enable failed");
195 return err;
196 }
197
198 err = clk_prepare_enable(csi->plld_dsi);
199 if (err) {
200 dev_err(csi->dev, "pll_d enable failed");
201 goto plld_dsi_err;
202 }
203 tegra210_csi_source_from_plld();
204 return err;
205plld_dsi_err:
206 clk_disable_unprepare(csi->plld);
207 return err;
208}
209
210static int tpg_clk_disable(struct tegra_csi_device *csi)
211{
212 int err = 0;
213
214 if (!atomic_dec_and_test(&csi->tpg_enabled))
215 return 0;
216 tegra210_csi_source_from_brick();
217 clk_disable_unprepare(csi->plld_dsi);
218 clk_disable_unprepare(csi->plld);
219
220 return err;
221}
222
223static int csi2_tpg_start_streaming(struct tegra_csi_channel *chan,
224 enum tegra_csi_port_num port_num)
225{
226 struct tegra_csi_port *port = &chan->ports[port_num];
227
228 tpg_write(port, TEGRA_CSI_PATTERN_GENERATOR_CTRL,
229 ((chan->pg_mode - 1) << PG_MODE_OFFSET) |
230 PG_ENABLE);
231 tpg_write(port, TEGRA_CSI_PG_BLANK,
232 port->v_blank << PG_VBLANK_OFFSET |
233 port->h_blank);
234 tpg_write(port, TEGRA_CSI_PG_PHASE, 0x0);
235 tpg_write(port, TEGRA_CSI_PG_RED_FREQ,
236 (0x10 << PG_RED_VERT_INIT_FREQ_OFFSET) |
237 (0x10 << PG_RED_HOR_INIT_FREQ_OFFSET));
238 tpg_write(port, TEGRA_CSI_PG_RED_FREQ_RATE, 0x0);
239 tpg_write(port, TEGRA_CSI_PG_GREEN_FREQ,
240 (0x10 << PG_GREEN_VERT_INIT_FREQ_OFFSET) |
241 (0x10 << PG_GREEN_HOR_INIT_FREQ_OFFSET));
242 tpg_write(port, TEGRA_CSI_PG_GREEN_FREQ_RATE, 0x0);
243 tpg_write(port, TEGRA_CSI_PG_BLUE_FREQ,
244 (0x10 << PG_BLUE_VERT_INIT_FREQ_OFFSET) |
245 (0x10 << PG_BLUE_HOR_INIT_FREQ_OFFSET));
246 tpg_write(port, TEGRA_CSI_PG_BLUE_FREQ_RATE, 0x0);
247 return 0;
248}
249
250int csi2_start_streaming(struct tegra_csi_channel *chan,
251 enum tegra_csi_port_num port_num)
252{
253 struct tegra_csi_port *port = &chan->ports[port_num];
254 int csi_port, csi_lanes;
255
256 csi_port = chan->ports[port_num].num;
257 csi_lanes = chan->ports[port_num].lanes;
258
259 csi_write(chan, TEGRA_CSI_CLKEN_OVERRIDE, 0, csi_port >> 1);
260
261 /* Clean up status */
262 pp_write(port, TEGRA_CSI_PIXEL_PARSER_STATUS, 0xFFFFFFFF);
263 cil_write(port, TEGRA_CSI_CIL_STATUS, 0xFFFFFFFF);
264 cil_write(port, TEGRA_CSI_CILX_STATUS, 0xFFFFFFFF);
265
266 cil_write(port, TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0);
267
268 /* CIL PHY registers setup */
269 cil_write(port, TEGRA_CSI_CIL_PAD_CONFIG0, 0x0);
270 cil_write(port, TEGRA_CSI_CIL_PHY_CONTROL,
271 BYPASS_LP_SEQ | 0xA);
272
273 /*
274 * The CSI unit provides for connection of up to six cameras in
275 * the system and is organized as three identical instances of
276 * two MIPI support blocks, each with a separate 4-lane
277 * interface that can be configured as a single camera with 4
278 * lanes or as a dual camera with 2 lanes available for each
279 * camera.
280 */
281 if (csi_lanes == 4) {
282 unsigned int cilb_offset;
283
284 cilb_offset = TEGRA_CSI_CIL_OFFSET + TEGRA_CSI_PORT_OFFSET;
285
286 cil_write(port, TEGRA_CSI_CIL_PAD_CONFIG0,
287 BRICK_CLOCK_A_4X);
288 csi_write(chan, cilb_offset + TEGRA_CSI_CIL_PAD_CONFIG0, 0x0,
289 csi_port >> 1);
290 csi_write(chan, cilb_offset + TEGRA_CSI_CIL_INTERRUPT_MASK, 0x0,
291 csi_port >> 1);
292 cil_write(port, TEGRA_CSI_CIL_PHY_CONTROL,
293 BYPASS_LP_SEQ | 0xA);
294 csi_write(chan, cilb_offset + TEGRA_CSI_CIL_PHY_CONTROL,
295 BYPASS_LP_SEQ | 0xA, csi_port >> 1);
296 csi_write(chan, TEGRA_CSI_PHY_CIL_COMMAND,
297 CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_ENABLE,
298 csi_port >> 1);
299 } else {
300 u32 val = csi_read(chan, TEGRA_CSI_PHY_CIL_COMMAND,
301 csi_port >> 1);
302
303 csi_write(chan,
304 TEGRA_CSI_CIL_OFFSET + TEGRA_CSI_CIL_PAD_CONFIG0, 0x0,
305 csi_port >> 1);
306 val |= ((csi_port & 0x1) == PORT_A) ? CSI_A_PHY_CIL_ENABLE :
307 CSI_B_PHY_CIL_ENABLE;
308 csi_write(chan, TEGRA_CSI_PHY_CIL_COMMAND, val,
309 csi_port >> 1);
310 }
311 /* CSI pixel parser registers setup */
312 pp_write(port, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
313 (0xF << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
314 CSI_PP_SINGLE_SHOT_ENABLE | CSI_PP_RST);
315 pp_write(port, TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0x0);
316 pp_write(port, TEGRA_CSI_PIXEL_STREAM_CONTROL0,
317 CSI_PP_PACKET_HEADER_SENT |
318 CSI_PP_DATA_IDENTIFIER_ENABLE |
319 CSI_PP_WORD_COUNT_SELECT_HEADER |
320 CSI_PP_CRC_CHECK_ENABLE | CSI_PP_WC_CHECK |
321 CSI_PP_OUTPUT_FORMAT_STORE | CSI_PPA_PAD_LINE_NOPAD |
322 CSI_PP_HEADER_EC_DISABLE | CSI_PPA_PAD_FRAME_NOPAD |
323 (csi_port & 1));
324 pp_write(port, TEGRA_CSI_PIXEL_STREAM_CONTROL1,
325 (0x1 << CSI_PP_TOP_FIELD_FRAME_OFFSET) |
326 (0x1 << CSI_PP_TOP_FIELD_FRAME_MASK_OFFSET));
327 pp_write(port, TEGRA_CSI_PIXEL_STREAM_GAP,
328 0x14 << PP_FRAME_MIN_GAP_OFFSET);
329 pp_write(port, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME, 0x0);
330 pp_write(port, TEGRA_CSI_INPUT_STREAM_CONTROL,
331 (0x3f << CSI_SKIP_PACKET_THRESHOLD_OFFSET) |
332 (csi_lanes - 1));
333
334 if (chan->pg_mode) {
335 tpg_clk_enable(chan->csi);
336 csi2_tpg_start_streaming(chan, port_num);
337 }
338
339 pp_write(port, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
340 (0xF << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
341 CSI_PP_SINGLE_SHOT_ENABLE | CSI_PP_ENABLE);
342 return 0;
343}
344
345void csi2_stop_streaming(struct tegra_csi_channel *chan,
346 enum tegra_csi_port_num port_num)
347{
348 struct tegra_csi_port *port = &chan->ports[port_num];
349
350
351 if (chan->pg_mode) {
352 tpg_write(port, TEGRA_CSI_PATTERN_GENERATOR_CTRL, PG_DISABLE);
353 tpg_clk_disable(chan->csi);
354 }
355 if (!port) {
356 pr_err("%s:no port\n", __func__);
357 return;
358 }
359 pp_write(port, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND,
360 (0xF << CSI_PP_START_MARKER_FRAME_MAX_OFFSET) |
361 CSI_PP_DISABLE);
362}
363
364int csi2_hw_init(struct tegra_csi_device *csi)
365{
366 int i, csi_port;
367 struct tegra_csi_channel *it;
368 struct tegra_csi_port *port;
369
370 csi->iomem[0] = (csi->iomem_base + TEGRA_CSI_PIXEL_PARSER_0_BASE);
371 csi->iomem[1] = (csi->iomem_base + TEGRA_CSI_PIXEL_PARSER_2_BASE);
372 csi->iomem[2] = (csi->iomem_base + TEGRA_CSI_PIXEL_PARSER_4_BASE);
373 list_for_each_entry(it, &csi->csi_chans, list) {
374 for (i = 0; i < it->numports; i++) {
375 port = &it->ports[i];
376 csi_port = it->ports[i].num;
377 port->pixel_parser = csi->iomem[csi_port >> 1] +
378 (csi_port % 2) * TEGRA_CSI_PORT_OFFSET;
379 port->cil = port->pixel_parser + TEGRA_CSI_CIL_OFFSET;
380 port->tpg = port->pixel_parser + TEGRA_CSI_TPG_OFFSET;
381 }
382 }
383 csi->plld = devm_clk_get(csi->dev, "pll_d");
384 if (IS_ERR(csi->plld)) {
385 dev_err(csi->dev, "Fail to get pll_d\n");
386 return PTR_ERR(csi->plld);
387 }
388 csi->plld_dsi = devm_clk_get(csi->dev, "pll_d_dsi_out");
389 if (IS_ERR(csi->plld_dsi)) {
390 dev_err(csi->dev, "Fail to get pll_d_dsi_out\n");
391 return PTR_ERR(csi->plld_dsi);
392 }
393 return 0;
394}
395
396int csi2_mipi_cal(struct tegra_csi_channel *chan)
397{
398 unsigned int lanes, num_ports, val, csi_port;
399 struct tegra_csi_port *port;
400 struct tegra_csi_device *csi = chan->csi;
401
402 lanes = 0;
403 num_ports = 0;
404
405 nvhost_module_enable_clk(csi->dev);
406 while (num_ports < chan->numports) {
407 port = &chan->ports[num_ports];
408 csi_port = port->num;
409 dev_dbg(csi->dev, "Calibrate csi port %d\n", port->num);
410
411 if (chan->numlanes == 2) {
412 lanes |= CSIA << csi_port;
413 val = csi_read(chan, TEGRA_CSI_PHY_CIL_COMMAND,
414 csi_port >> 1);
415 csi_write(chan,
416 TEGRA_CSI_CIL_OFFSET +
417 TEGRA_CSI_CIL_PAD_CONFIG0, 0x0, csi_port >> 1);
418 val |= ((csi_port & 0x1) == PORT_A) ?
419 CSI_A_PHY_CIL_ENABLE : CSI_B_PHY_CIL_ENABLE;
420 csi_write(chan, TEGRA_CSI_PHY_CIL_COMMAND, val,
421 csi_port >> 1);
422 } else {
423 lanes |= (CSIA | CSIB) << port->num;
424 csi_write(chan, TEGRA_CSI_PHY_CIL_COMMAND,
425 CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_ENABLE,
426 csi_port >> 1);
427 }
428 num_ports++;
429 }
430 if (!lanes) {
431 dev_err(csi->dev,
432 "Selected no CSI lane, cannot do calibration");
433 return -EINVAL;
434 }
435 nvhost_module_disable_clk(csi->dev);
436 return tegra_mipi_calibration(lanes);
437}
438
439int csi2_power_on(struct tegra_csi_device *csi)
440{
441 return 0;
442}
443int csi2_power_off(struct tegra_csi_device *csi)
444{
445 return 0;
446}
447const struct tegra_csi_fops csi2_fops = {
448 .csi_power_on = csi2_power_on,
449 .csi_power_off = csi2_power_off,
450 .csi_start_streaming = csi2_start_streaming,
451 .csi_stop_streaming = csi2_stop_streaming,
452 .mipical = csi2_mipi_cal,
453 .hw_init = csi2_hw_init,
454};
455EXPORT_SYMBOL(csi2_fops);
diff --git a/drivers/media/platform/tegra/camera/csi/csi2_fops.h b/drivers/media/platform/tegra/camera/csi/csi2_fops.h
new file mode 100644
index 000000000..7b801e777
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi2_fops.h
@@ -0,0 +1,27 @@
1/*
2 * Tegra CSI2 device common APIs
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * Author: Bryan Wu <pengw@nvidia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __CSI2_H__
16#define __CSI2_H__
17
18#include "csi.h"
19
20int csi2_start_streaming(struct tegra_csi_channel *chan,
21 enum tegra_csi_port_num port_num);
22void csi2_stop_streaming(struct tegra_csi_channel *chan,
23 enum tegra_csi_port_num port_num);
24
25extern struct tegra_csi_fops csi2_fops;
26
27#endif
diff --git a/drivers/media/platform/tegra/camera/csi/csi4_fops.c b/drivers/media/platform/tegra/camera/csi/csi4_fops.c
new file mode 100644
index 000000000..6fd28156e
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi4_fops.c
@@ -0,0 +1,506 @@
1/*
2 * Tegra CSI4 device common APIs
3 *
4 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Frank Chen <frankc@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/clk/tegra.h>
13#include "nvhost_acm.h"
14#include "camera/csi/csi.h"
15#include "camera/csi/csi4_registers.h"
16#include "camera/vi/core.h"
17#include "mipical/mipi_cal.h"
18#include "nvcsi/nvcsi.h"
19
20static void csi4_stream_write(struct tegra_csi_channel *chan,
21 unsigned int index, unsigned int addr, u32 val)
22{
23 struct tegra_csi_device *csi = chan->csi;
24 u32 cilb_offset = (index & 0x1) ? CSI4_STREAM_OFFSET : 0x0;
25
26 writel(val, csi->iomem[index >> 1] + cilb_offset + addr);
27}
28
29static u32 csi4_stream_read(struct tegra_csi_channel *chan,
30 unsigned int index, unsigned int addr)
31{
32 struct tegra_csi_device *csi = chan->csi;
33 u32 cilb_offset = (index & 0x1) ? CSI4_STREAM_OFFSET : 0x0;
34
35 return readl(csi->iomem[index >> 1] + cilb_offset + addr);
36}
37
38static void csi4_phy_write(struct tegra_csi_channel *chan,
39 unsigned int index, unsigned int addr, u32 val)
40{
41 struct tegra_csi_device *csi = chan->csi;
42
43 writel(val, csi->iomem_base +
44 CSI4_BASE_ADDRESS + (CSI4_PHY_OFFSET * index) + addr);
45}
46
47static u32 csi4_phy_read(struct tegra_csi_channel *chan,
48 unsigned int index, unsigned int addr)
49{
50 struct tegra_csi_device *csi = chan->csi;
51
52 return readl(csi->iomem_base +
53 CSI4_BASE_ADDRESS + (CSI4_PHY_OFFSET * index) + addr);
54}
55
56static void csi4_stream_init(struct tegra_csi_channel *chan, int port_num)
57{
58 struct tegra_csi_device *csi = chan->csi;
59
60 dev_dbg(csi->dev, "%s\n", __func__);
61
62 csi4_stream_write(chan, port_num, CIL_INTR_STATUS, 0xffffffff);
63 csi4_stream_write(chan, port_num, CIL_ERR_INTR_STATUS, 0xffffffff);
64 csi4_stream_write(chan, port_num, CIL_INTR_MASK, 0xffffffff);
65 csi4_stream_write(chan, port_num, CIL_ERR_INTR_MASK, 0xffffffff);
66 csi4_stream_write(chan, port_num, INTR_STATUS, 0x3ffff);
67 csi4_stream_write(chan, port_num, ERR_INTR_STATUS, 0x7ffff);
68 csi4_stream_write(chan, port_num, ERROR_STATUS2VI_MASK, 0x0);
69 csi4_stream_write(chan, port_num, INTR_MASK, 0x0);
70 csi4_stream_write(chan, port_num, ERR_INTR_MASK, 0x0);
71}
72
73static void csi4_stream_config(struct tegra_csi_channel *chan, int port_num)
74{
75 struct tegra_csi_device *csi = chan->csi;
76 int val;
77
78 dev_dbg(csi->dev, "%s\n", __func__);
79
80 csi4_stream_write(chan, port_num, PPFSM_TIMEOUT_CTRL, 0);
81 csi4_stream_write(chan, port_num, PH_CHK_CTRL,
82 CFG_PH_CRC_CHK_EN | CFG_PH_ECC_CHK_EN);
83 csi4_stream_write(chan, port_num, VC0_DPCM_CTRL, 0);
84 csi4_stream_write(chan, port_num, VC0_DT_OVERRIDE, 0);
85
86 val = csi4_stream_read(chan, port_num, VC0_DPCM_CTRL);
87 dev_dbg(csi->dev, "%s (%d) read VC0_DPCM_CTRL = %08x\n",
88 __func__, port_num, val);
89}
90
91
92static void csi4_phy_config(
93 struct tegra_csi_channel *chan, int csi_port,
94 int csi_lanes, bool enable)
95{
96 struct tegra_csi_device *csi = chan->csi;
97 int phy_num = (csi_port & 0x6) >> 1;
98 bool cil_a = (csi_port & 0x1) ? false : true;
99 int cil_config;
100
101 dev_dbg(csi->dev, "%s\n", __func__);
102
103 /* set to DPHY */
104 csi4_phy_write(chan, phy_num, NVCSI_CIL_PHY_CTRL, DPHY);
105
106 /* read current NVCSI_CIL_CONFIG setting */
107 cil_config = csi4_phy_read(chan, phy_num, NVCSI_CIL_CONFIG);
108 dev_dbg(csi->dev, "NVCSI_CIL_CONFIG = %08x\n", cil_config);
109
110 if (cil_a) {
111 /* soft reset for data lane */
112 csi4_phy_write(chan, phy_num, NVCSI_CIL_A_SW_RESET,
113 SW_RESET1_EN | SW_RESET0_EN);
114 /* reset CSI lane number */
115 csi4_phy_write(chan, phy_num, NVCSI_CIL_CONFIG,
116 cil_config & ~DATA_LANE_A);
117 /* disable clock lane*/
118 csi4_phy_write(chan, phy_num,
119 NVCSI_CIL_A_PAD_CONFIG,
120 PD_CLK | PD_IO0 | PD_IO1 | SPARE_IO0 | SPARE_IO1);
121
122 /* setting up CIL B for 4 lane */
123 if (csi_lanes > 2) {
124 /* soft reset for data lane */
125 csi4_phy_write(chan, phy_num, NVCSI_CIL_B_SW_RESET,
126 SW_RESET1_EN | SW_RESET0_EN);
127 /* reset CSI lane number */
128 csi4_phy_write(chan, phy_num, NVCSI_CIL_CONFIG,
129 cil_config & ~DATA_LANE_B);
130 /* disable clock lane*/
131 csi4_phy_write(chan, phy_num,
132 NVCSI_CIL_B_PAD_CONFIG,
133 PD_CLK | PD_IO0 | PD_IO1 |
134 SPARE_IO0 | SPARE_IO1);
135 }
136
137 /* power down de-serializer is CIL B is not in use*/
138 if ((cil_config & DATA_LANE_B) == 0)
139 csi4_phy_write(chan, phy_num,
140 NVCSI_CIL_PAD_CONFIG, PDVCLAMP);
141 } else {
142 /* soft reset for data lane */
143 csi4_phy_write(chan, phy_num, NVCSI_CIL_B_SW_RESET,
144 SW_RESET1_EN | SW_RESET0_EN);
145 /* reset CSI lane number */
146 csi4_phy_write(chan, phy_num, NVCSI_CIL_CONFIG,
147 cil_config & ~DATA_LANE_B);
148 /* disable clock lane*/
149 csi4_phy_write(chan, phy_num,
150 NVCSI_CIL_B_PAD_CONFIG,
151 PD_CLK | PD_IO0 | PD_IO1 | SPARE_IO0 | SPARE_IO1);
152
153 /* power down de-serializer if CIL A is not in use*/
154 if ((cil_config & DATA_LANE_A) == 0)
155 csi4_phy_write(chan, phy_num,
156 NVCSI_CIL_PAD_CONFIG, PDVCLAMP);
157 }
158
159 if (!enable)
160 return;
161
162 /* power on de-serializer */
163 csi4_phy_write(chan, phy_num, NVCSI_CIL_PAD_CONFIG, 0);
164
165 if (cil_a) {
166 /* set CSI lane number */
167 csi4_phy_write(chan, phy_num, NVCSI_CIL_CONFIG,
168 (cil_config & ~DATA_LANE_A) |
169 (csi_lanes << DATA_LANE_A_OFFSET));
170 /* enable clock lane*/
171 csi4_phy_write(chan, phy_num,
172 NVCSI_CIL_A_PAD_CONFIG,
173 E_INPUT_LP_CLK | E_INPUT_LP_IO0 | E_INPUT_LP_IO1);
174 /* setup settle time */
175 csi4_phy_write(chan, phy_num,
176 NVCSI_CIL_A_CONTROL,
177 DEFAULT_DESKEW_COMPARE | DEFAULT_DESKEW_SETTLE |
178 DEFAULT_CLK_SETTLE |
179 T18X_BYPASS_LP_SEQ | DEFAULT_THS_SETTLE);
180 /* release soft reset */
181 csi4_phy_write(chan, phy_num, NVCSI_CIL_A_SW_RESET, 0x0);
182
183 /* setting up CIL B for 4 lane */
184 if (csi_lanes > 2) {
185 /* set CSI lane number */
186 csi4_phy_write(chan, phy_num, NVCSI_CIL_CONFIG,
187 csi_lanes << DATA_LANE_A_OFFSET);
188 /* enable clock lane*/
189 csi4_phy_write(chan, phy_num,
190 NVCSI_CIL_B_PAD_CONFIG,
191 E_INPUT_LP_IO0 | E_INPUT_LP_IO1 | PD_CLK);
192 /* setup settle time */
193 csi4_phy_write(chan, phy_num,
194 NVCSI_CIL_B_CONTROL,
195 DEFAULT_DESKEW_COMPARE | DEFAULT_DESKEW_SETTLE
196 | DEFAULT_CLK_SETTLE |
197 T18X_BYPASS_LP_SEQ | DEFAULT_THS_SETTLE);
198 /* release soft reset */
199 csi4_phy_write(chan, phy_num,
200 NVCSI_CIL_B_SW_RESET, 0x0);
201 }
202 } else {
203 /* set CSI lane number */
204 csi4_phy_write(chan, phy_num, NVCSI_CIL_CONFIG,
205 (cil_config & ~DATA_LANE_B) |
206 (csi_lanes << DATA_LANE_B_OFFSET));
207 /* enable clock lane*/
208 csi4_phy_write(chan, phy_num,
209 NVCSI_CIL_B_PAD_CONFIG,
210 E_INPUT_LP_CLK | E_INPUT_LP_IO0 | E_INPUT_LP_IO1);
211 /* setup settle time */
212 csi4_phy_write(chan, phy_num,
213 NVCSI_CIL_B_CONTROL,
214 DEFAULT_DESKEW_COMPARE | DEFAULT_DESKEW_SETTLE |
215 DEFAULT_CLK_SETTLE |
216 T18X_BYPASS_LP_SEQ | DEFAULT_THS_SETTLE);
217 /* release soft reset */
218 csi4_phy_write(chan, phy_num, NVCSI_CIL_B_SW_RESET, 0x0);
219 }
220}
221
222static void csi4_stream_check_status(
223 struct tegra_csi_channel *chan, int port_num)
224{
225 struct tegra_csi_device *csi = chan->csi;
226 int status = 0;
227
228 dev_dbg(csi->dev, "%s\n", __func__);
229 if (!chan->pg_mode) {
230 status = csi4_stream_read(chan, port_num, ERROR_STATUS2VI_VC0);
231 if (status)
232 dev_err(csi->dev,
233 "%s (%d) ERROR_STATUS2VI_VC0 = 0x%08x\n",
234 __func__, port_num, status);
235
236 status = csi4_stream_read(chan, port_num, ERROR_STATUS2VI_VC1);
237 if (status)
238 dev_err(csi->dev,
239 "%s (%d) ERROR_STATUS2VI_VC1 = 0x%08x\n",
240 __func__, port_num, status);
241
242 status = csi4_stream_read(chan, port_num, ERROR_STATUS2VI_VC2);
243 if (status)
244 dev_err(csi->dev,
245 "%s (%d) ERROR_STATUS2VI_VC2 = 0x%08x\n",
246 __func__, port_num, status);
247
248 status = csi4_stream_read(chan, port_num, ERROR_STATUS2VI_VC3);
249 if (status)
250 dev_err(csi->dev,
251 "%s (%d) ERROR_STATUS2VI_VC2 = 0x%08x\n",
252 __func__, port_num, status);
253 }
254 status = csi4_stream_read(chan, port_num, INTR_STATUS);
255 if (status)
256 dev_err(csi->dev,
257 "%s (%d) INTR_STATUS 0x%08x\n",
258 __func__, port_num, status);
259
260 status = csi4_stream_read(chan, port_num, ERR_INTR_STATUS);
261 if (status)
262 dev_err(csi->dev,
263 "%s (%d) ERR_INTR_STATUS 0x%08x\n",
264 __func__, port_num, status);
265}
266
267static void csi4_cil_check_status(struct tegra_csi_channel *chan, int port_num)
268{
269 struct tegra_csi_device *csi = chan->csi;
270 int status = 0;
271
272 dev_dbg(csi->dev, "%s %d\n", __func__, __LINE__);
273
274 status = csi4_stream_read(chan, port_num, CIL_INTR_STATUS);
275 if (status)
276 dev_err(csi->dev,
277 "%s (%d) CIL_INTR_STATUS 0x%08x\n",
278 __func__, port_num, status);
279
280 status = csi4_stream_read(chan, port_num, CIL_ERR_INTR_STATUS);
281 if (status)
282 dev_err(csi->dev,
283 "%s (%d) CIL_ERR_INTR_STATUS 0x%08x\n",
284 __func__, port_num, status);
285}
286
287
288int csi4_power_on(struct tegra_csi_device *csi)
289{
290 int err = 0;
291
292 err = nvhost_module_busy(csi->pdev);
293 if (err)
294 dev_err(csi->dev, "%s:cannot enable csi\n", __func__);
295
296 return err;
297}
298
299int csi4_power_off(struct tegra_csi_device *csi)
300{
301 nvhost_module_idle(csi->pdev);
302
303 return 0;
304}
305
306static void csi4_tpg_stop_streaming(struct tegra_csi_channel *chan,
307 int ports_index)
308{
309 unsigned int csi_port = chan->ports[ports_index].num;
310 struct tegra_csi_device *csi = chan->csi;
311
312 dev_dbg(csi->dev, "%s\n", __func__);
313 csi4_stream_check_status(chan, csi_port);
314 csi4_cil_check_status(chan, csi_port);
315 csi4_stream_write(chan, csi_port, PP_EN_CTRL, 0);
316 csi4_stream_write(chan, csi_port, TPG_EN_0, 0);
317 csi4_stream_write(chan, csi_port, PG_CTRL, PG_DISABLE);
318}
319static int csi4_tpg_start_streaming(struct tegra_csi_channel *chan,
320 enum tegra_csi_port_num port_num)
321{
322 struct tegra_csi_port *port = &chan->ports[port_num];
323 struct tegra_csi_device *csi = chan->csi;
324 unsigned int val, csi_port, csi_lanes;
325
326 if (!port->core_format) {
327 dev_err(csi->dev, "Fail to find tegra video fmt");
328 return -EINVAL;
329 }
330
331 csi_port = port->num;
332 csi_lanes = port->lanes;
333 dev_dbg(csi->dev, "%s CSI port=%d, # lanes=%d\n",
334 __func__, csi_port, csi_lanes);
335
336 csi4_stream_write(chan, csi_port, PH_CHK_CTRL, 0);
337 csi4_stream_write(chan, csi_port, INTR_MASK, PH_ECC_MULTI_BIT_ERR |
338 PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
339 csi4_stream_write(chan, csi_port, ERR_INTR_MASK, PH_ECC_MULTI_BIT_ERR |
340 PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
341 csi4_stream_write(chan, csi_port, ERROR_STATUS2VI_MASK,
342 CFG_ERR_STATUS2VI_MASK_VC0 |
343 CFG_ERR_STATUS2VI_MASK_VC1 |
344 CFG_ERR_STATUS2VI_MASK_VC2 |
345 CFG_ERR_STATUS2VI_MASK_VC3);
346 /* calculate PG blank */
347 csi4_stream_write(chan, csi_port, PG_BLANK,
348 ((port->v_blank & PG_VBLANK_MASK) << PG_VBLANK_OFFSET) |
349 ((port->h_blank & PG_HBLANK_MASK) << PG_HBLANK_OFFSET));
350 csi4_stream_write(chan, csi_port, PG_PHASE, 0x0);
351 csi4_stream_write(chan, csi_port, PG_RED_FREQ,
352 (0x10 << PG_VERT_INIT_FREQ_OFFSET)|
353 (0x10 << PG_HOR_INIT_FREQ_OFFSET));
354 csi4_stream_write(chan, csi_port, PG_RED_FREQ_RATE, 0x0);
355 csi4_stream_write(chan, csi_port, PG_GREEN_FREQ,
356 (0x10 << PG_VERT_INIT_FREQ_OFFSET)|
357 (0x10 << PG_HOR_INIT_FREQ_OFFSET));
358 csi4_stream_write(chan, csi_port, PG_GREEN_FREQ_RATE, 0x0);
359 csi4_stream_write(chan, csi_port, PG_BLUE_FREQ,
360 (0x10 << PG_VERT_INIT_FREQ_OFFSET)|
361 (0x10 << PG_HOR_INIT_FREQ_OFFSET));
362 csi4_stream_write(chan, csi_port, PG_BLUE_FREQ_RATE, 0x0);
363 /* calculate PG IMAGE SIZE and DT */
364 mutex_lock(&chan->format_lock);
365 val = port->format.height << HEIGHT_OFFSET |
366 (port->format.width *
367 (port->core_format->vf_code == TEGRA_VF_RAW10 ? 10 : 24) / 8);
368 mutex_unlock(&chan->format_lock);
369 csi4_stream_write(chan, csi_port, PG_IMAGE_SIZE, val);
370 csi4_stream_write(chan, csi_port, PG_IMAGE_DT,
371 port->core_format->img_dt);
372 csi4_stream_write(chan, csi_port, PP_EN_CTRL, CFG_PP_EN);
373 csi4_stream_write(chan, csi_port, TPG_EN_0, cfg_tpg_en);
374
375 csi4_stream_write(chan, csi_port, PG_CTRL,
376 ((chan->pg_mode - 1) << PG_MODE_OFFSET) | PG_ENABLE);
377 return 0;
378}
379int csi4_hw_init(struct tegra_csi_device *csi)
380{
381 csi->iomem[0] = csi->iomem_base + TEGRA_CSI_STREAM_0_BASE;
382 csi->iomem[1] = csi->iomem_base + TEGRA_CSI_STREAM_2_BASE;
383 csi->iomem[2] = csi->iomem_base + TEGRA_CSI_STREAM_4_BASE;
384
385 return 0;
386}
387int csi4_start_streaming(struct tegra_csi_channel *chan,
388 enum tegra_csi_port_num port_num)
389{
390 struct tegra_csi_device *csi = chan->csi;
391 int csi_port, csi_lanes, ret = 0;
392
393 csi_port = chan->ports[port_num].num;
394 csi_lanes = chan->ports[port_num].lanes;
395 dev_dbg(csi->dev, "%s ports index=%d, lanes=%d\n",
396 __func__, csi_port, csi_lanes);
397
398 if (chan->pg_mode)
399 ret = csi4_tpg_start_streaming(chan, port_num);
400 else {
401 csi4_stream_init(chan, csi_port);
402 csi4_stream_config(chan, csi_port);
403 /* enable DPHY */
404 csi4_phy_config(chan, csi_port, csi_lanes, true);
405 csi4_stream_write(chan, csi_port, PP_EN_CTRL, CFG_PP_EN);
406 }
407 return ret;
408}
409
410void csi4_stop_streaming(struct tegra_csi_channel *chan,
411 enum tegra_csi_port_num port_num)
412{
413 struct tegra_csi_device *csi = chan->csi;
414 int csi_port, csi_lanes;
415
416 dev_dbg(csi->dev, "%s ports index=%d, lanes=%d\n",
417 __func__, port_num, chan->numlanes);
418
419 csi_port = chan->ports[port_num].num;
420 csi_lanes = chan->ports[port_num].lanes;
421
422 if (chan->pg_mode)
423 csi4_tpg_stop_streaming(chan, port_num);
424 else {
425 /* disable DPHY */
426 csi4_phy_config(chan, csi_port, csi_lanes, false);
427 csi4_stream_check_status(chan, csi_port);
428 csi4_cil_check_status(chan, csi_port);
429 }
430}
431
432void csi4_override_format(struct tegra_csi_channel *chan,
433 enum tegra_csi_port_num port_num)
434{
435 struct tegra_csi_port *port = &chan->ports[port_num];
436 unsigned int val;
437 int csi_port;
438
439 if (!chan->pg_mode) {
440 dev_err(chan->csi->dev, "%s non PG format update failed\n",
441 __func__);
442 return;
443 }
444
445 /* calculate PG IMAGE SIZE and DT */
446 mutex_lock(&chan->format_lock);
447 val = port->format.height << HEIGHT_OFFSET |
448 (port->format.width *
449 (port->core_format->vf_code == TEGRA_VF_RAW10 ? 10 : 24) / 8);
450 mutex_unlock(&chan->format_lock);
451
452 csi_port = chan->ports[port_num].num;
453 csi4_stream_write(chan, csi_port, PG_IMAGE_SIZE, val);
454}
455
456int csi4_mipi_cal(struct tegra_csi_channel *chan)
457{
458 unsigned int lanes, num_ports, port, addr;
459 unsigned int cila, cilb;
460 struct tegra_csi_device *csi = chan->csi;
461
462 lanes = 0;
463 num_ports = 0;
464 port = 0;
465 while (num_ports < chan->numports) {
466 port = chan->ports[num_ports].num;
467 dev_dbg(csi->dev, "csi port:%d\n", port);
468
469 if (chan->numlanes == 2) {
470 lanes |= CSIA << port;
471 cila = (0x01 << E_INPUT_LP_IO0_SHIFT) |
472 (0x01 << E_INPUT_LP_IO1_SHIFT) |
473 (0x01 << E_INPUT_LP_CLK_SHIFT) |
474 (0x00 << PD_CLK_SHIFT) |
475 (0x00 << PD_IO0_SHIFT) |
476 (0x00 << PD_IO1_SHIFT);
477 addr = (port % 2 == 0 ?
478 NVCSI_CIL_A_BASE : NVCSI_CIL_B_BASE)
479 + PAD_CONFIG_0;
480 csi4_phy_write(chan, port >> 1, addr, cila);
481 } else {
482 lanes |= (CSIA | CSIB) << port;
483 cila = (0x01 << E_INPUT_LP_IO0_SHIFT) |
484 (0x01 << E_INPUT_LP_IO1_SHIFT) |
485 (0x01 << E_INPUT_LP_CLK_SHIFT) |
486 (0x00 << PD_CLK_SHIFT) |
487 (0x00 << PD_IO0_SHIFT) |
488 (0x00 << PD_IO1_SHIFT);
489 cilb = (0x01 << E_INPUT_LP_IO0_SHIFT) |
490 (0x01 << E_INPUT_LP_IO1_SHIFT) |
491 (0x01 << PD_CLK_SHIFT) |
492 (0x00 << PD_IO0_SHIFT) |
493 (0x00 << PD_IO1_SHIFT);
494 csi4_phy_write(chan, port >> 1,
495 NVCSI_CIL_A_BASE + PAD_CONFIG_0, cila);
496 csi4_phy_write(chan, port >> 1,
497 NVCSI_CIL_B_BASE + PAD_CONFIG_0, cilb);
498 }
499 num_ports++;
500 }
501 if (!lanes) {
502 dev_err(csi->dev, "Selected no CSI lane, cannot do calibration");
503 return -EINVAL;
504 }
505 return tegra_mipi_calibration(lanes);
506}
diff --git a/drivers/media/platform/tegra/camera/csi/csi4_fops.h b/drivers/media/platform/tegra/camera/csi/csi4_fops.h
new file mode 100644
index 000000000..49f0aa8ad
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi4_fops.h
@@ -0,0 +1,41 @@
1/*
2 * Tegra CSI4 device common APIs
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * Author: Frank Chen <frankc@nvidia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __CSI4_H__
16#define __CSI4_H__
17
18#include "csi.h"
19
20int csi4_power_on(struct tegra_csi_device *csi);
21int csi4_power_off(struct tegra_csi_device *csi);
22int csi4_start_streaming(struct tegra_csi_channel *chacsin,
23 enum tegra_csi_port_num port_num);
24void csi4_stop_streaming(struct tegra_csi_channel *chan,
25 enum tegra_csi_port_num port_num);
26void csi4_override_format(struct tegra_csi_channel *chan,
27 enum tegra_csi_port_num port_num);
28int csi4_mipi_cal(struct tegra_csi_channel *chan);
29int csi4_hw_init(struct tegra_csi_device *csi);
30
31struct tegra_csi_fops csi4_fops = {
32 .csi_power_on = csi4_power_on,
33 .csi_power_off = csi4_power_off,
34 .csi_start_streaming = csi4_start_streaming,
35 .csi_stop_streaming = csi4_stop_streaming,
36 .csi_override_format = csi4_override_format,
37 .mipical = csi4_mipi_cal,
38 .hw_init = csi4_hw_init,
39};
40
41#endif
diff --git a/drivers/media/platform/tegra/camera/csi/csi4_registers.h b/drivers/media/platform/tegra/camera/csi/csi4_registers.h
new file mode 100644
index 000000000..ed4ef936c
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/csi/csi4_registers.h
@@ -0,0 +1,196 @@
1/*
2 * drivers/media/platform/tegra/camera/csi/csi4_registers.h
3 *
4 * Tegra 18x CSI register offsets
5 *
6 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __CSI4_REGISTERS_H__
22#define __CSI4_REGISTERS_H__
23
24#define CSI4_BASE_ADDRESS 0x18000
25#define CSI4_PHY_OFFSET 0x10000
26#define CSI4_STREAM_OFFSET 0x800
27
28#define CSI_PORTS (6)
29#define PHY_BRICKS (3)
30
31/* NVCSI registers. Starts from 0x0 */
32#define CFG_NVCSI_INCR_SYNCPT_CNTRL 0x04
33
34/* NVCSI_STREAM registers */
35#define TEGRA_CSI_STREAM_0_BASE 0x010000
36#define TEGRA_CSI_STREAM_1_BASE 0x010800
37#define TEGRA_CSI_STREAM_2_BASE 0x020000
38#define TEGRA_CSI_STREAM_3_BASE 0x020800
39#define TEGRA_CSI_STREAM_4_BASE 0x030000
40#define TEGRA_CSI_STREAM_5_BASE 0x030800
41
42#define PP_EN_CTRL 0x08
43#define CFG_PP_EN (0x1 << 0)
44
45#define PPFSM_TIMEOUT_CTRL 0x6c
46#define CFG_TIMEOUT_EN (0x1 << 31)
47#define CFG_TIMEOUT_PERIOD (0x7fffffff << 0)
48
49#define VC0_DT_OVERRIDE 0x20
50#define CFG_VC0_DT_OVERRIDE_EN (0x1 << 31)
51#define CFG_VC0_DT_OVERRIDE (0x3f << 0)
52
53#define PH_CHK_CTRL 0x70
54#define CFG_PH_CRC_CHK_EN (0x1 << 1)
55#define CFG_PH_ECC_CHK_EN (0x1 << 0)
56
57#define VC0_DPCM_CTRL 0x74
58#define CFG_VC0_DPCM_COMPRESSION_RATIO (0xf << 0)
59
60#define ERROR_STATUS2VI_MASK 0x90
61
62/* T186 TPG */
63#define TPG_EN_0 0x0b8
64#define cfg_tpg_en 0x1
65/* NVCSI_STREAM Legacy T210 PG*/
66#define PG_CTRL 0x194
67#define PG_MODE_OFFSET 2
68#define PG_ENABLE 0x1
69#define PG_DISABLE 0x0
70#define PG_BLANK 0x198
71#define PG_VBLANK_MASK 0xffff
72#define PG_HBLANK_MASK 0xffff
73#define PG_VBLANK_OFFSET 16
74#define PG_HBLANK_OFFSET 0
75#define PG_PHASE 0x19c
76#define PG_RED_FREQ 0x1a0
77#define PG_VERT_INIT_FREQ_OFFSET 16
78#define PG_HOR_INIT_FREQ_OFFSET 0
79#define PG_RED_FREQ_RATE 0x1a4
80#define PG_GREEN_FREQ 0x1a8
81#define PG_GREEN_FREQ_RATE 0x1ac
82#define PG_BLUE_FREQ 0x1b0
83#define PG_BLUE_FREQ_RATE 0X1b4
84#define PG_AOHDR 0x1b8
85#define PG_IMAGE_SIZE 0x1bc
86#define HEIGHT_OFFSET 16
87#define PG_IMAGE_DT 0x1c0
88
89/* TODO - double check if rr_status2vi_vc0:[0] means bit or value */
90#define ERROR_STATUS2VI_VC0 0x94
91#define ERROR_STATUS2VI_VC1 0x98
92#define ERROR_STATUS2VI_VC2 0x9c
93#define ERROR_STATUS2VI_VC3 0xa0
94#define ERR_STATUS2VI_VC (0xf << 0)
95#define ERR_PP_FSM_TIMEOUT (0)
96#define ERR_PH_ECC_SINGLE_BIT (1)
97#define ERR_PACKET_PAYLOAD_CRC (2)
98#define ERR_PACKET_PAYLOAD_LESS (3)
99
100#define INTR_STATUS 0xa4
101#define INTR_MASK 0xa8
102#define PD_CRC_ERR_VC0 (0x1 << 2)
103#define PH_ECC_SINGLE_BIT_ERR_VC0 (0x1 << 1)
104#define PH_ECC_MULTI_BIT_ERR (0x1 << 16)
105#define ERR_INTR_STATUS 0xac
106#define ERR_INTR_MASK 0xb0
107#define MASK_PH_CRC_ERR (0x1 << 17)
108#define MASK_PH_ECC_MULTI_BIT_ERR (0x1 << 16)
109#define MASK_PD_WC_SHORT_ERR_VC3 (0x1 << 15)
110#define MASK_PD_CRC_ERR_VC3 (0x1 << 14)
111#define MASK_PH_ECC_SINGLE_BIT_ERR_VC3 (0x1 << 13)
112#define MASK_PPFSM_TIMEOUT_VC3 (0x1 << 12)
113#define MASK_PD_WC_SHORT_ERR_VC2 (0x1 << 11)
114#define MASK_PD_CRC_ERR_VC2 (0x1 << 10)
115#define MASK_PH_ECC_SINGLE_BIT_ERR_VC2 (0x1 << 9)
116#define MASK_PPFSM_TIMEOUT_VC2 (0x1 << 8)
117#define MASK_PD_WC_SHORT_ERR_VC1 (0x1 << 7)
118#define MASK_PD_CRC_ERR_VC1 (0x1 << 6)
119#define MASK_PH_ECC_SINGLE_BIT_ERR_VC1 (0x1 << 5)
120#define MASK_PPFSM_TIMEOUT_VC1 (0x1 << 4)
121#define MASK_PD_WC_SHORT_ERR_VC0 (0x1 << 3)
122#define MASK_PD_CRC_ERR_VC0 (0x1 << 2)
123#define MASK_PH_ECC_SINGLE_BIT_ERR_VC0 (0x1 << 1)
124#define MASK_PPFSM_TIMEOUT_VC0 (0x1 << 0)
125/* For ERR_INTR_MASK and ERR_INTR_MASK */
126#define MASK_HSM_INTR_SW_TRIGGER (0x1 << 18)
127
128/* NVCSI_PHY CIL registers */
129#define NVCSI_PHY_0_CILA_BASE 0x010400
130#define NVCSI_PHY_0_CILB_BASE 0x010C00
131#define NVCSI_PHY_1_CILA_BASE 0x020400
132#define NVCSI_PHY_1_CILB_BASE 0x020C00
133#define NVCSI_PHY_2_CILA_BASE 0x030400
134#define NVCSI_PHY_2_CILB_BASE 0x030C00
135
136#define CIL_INTR_STATUS 0x400
137#define CIL_INTR_MASK 0x404
138#define CIL_ERR_INTR_STATUS 0x408
139#define CIL_ERR_INTR_MASK 0x40c
140
141/* NVCSI_PHY registers */
142#define NVCSI_CIL_PHY_CTRL 0x00
143#define CFG_PHY_MODE (0x1 << 0)
144#define DPHY (0)
145#define CPHY (1)
146
147#define NVCSI_CIL_CONFIG 0x04
148#define DATA_LANE_B_OFFSET 0x8
149#define DATA_LANE_A_OFFSET 0x0
150#define DATA_LANE_B (0x7 << DATA_LANE_B_OFFSET)
151#define DATA_LANE_A (0x7 << DATA_LANE_A_OFFSET)
152
153#define NVCSI_CIL_PAD_CONFIG 0x0c
154#define LOADADJ (0xf << 12)
155#define PDVCLAMP (0x1 << 9)
156#define E_VCLAMP (0x1 << 8)
157#define SPARE_TOP (0xff << 0)
158
159#define NVCSI_CIL_A_SW_RESET 0x18
160#define NVCSI_CIL_B_SW_RESET 0x7c
161#define SW_RESET1_EN (0x1 << 1)
162#define SW_RESET0_EN (0x1 << 0)
163
164#define NVCSI_CIL_A_PAD_CONFIG 0x20
165#define NVCSI_CIL_B_PAD_CONFIG 0x84
166#define E_INPUT_LP_IO1_SHIFT 22
167#define E_INPUT_LP_IO0_SHIFT 21
168#define E_INPUT_LP_CLK_SHIFT 20
169#define E_INPUT_LP_IO1 (0x1 << 22)
170#define E_INPUT_LP_IO0 (0x1 << 21)
171#define E_INPUT_LP_CLK (0x1 << 20)
172#define BANDWD_IN (0x1 << 19)
173#define PD_CLK (0x1 << 18)
174#define PD_IO1 (0x1 << 17)
175#define PD_IO0 (0x1 << 16)
176#define PD_CLK_SHIFT 18
177#define PD_IO1_SHIFT 17
178#define PD_IO0_SHIFT 16
179#define SPARE_CLK (0x1 << 8)
180#define SPARE_IO1 (0x1 << 4)
181#define SPARE_IO0 (0x1 << 0)
182
183#define NVCSI_CIL_A_CONTROL 0x5c
184#define NVCSI_CIL_B_CONTROL 0xc0
185#define DEFAULT_DESKEW_COMPARE (0x4 << 20)
186#define DEFAULT_DESKEW_SETTLE (0x6 << 16)
187#define DEFAULT_CLK_SETTLE (0x21 << 8)
188#define T18X_BYPASS_LP_SEQ (0x1 << 7)
189#define DEFAULT_THS_SETTLE (0x14 << 0)
190
191/* MIPICAL */
192#define NVCSI_CIL_A_BASE 0x18
193#define NVCSI_CIL_B_BASE 0x7c
194#define PAD_CONFIG_0 0x8
195
196#endif /* __CSI4_REGISTERS_H__ */
diff --git a/drivers/media/platform/tegra/camera/sensor_common.c b/drivers/media/platform/tegra/camera/sensor_common.c
new file mode 100644
index 000000000..b1504e61d
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/sensor_common.c
@@ -0,0 +1,329 @@
1/*
2 * sensor_common.c - utilities for tegra sensor drivers
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <media/sensor_common.h>
20#include <linux/of_graph.h>
21#include <linux/string.h>
22
23static int read_property_u32(
24 struct device_node *node, const char *name, u32 *value)
25{
26 const char *str;
27 int err = 0;
28
29 err = of_property_read_string(node, name, &str);
30 if (err)
31 return -ENODATA;
32
33 err = kstrtou32(str, 10, value);
34 if (err)
35 return -EFAULT;
36
37 return 0;
38}
39
40static int read_property_u64(
41 struct device_node *node, const char *name, u64 *value)
42{
43 const char *str;
44 int err = 0;
45
46 err = of_property_read_string(node, name, &str);
47 if (err)
48 return -ENODATA;
49
50 err = kstrtou64(str, 10, value);
51 if (err)
52 return -EFAULT;
53
54 return 0;
55}
56
57static int sensor_common_parse_signal_props(
58 struct device *dev, struct device_node *node,
59 struct sensor_signal_properties *signal)
60{
61 const char *temp_str;
62 int err = 0;
63
64 /* Do not report error for these properties yet */
65 read_property_u32(node, "readout_orientation",
66 &signal->readout_orientation);
67 read_property_u32(node, "num_lanes",
68 &signal->num_lanes);
69 read_property_u32(node, "mclk_khz",
70 &signal->mclk_freq);
71 read_property_u64(node, "pix_clk_hz",
72 &signal->pixel_clock.val);
73 read_property_u32(node, "cil_settletime",
74 &signal->cil_settletime);
75 /* initialize default if this prop not available */
76 err = of_property_read_string(node, "discontinuous_clk",
77 &temp_str);
78 if (!err)
79 signal->discontinuous_clk =
80 !strncmp(temp_str, "yes", sizeof("yes"));
81 else
82 signal->discontinuous_clk = 1;
83 /* initialize default if this prop not available */
84 err = of_property_read_string(node, "dpcm_enable",
85 &temp_str);
86 if (!err)
87 signal->dpcm_enable =
88 !strncmp(temp_str, "true", sizeof("true"));
89 else
90 signal->dpcm_enable = 0;
91
92 return 0;
93}
94
95static int extract_pixel_format(
96 const char *pixel_t, u32 *format)
97{
98 size_t size = strnlen(pixel_t, OF_MAX_STR_LEN);
99
100 if (strncmp(pixel_t, "bayer_bggr10", size) == 0)
101 *format = V4L2_PIX_FMT_SBGGR10;
102 else if (strncmp(pixel_t, "bayer_rggb10", size) == 0)
103 *format = V4L2_PIX_FMT_SRGGB10;
104 else if (strncmp(pixel_t, "bayer_bggr12", size) == 0)
105 *format = V4L2_PIX_FMT_SBGGR12;
106 else if (strncmp(pixel_t, "bayer_rggb12", size) == 0)
107 *format = V4L2_PIX_FMT_SRGGB12;
108 else if (strncmp(pixel_t, "bayer_xbggr10p", size) == 0)
109 *format = V4L2_PIX_FMT_XBGGR10P;
110 else if (strncmp(pixel_t, "bayer_xrggb10p", size) == 0)
111 *format = V4L2_PIX_FMT_XRGGB10P;
112 else {
113 pr_err("%s: Need to extend format%s\n", __func__, pixel_t);
114 return -EINVAL;
115 }
116
117 return 0;
118}
119
120static int sensor_common_parse_image_props(
121 struct device *dev, struct device_node *node,
122 struct sensor_image_properties *image)
123{
124 const char *temp_str;
125 int err = 0;
126
127 err = read_property_u32(node, "active_w",
128 &image->width);
129 if (err) {
130 dev_err(dev, "%s:active_w property missing\n", __func__);
131 goto fail;
132 }
133
134 err = read_property_u32(node, "active_h",
135 &image->height);
136 if (err) {
137 dev_err(dev, "%s:active_h property missing\n", __func__);
138 goto fail;
139 }
140
141 err = read_property_u32(node, "line_length",
142 &image->line_length);
143 if (err) {
144 dev_err(dev, "%s:Line length property missing\n", __func__);
145 goto fail;
146 }
147
148 err = of_property_read_string(node, "pixel_t",
149 &temp_str);
150 if (err) {
151 dev_err(dev, "%s:pixel_t property missing\n", __func__);
152 goto fail;
153 }
154
155 err = extract_pixel_format(temp_str, &image->pixel_format);
156 if (err) {
157 dev_err(dev, "Unsupported pixel format\n");
158 goto fail;
159 }
160
161 /* ignore err for this prop */
162 read_property_u32(node, "embedded_metadata_height",
163 &image->embedded_metadata_height);
164
165fail:
166 return err;
167}
168
169static int sensor_common_parse_dv_timings(
170 struct device *dev, struct device_node *node,
171 struct sensor_dv_timings *timings)
172{
173 /* Do not report error for these properties yet */
174 read_property_u32(node, "horz_front_porch",
175 &timings->hfrontporch);
176 read_property_u32(node, "horz_sync",
177 &timings->hsync);
178 read_property_u32(node, "horz_back_porch",
179 &timings->hbackporch);
180 read_property_u32(node, "vert_front_porch",
181 &timings->vfrontporch);
182 read_property_u32(node, "vert_sync",
183 &timings->vsync);
184 read_property_u32(node, "vert_back_porch",
185 &timings->vbackporch);
186
187 return 0;
188}
189
190static int sensor_common_parse_control_props(
191 struct device *dev, struct device_node *node,
192 struct sensor_control_properties *control)
193{
194 int err = 0;
195
196 err = read_property_u32(node, "gain_factor",
197 &control->gain_factor);
198 if (err)
199 dev_err(dev, "%s:%s:property missing\n",
200 __func__, "gain_factor");
201
202 err = read_property_u32(node, "framerate_factor",
203 &control->framerate_factor);
204 if (err)
205 dev_err(dev, "%s:%s:property missing\n",
206 __func__, "framerate_factor");
207
208 /* ignore err for this prop */
209 err = read_property_u32(node, "inherent_gain",
210 &control->inherent_gain);
211
212 err = read_property_u32(node, "min_gain_val",
213 &control->min_gain_val);
214 if (err)
215 dev_err(dev, "%s:%s:property missing\n",
216 __func__, "min_gain_val");
217
218 err = read_property_u32(node, "max_gain_val",
219 &control->max_gain_val);
220 if (err)
221 dev_err(dev, "%s:%s:property missing\n",
222 __func__, "max_gain_val");
223
224 /* ignore err for this prop */
225 err = read_property_u32(node, "min_hdr_ratio",
226 &control->min_hdr_ratio);
227 err = read_property_u32(node, "max_hdr_ratio",
228 &control->max_hdr_ratio);
229
230 err = read_property_u32(node, "min_framerate",
231 &control->min_framerate);
232 if (err)
233 dev_err(dev, "%s:%s:property missing\n",
234 __func__, "min_framerate");
235
236 err = read_property_u32(node, "max_framerate",
237 &control->max_framerate);
238 if (err)
239 dev_err(dev, "%s:%s:property missing\n",
240 __func__, "max_framerate");
241
242 err = read_property_u64(node, "min_exp_time",
243 &control->min_exp_time.val);
244 if (err)
245 dev_err(dev, "%s:%s:property missing\n",
246 __func__, "min_exp_time");
247
248 err = read_property_u64(node, "max_exp_time",
249 &control->max_exp_time.val);
250 if (err)
251 dev_err(dev, "%s:%s:property missing\n",
252 __func__, "max_exp_time");
253
254
255 return err;
256}
257
258int sensor_common_init_sensor_properties(
259 struct device *dev, struct device_node *node,
260 struct sensor_properties *sensor)
261{
262 char temp_str[OF_MAX_STR_LEN];
263 struct device_node *temp_node;
264 int num_modes = 0;
265 int err, i;
266
267 /* get number of modes */
268 for (i = 0; num_modes < MAX_NUM_SENSOR_MODES; i++) {
269 snprintf(temp_str, sizeof(temp_str), "%s%d",
270 OF_SENSORMODE_PREFIX, i);
271 temp_node = of_find_node_by_name(node, temp_str);
272 if (temp_node == NULL)
273 break;
274 num_modes++;
275 }
276 sensor->num_modes = num_modes;
277
278 sensor->sensor_modes = devm_kzalloc(dev,
279 num_modes * sizeof(struct sensor_mode_properties),
280 GFP_KERNEL);
281 if (!sensor->sensor_modes) {
282 dev_err(dev, "Failed to allocate memory for sensor modes\n");
283 return -ENOMEM;
284 }
285 memset(sensor->sensor_modes, 0, num_modes *
286 sizeof(struct sensor_mode_properties));
287
288 for (i = 0; i < num_modes; i++) {
289 snprintf(temp_str, sizeof(temp_str), "%s%d",
290 OF_SENSORMODE_PREFIX, i);
291
292 temp_node = of_find_node_by_name(node, temp_str);
293 if (temp_node == NULL) {
294 dev_err(dev, "Failed to find mode\n");
295 return -ENODATA;
296 };
297
298 err = sensor_common_parse_signal_props(dev, temp_node,
299 &sensor->sensor_modes[i].signal_properties);
300 if (err) {
301 dev_err(dev, "Failed to read signal properties\n");
302 return err;
303 }
304
305 err = sensor_common_parse_image_props(dev, temp_node,
306 &sensor->sensor_modes[i].image_properties);
307 if (err) {
308 dev_err(dev, "Failed to read image properties\n");
309 return err;
310 }
311
312 err = sensor_common_parse_dv_timings(dev, temp_node,
313 &sensor->sensor_modes[i].dv_timings);
314 if (err) {
315 dev_err(dev, "Failed to read DV timings\n");
316 return err;
317 }
318
319 err = sensor_common_parse_control_props(dev, temp_node,
320 &sensor->sensor_modes[i].control_properties);
321 if (err) {
322 dev_err(dev, "Failed to read control properties\n");
323 return err;
324 }
325 }
326
327 return 0;
328}
329EXPORT_SYMBOL(sensor_common_init_sensor_properties);
diff --git a/drivers/media/platform/tegra/camera/vi/Makefile b/drivers/media/platform/tegra/camera/vi/Makefile
new file mode 100644
index 000000000..11bce8f3b
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/Makefile
@@ -0,0 +1,21 @@
1GCOV_PROFILE := y
2ccflags-y += -I../nvhost/drivers/video/tegra/host
3ccflags-y += -Idrivers/video/tegra/host
4ccflags-y += -Idrivers/video/tegra/camera
5ccflags-y += -Idrivers/media/platform/tegra
6ccflags-y += -Werror
7
8ifeq ($(CONFIG_ARCH_TEGRA_18x_SOC),y)
9ccflags-y += -I../t18x/drivers/video/tegra/host/
10ccflags-y += -I../t18x/include
11ccflags-y += -I../nvhost/include
12obj-y += mc_common.o core.o channel.o graph.o vi2_fops.o vi4_fops.o
13endif
14
15obj-$(CONFIG_TEGRA_CAMERA_RTCPU) += capture.o
16
17ifeq ($(CONFIG_ARCH_TEGRA_210_SOC),y)
18ccflags-y += -I../nvhost/include
19ccflags-y += -I../t18x/drivers/video/tegra/host/
20obj-y += mc_common.o core.o channel.o graph.o vi2_fops.o
21endif
diff --git a/drivers/media/platform/tegra/camera/vi/capture.c b/drivers/media/platform/tegra/camera/vi/capture.c
new file mode 100644
index 000000000..7a8083098
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/capture.c
@@ -0,0 +1,880 @@
1/*
2 * Tegra Video Input capture operations
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
7 *
8 * Author: David Wang <davidw@nvidia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/completion.h>
16#include <linux/dma-buf.h>
17#include <linux/nvhost.h>
18#include <linux/of_platform.h>
19#include <linux/printk.h>
20#include <linux/scatterlist.h>
21#include <linux/tegra-capture-ivc.h>
22#include <media/capture.h>
23
24#include "soc/tegra/camrtc-capture.h"
25#include "soc/tegra/camrtc-capture-messages.h"
26#include "mc_common.h"
27
28
29#define CAPTURE_CHANNEL_UNKNOWN_RESP 0xFFFFFFFF
30#define CAPTURE_CHANNEL_INVALID_ID 0xFFFF
31#define CAPTURE_CHANNEL_INVALID_MASK 0llu
32#define PROGRESS_SP_IDX 0
33#define EMBDATA_SP_IDX 1
34#define LINETIMER_SP_IDX 2
35#define CAPTURE_CHANNEL_MAX_NUM_SPS 3
36
37struct vi_capture_buf {
38 struct dma_buf *buf;
39 struct dma_buf_attachment *attach;
40 struct sg_table *sgt;
41 dma_addr_t iova;
42};
43
44struct vi_capture_unpins {
45 uint32_t num_unpins;
46 struct vi_capture_buf data[];
47};
48
49struct vi_capture {
50 uint16_t channel_id;
51 struct device *rtcpu_dev;
52 struct tegra_channel *vi_channel;
53 struct vi_capture_buf requests;
54 uint32_t request_size;
55
56 uint32_t syncpts[CAPTURE_CHANNEL_MAX_NUM_SPS];
57
58 struct completion control_resp;
59 struct completion capture_resp;
60 struct mutex control_msg_lock;
61 struct CAPTURE_CONTROL_MSG control_resp_msg;
62
63 struct mutex unpins_list_lock;
64 struct vi_capture_unpins *unpins_list;
65};
66
67static void vi_capture_ivc_control_callback(const void *ivc_resp,
68 const void *pcontext)
69{
70 const struct CAPTURE_CONTROL_MSG *control_msg = ivc_resp;
71 struct vi_capture *capture = (struct vi_capture *)pcontext;
72 struct tegra_channel *chan = capture->vi_channel;
73
74 if (unlikely(capture == NULL)) {
75 dev_err(chan->vi->dev, "%s: invalid context", __func__);
76 return;
77 }
78
79 if (unlikely(control_msg == NULL)) {
80 dev_err(chan->vi->dev, "%s: invalid response", __func__);
81 return;
82 }
83
84 switch (control_msg->header.msg_id) {
85 case CAPTURE_CHANNEL_SETUP_RESP:
86 case CAPTURE_CHANNEL_RESET_RESP:
87 case CAPTURE_CHANNEL_RELEASE_RESP:
88 case CAPTURE_COMPAND_CONFIG_RESP:
89 case CAPTURE_PDAF_CONFIG_RESP:
90 case CAPTURE_SYNCGEN_ENABLE_RESP:
91 case CAPTURE_SYNCGEN_DISABLE_RESP:
92 memcpy(&capture->control_resp_msg, control_msg,
93 sizeof(*control_msg));
94 complete(&capture->control_resp);
95 break;
96 default:
97 dev_err(chan->vi->dev,
98 "%s: unknown capture control resp", __func__);
99 break;
100 }
101}
102
103static void vi_capture_request_unpin(struct tegra_channel *chan,
104 uint32_t buffer_index);
105static void vi_capture_ivc_status_callback(const void *ivc_resp,
106 const void *pcontext)
107{
108 struct CAPTURE_MSG *status_msg = (struct CAPTURE_MSG *)ivc_resp;
109 struct vi_capture *capture = (struct vi_capture *)pcontext;
110 struct tegra_channel *chan = capture->vi_channel;
111
112 if (unlikely(capture == NULL)) {
113 dev_err(chan->vi->dev, "%s: invalid context", __func__);
114 return;
115 }
116
117 if (unlikely(status_msg == NULL)) {
118 dev_err(chan->vi->dev, "%s: invalid response", __func__);
119 return;
120 }
121
122 switch (status_msg->header.msg_id) {
123 case CAPTURE_STATUS_IND:
124 vi_capture_request_unpin(chan,
125 status_msg->capture_status_ind.buffer_index);
126 complete(&capture->capture_resp);
127 dev_dbg(chan->vi->dev, "%s: status chan_id %u msg_id %u\n",
128 __func__, status_msg->header.channel_id,
129 status_msg->header.msg_id);
130 break;
131 default:
132 dev_err(chan->vi->dev,
133 "%s: unknown capture resp", __func__);
134 break;
135 }
136}
137
138int vi_capture_init(struct tegra_channel *chan)
139{
140 struct vi_capture *capture;
141 struct device_node *dn;
142 struct platform_device *rtc_pdev;
143
144 dev_dbg(chan->vi->dev, "%s++\n", __func__);
145 dn = of_find_node_by_path("tegra-camera-rtcpu");
146 if (of_device_is_available(dn) == 0) {
147 dev_err(chan->vi->dev, "failed to find rtcpu device node\n");
148 return -ENODEV;
149 }
150 rtc_pdev = of_find_device_by_node(dn);
151 if (rtc_pdev == NULL) {
152 dev_err(chan->vi->dev, "failed to find rtcpu platform\n");
153 return -ENODEV;
154 }
155
156 capture = devm_kzalloc(chan->vi->dev,
157 sizeof(*capture), GFP_KERNEL);
158 if (unlikely(capture == NULL)) {
159 dev_err(chan->vi->dev, "failed to allocate capture channel\n");
160 return -ENOMEM;
161 }
162
163 capture->rtcpu_dev = &rtc_pdev->dev;
164
165 init_completion(&capture->control_resp);
166 init_completion(&capture->capture_resp);
167
168 mutex_init(&capture->control_msg_lock);
169 mutex_init(&capture->unpins_list_lock);
170
171 capture->vi_channel = chan;
172 chan->capture_data = capture;
173
174 capture->channel_id = CAPTURE_CHANNEL_INVALID_ID;
175
176 return 0;
177}
178
179void vi_capture_shutdown(struct tegra_channel *chan)
180{
181 struct vi_capture *capture = chan->capture_data;
182
183 dev_dbg(chan->vi->dev, "%s--\n", __func__);
184 if (capture == NULL)
185 return;
186
187 if (capture->channel_id != CAPTURE_CHANNEL_INVALID_ID)
188 vi_capture_release(chan, 0);
189
190 devm_kfree(chan->vi->dev, capture);
191 chan->capture_data = NULL;
192}
193
194static int vi_capture_ivc_send_control(struct tegra_channel *chan,
195 const struct CAPTURE_CONTROL_MSG *msg, size_t size,
196 uint32_t resp_id)
197{
198 struct vi_capture *capture = chan->capture_data;
199 struct CAPTURE_MSG_HEADER resp_header = msg->header;
200 uint32_t timeout = HZ;
201 int err = 0;
202
203 dev_dbg(chan->vi->dev, "%s: sending chan_id %u msg_id %u\n",
204 __func__, resp_header.channel_id, resp_header.msg_id);
205 resp_header.msg_id = resp_id;
206 /* Send capture control IVC message */
207 mutex_lock(&capture->control_msg_lock);
208 err = tegra_capture_ivc_control_submit(msg, size);
209 if (err < 0) {
210 dev_err(chan->vi->dev, "IVC control submit failed\n");
211 goto fail;
212 }
213
214 timeout = wait_for_completion_killable_timeout(
215 &capture->control_resp, timeout);
216 if (timeout <= 0) {
217 dev_err(chan->vi->dev,
218 "no reply from camera processor\n");
219 err = -ETIMEDOUT;
220 goto fail;
221 }
222
223 if (memcmp(&resp_header, &capture->control_resp_msg.header,
224 sizeof(resp_header)) != 0) {
225 dev_err(chan->vi->dev,
226 "unexpected response from camera processor\n");
227 err = -EINVAL;
228 goto fail;
229 }
230
231 mutex_unlock(&capture->control_msg_lock);
232 dev_dbg(chan->vi->dev, "%s: response chan_id %u msg_id %u\n",
233 __func__, capture->control_resp_msg.header.channel_id,
234 capture->control_resp_msg.header.msg_id);
235 return 0;
236
237fail:
238 mutex_unlock(&capture->control_msg_lock);
239 return err;
240}
241
242static int pin_memory(struct device *dev,
243 uint32_t mem, struct vi_capture_buf *unpin_data);
244static void unpin_memory(struct vi_capture_buf *unpin_data);
245
246static int pin_memory(struct device *dev,
247 uint32_t mem, struct vi_capture_buf *unpin_data)
248{
249 struct dma_buf *buf;
250 struct dma_buf_attachment *attach;
251 struct sg_table *sgt;
252 int err = 0;
253
254 buf = dma_buf_get(mem);
255 if (IS_ERR(buf)) {
256 err = PTR_ERR(buf);
257 goto fail;
258 }
259
260 attach = dma_buf_attach(buf, dev);
261 if (IS_ERR(attach)) {
262 err = PTR_ERR(attach);
263 goto fail;
264 }
265
266 sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
267 if (IS_ERR(sgt)) {
268 err = PTR_ERR(sgt);
269 goto fail;
270 }
271
272 if (sg_dma_address(sgt->sgl) == 0)
273 sg_dma_address(sgt->sgl) = sg_phys(sgt->sgl);
274
275 unpin_data->iova = sg_dma_address(sgt->sgl);
276 unpin_data->buf = buf;
277 unpin_data->attach = attach;
278 unpin_data->sgt = sgt;
279
280 return 0;
281
282fail:
283 unpin_memory(unpin_data);
284 return err;
285}
286
287static void unpin_memory(struct vi_capture_buf *unpin_data)
288{
289 if (unpin_data->sgt != NULL)
290 dma_buf_unmap_attachment(unpin_data->attach, unpin_data->sgt,
291 DMA_BIDIRECTIONAL);
292 if (unpin_data->attach != NULL)
293 dma_buf_detach(unpin_data->buf, unpin_data->attach);
294 if (unpin_data->buf != NULL)
295 dma_buf_put(unpin_data->buf);
296
297 unpin_data->sgt = NULL;
298 unpin_data->attach = NULL;
299 unpin_data->buf = NULL;
300 unpin_data->iova = 0;
301}
302
303static int vi_capture_setup_syncpts(struct tegra_channel *chan);
304static void vi_capture_release_syncpts(struct tegra_channel *chan);
305
306static int vi_capture_setup_syncpts(struct tegra_channel *chan)
307{
308 struct vi_capture *capture = chan->capture_data;
309 int i;
310 int err = 0;
311
312 for (i = 0; i < CAPTURE_CHANNEL_MAX_NUM_SPS; i++) {
313 capture->syncpts[i] = nvhost_get_syncpt_client_managed(
314 chan->vi->ndev, "vi-capture");
315 if (capture->syncpts[i] == 0) {
316 dev_err(chan->vi->dev, "failed to get syncpt %i!\n", i);
317 err = -ENODEV;
318 goto fail;
319 }
320 }
321
322 return 0;
323
324fail:
325 vi_capture_release_syncpts(chan);
326 return err;
327}
328
329static void vi_capture_release_syncpts(struct tegra_channel *chan)
330{
331 struct vi_capture *capture = chan->capture_data;
332 int i;
333
334 for (i = 0; i < CAPTURE_CHANNEL_MAX_NUM_SPS; i++) {
335 if (capture->syncpts[i] != 0)
336 nvhost_syncpt_put_ref_ext(chan->vi->ndev,
337 capture->syncpts[i]);
338 capture->syncpts[i] = 0;
339 }
340}
341
342int vi_capture_setup(struct tegra_channel *chan,
343 struct vi_capture_setup *setup)
344{
345 struct vi_capture *capture = chan->capture_data;
346 uint32_t transaction;
347 struct CAPTURE_CONTROL_MSG control_desc;
348 struct CAPTURE_CONTROL_MSG *resp_msg = &capture->control_resp_msg;
349 struct capture_channel_config *config =
350 &control_desc.channel_setup_req.channel_config;
351 int err = 0;
352
353 if (capture == NULL) {
354 dev_err(chan->vi->dev,
355 "%s: vi capture uninitialized\n", __func__);
356 return -ENODEV;
357 }
358
359 if (capture->channel_id != CAPTURE_CHANNEL_INVALID_ID) {
360 dev_err(chan->vi->dev,
361 "%s: already setup, release first\n", __func__);
362 return -EEXIST;
363 }
364
365 dev_dbg(chan->vi->dev, "chan flags %u\n", setup->channel_flags);
366 dev_dbg(chan->vi->dev, "chan mask %llx\n", setup->vi_channel_mask);
367 dev_dbg(chan->vi->dev, "queue depth %u\n", setup->queue_depth);
368 dev_dbg(chan->vi->dev, "request size %u\n", setup->request_size);
369
370 if (setup->vi_channel_mask == CAPTURE_CHANNEL_INVALID_MASK ||
371 setup->channel_flags == 0 ||
372 setup->queue_depth == 0 ||
373 setup->request_size == 0)
374 return -EINVAL;
375
376 /* pin the capture descriptor ring buffer */
377 dev_dbg(chan->vi->dev, "%s: descr buffer handle %u\n",
378 __func__, setup->mem);
379 err = pin_memory(capture->rtcpu_dev, setup->mem, &capture->requests);
380 if (err < 0) {
381 dev_err(chan->vi->dev, "%s: memory setup failed\n", __func__);
382 return -EFAULT;
383 }
384 capture->request_size = setup->request_size;
385
386 /* allocate for unpin list based on queue depth */
387 capture->unpins_list = devm_kzalloc(chan->vi->dev,
388 sizeof(struct vi_capture_unpins) * setup->queue_depth,
389 GFP_KERNEL);
390 if (unlikely(capture->unpins_list == NULL)) {
391 dev_err(chan->vi->dev, "failed to allocate unpins array\n");
392 goto unpins_list_fail;
393 }
394
395 err = vi_capture_setup_syncpts(chan);
396 if (err < 0) {
397 dev_err(chan->vi->dev, "%s: syncpt setup failed\n", __func__);
398 goto syncpt_fail;
399 }
400
401 err = tegra_capture_ivc_register_control_cb(
402 &vi_capture_ivc_control_callback,
403 &transaction, capture);
404 if (err < 0) {
405 dev_err(chan->vi->dev, "failed to register control callback\n");
406 goto control_cb_fail;
407 }
408
409 memset(&control_desc, 0, sizeof(control_desc));
410 control_desc.header.msg_id = CAPTURE_CHANNEL_SETUP_REQ;
411 control_desc.header.transaction = transaction;
412
413 config->channel_flags = setup->channel_flags;
414 config->vi_channel_mask = setup->vi_channel_mask;
415
416 config->queue_depth = setup->queue_depth;
417 config->request_size = setup->request_size;
418 config->requests = capture->requests.iova;
419
420 config->progress_sp.id = capture->syncpts[PROGRESS_SP_IDX];
421 config->embdata_sp.id = capture->syncpts[EMBDATA_SP_IDX];
422 config->linetimer_sp.id = capture->syncpts[LINETIMER_SP_IDX];
423
424 err = vi_capture_ivc_send_control(chan, &control_desc,
425 sizeof(control_desc), CAPTURE_CHANNEL_SETUP_RESP);
426 if (err < 0)
427 goto submit_fail;
428
429 if (resp_msg->channel_setup_resp.result != CAPTURE_OK) {
430 dev_err(chan->vi->dev, "%s: control failed, errno %d", __func__,
431 resp_msg->channel_setup_resp.result);
432 err = -EINVAL;
433 goto resp_fail;
434 }
435
436 capture->channel_id = resp_msg->channel_setup_resp.channel_id;
437
438 err = tegra_capture_ivc_notify_chan_id(capture->channel_id,
439 transaction);
440 if (err < 0) {
441 dev_err(chan->vi->dev, "failed to update control callback\n");
442 goto cb_fail;
443 }
444
445 err = tegra_capture_ivc_register_capture_cb(
446 &vi_capture_ivc_status_callback,
447 capture->channel_id, capture);
448 if (err < 0) {
449 dev_err(chan->vi->dev, "failed to register capture callback\n");
450 goto cb_fail;
451 }
452
453 return 0;
454
455cb_fail:
456 vi_capture_release(chan, CAPTURE_CHANNEL_RESET_FLAG_IMMEDIATE);
457resp_fail:
458submit_fail:
459 tegra_capture_ivc_unregister_control_cb(transaction);
460control_cb_fail:
461 vi_capture_release_syncpts(chan);
462syncpt_fail:
463 devm_kfree(chan->vi->dev, capture->unpins_list);
464unpins_list_fail:
465 unpin_memory(&capture->requests);
466 return err;
467}
468
469int vi_capture_reset(struct tegra_channel *chan,
470 uint32_t reset_flags)
471{
472 struct vi_capture *capture = chan->capture_data;
473 struct CAPTURE_CONTROL_MSG control_desc;
474 struct CAPTURE_CONTROL_MSG *resp_msg = &capture->control_resp_msg;
475 int err = 0;
476
477 if (capture == NULL) {
478 dev_err(chan->vi->dev,
479 "%s: vi capture uninitialized\n", __func__);
480 return -ENODEV;
481 }
482
483 if (capture->channel_id == CAPTURE_CHANNEL_INVALID_ID) {
484 dev_err(chan->vi->dev,
485 "%s: setup channel first\n", __func__);
486 return -ENODEV;
487 }
488
489 memset(&control_desc, 0, sizeof(control_desc));
490 control_desc.header.msg_id = CAPTURE_CHANNEL_RESET_REQ;
491 control_desc.header.channel_id = capture->channel_id;
492 control_desc.channel_reset_req.reset_flags = reset_flags;
493
494 err = vi_capture_ivc_send_control(chan, &control_desc,
495 sizeof(control_desc), CAPTURE_CHANNEL_RESET_RESP);
496 if (err < 0)
497 goto submit_fail;
498
499 if (resp_msg->channel_reset_resp.result != CAPTURE_OK) {
500 dev_err(chan->vi->dev, "%s: control failed, errno %d", __func__,
501 resp_msg->channel_reset_resp.result);
502 err = -EINVAL;
503 }
504
505 return 0;
506
507submit_fail:
508 return err;
509}
510
511int vi_capture_release(struct tegra_channel *chan,
512 uint32_t reset_flags)
513{
514 struct vi_capture *capture = chan->capture_data;
515 struct CAPTURE_CONTROL_MSG control_desc;
516 struct CAPTURE_CONTROL_MSG *resp_msg = &capture->control_resp_msg;
517 int err = 0;
518 int ret = 0;
519
520 if (capture == NULL) {
521 dev_err(chan->vi->dev,
522 "%s: vi capture uninitialized\n", __func__);
523 return -ENODEV;
524 }
525
526 if (capture->channel_id == CAPTURE_CHANNEL_INVALID_ID) {
527 dev_err(chan->vi->dev,
528 "%s: setup channel first\n", __func__);
529 return -ENODEV;
530 }
531
532 memset(&control_desc, 0, sizeof(control_desc));
533 control_desc.header.msg_id = CAPTURE_CHANNEL_RELEASE_REQ;
534 control_desc.header.channel_id = capture->channel_id;
535 control_desc.channel_release_req.reset_flags = reset_flags;
536
537 err = vi_capture_ivc_send_control(chan, &control_desc,
538 sizeof(control_desc), CAPTURE_CHANNEL_RELEASE_RESP);
539 if (err < 0)
540 goto submit_fail;
541
542 if (resp_msg->channel_release_resp.result != CAPTURE_OK) {
543 dev_err(chan->vi->dev, "%s: control failed, errno %d", __func__,
544 resp_msg->channel_release_resp.result);
545 err = -EINVAL;
546 }
547
548 vi_capture_release_syncpts(chan);
549 unpin_memory(&capture->requests);
550
551 ret = tegra_capture_ivc_unregister_capture_cb(capture->channel_id);
552 if (ret < 0 && err == 0) {
553 dev_err(chan->vi->dev,
554 "failed to unregister capture callback\n");
555 err = ret;
556 }
557
558 ret = tegra_capture_ivc_unregister_control_cb(capture->channel_id);
559 if (ret < 0 && err == 0) {
560 dev_err(chan->vi->dev,
561 "failed to unregister control callback\n");
562 err = ret;
563 }
564
565 capture->channel_id = CAPTURE_CHANNEL_INVALID_ID;
566
567 return 0;
568
569submit_fail:
570 return err;
571}
572
573int vi_capture_get_info(struct tegra_channel *chan,
574 struct vi_capture_info *info)
575{
576 struct vi_capture *capture = chan->capture_data;
577
578 if (capture == NULL) {
579 dev_err(chan->vi->dev,
580 "%s: vi capture uninitialized\n", __func__);
581 return -ENODEV;
582 }
583
584 if (capture->channel_id == CAPTURE_CHANNEL_INVALID_ID) {
585 dev_err(chan->vi->dev,
586 "%s: setup channel first\n", __func__);
587 return -ENODEV;
588 }
589
590 if (info == NULL)
591 return -EINVAL;
592
593 info->syncpts.progress_syncpt = capture->syncpts[PROGRESS_SP_IDX];
594 info->syncpts.emb_data_syncpt = capture->syncpts[EMBDATA_SP_IDX];
595 info->syncpts.line_timer_syncpt = capture->syncpts[LINETIMER_SP_IDX];
596
597 return 0;
598}
599
600int vi_capture_control_message(struct tegra_channel *chan,
601 struct vi_capture_control_msg *msg)
602{
603 struct vi_capture *capture = chan->capture_data;
604 const void __user *msg_ptr =
605 (const void __user *)(uintptr_t)msg->ptr;
606 void __user *response =
607 (void __user *)(uintptr_t)msg->response;
608 void *msg_cpy;
609 struct CAPTURE_MSG_HEADER *header;
610 uint32_t resp_id;
611 struct CAPTURE_CONTROL_MSG *resp_msg = &capture->control_resp_msg;
612 int err = 0;
613
614 if (capture == NULL) {
615 dev_err(chan->vi->dev,
616 "%s: vi capture uninitialized\n", __func__);
617 return -ENODEV;
618 }
619
620 if (msg->ptr == 0ull || msg->response == 0ull || msg->size == 0)
621 return -EINVAL;
622
623 msg_cpy = devm_kzalloc(chan->vi->dev, msg->size, GFP_KERNEL);
624 if (unlikely(msg_cpy == NULL))
625 return -ENOMEM;
626
627 err = copy_from_user(msg_cpy, msg_ptr, msg->size) ? -EFAULT : 0;
628 if (err < 0)
629 goto fail;
630 header = (struct CAPTURE_MSG_HEADER *)msg_cpy;
631 header->channel_id = capture->channel_id;
632
633 switch (header->msg_id) {
634 case CAPTURE_COMPAND_CONFIG_REQ:
635 resp_id = CAPTURE_COMPAND_CONFIG_RESP;
636 break;
637 case CAPTURE_PDAF_CONFIG_REQ:
638 resp_id = CAPTURE_PDAF_CONFIG_RESP;
639 break;
640 case CAPTURE_SYNCGEN_ENABLE_REQ:
641 resp_id = CAPTURE_SYNCGEN_ENABLE_RESP;
642 break;
643 case CAPTURE_SYNCGEN_DISABLE_REQ:
644 resp_id = CAPTURE_SYNCGEN_DISABLE_RESP;
645 break;
646 default:
647 dev_err(chan->vi->dev,
648 "%s: unknown capture control resp", __func__);
649 err = -EINVAL;
650 goto fail;
651 }
652
653 err = vi_capture_ivc_send_control(chan, msg_cpy, msg->size, resp_id);
654 if (err < 0)
655 goto fail;
656
657 err = copy_to_user(response, resp_msg,
658 sizeof(*resp_msg)) ? -EFAULT : 0;
659
660fail:
661 devm_kfree(chan->vi->dev, msg_cpy);
662 return err;
663}
664
665struct surface_t {
666 uint32_t offset;
667 uint32_t offset_hi;
668};
669
670static int vi_capture_request_pin_and_reloc(struct tegra_channel *chan,
671 struct vi_capture_req *req)
672{
673 struct vi_capture *capture = chan->capture_data;
674 uint32_t num_relocs = req->num_relocs;
675 uint32_t __user *reloc_relatives =
676 (uint32_t __user *)(uintptr_t)req->reloc_relatives;
677 uint32_t local_reloc_relatives[num_relocs];
678 struct vi_capture_unpins *unpins;
679 uint32_t request_offset = req->buffer_index * capture->request_size;
680 void *reloc_page_addr = NULL;
681 uint32_t prev_mem = 0;
682 int last_page = -1;
683 dma_addr_t surface_phys_addr = 0;
684 dma_addr_t surface_prev_addr = 0;
685 int i, pin_count = 0;
686 int err = 0;
687
688 err = copy_from_user(local_reloc_relatives, reloc_relatives,
689 num_relocs * sizeof(uint32_t)) ? -EFAULT : 0;
690 if (err < 0)
691 return err;
692
693 unpins = devm_kzalloc(chan->vi->dev,
694 sizeof(struct vi_capture_unpins) +
695 sizeof(struct vi_capture_buf) * num_relocs,
696 GFP_KERNEL);
697 if (unpins == NULL)
698 return -ENOMEM;
699
700 dev_dbg(chan->vi->dev, "%s: relocating %u surfaces\n",
701 __func__, num_relocs);
702 for (i = 0; i < num_relocs; i++) {
703 uint32_t reloc_offset =
704 request_offset + local_reloc_relatives[i];
705 uint64_t surface_raw;
706 struct surface_t *surface;
707 uint32_t mem;
708 uint32_t target_offset;
709 dma_addr_t target_phys_addr;
710
711 dev_dbg(chan->vi->dev,
712 "%s: idx:%i reloc:%u reloc_offset:%u", __func__,
713 i, local_reloc_relatives[i], reloc_offset);
714
715 /* locate page of the request descr buffer relocation is on */
716 if (last_page != reloc_offset >> PAGE_SHIFT) {
717 if (reloc_page_addr != NULL)
718 dma_buf_kunmap(capture->requests.buf, last_page,
719 reloc_page_addr);
720
721 reloc_page_addr = dma_buf_kmap(capture->requests.buf,
722 reloc_offset >> PAGE_SHIFT);
723 last_page = reloc_offset >> PAGE_SHIFT;
724
725 if (unlikely(reloc_page_addr == NULL)) {
726 dev_err(chan->vi->dev,
727 "%s: couldn't map request\n", __func__);
728 goto fail;
729 }
730 }
731
732 /* read surface offset and memory handle from request descr */
733 surface_raw = __raw_readq(
734 (void __iomem *)(reloc_page_addr +
735 (reloc_offset & ~PAGE_MASK)));
736 surface = (struct surface_t *)&surface_raw;
737 target_offset = surface->offset;
738 mem = surface->offset_hi;
739 dev_dbg(chan->vi->dev, "%s: hmem:%u offset:%u\n", __func__,
740 target_offset, mem);
741
742 if (mem != prev_mem) {
743 err = pin_memory(capture->rtcpu_dev,
744 mem, &unpins->data[pin_count]);
745 if (err < 0) {
746 unpins->num_unpins = pin_count;
747 goto fail;
748 }
749 surface_prev_addr = unpins->data[i].iova;
750 surface_phys_addr = unpins->data[i].iova;
751
752 mutex_lock(&capture->unpins_list_lock);
753 memcpy(&capture->unpins_list[req->buffer_index],
754 unpins, sizeof(*unpins));
755 mutex_unlock(&capture->unpins_list_lock);
756
757 pin_count++;
758 } else
759 surface_phys_addr = surface_prev_addr;
760
761 target_phys_addr = surface_phys_addr + target_offset;
762 /* write relocated physical address to request descr */
763 __raw_writeq(
764 target_phys_addr,
765 (void __iomem *)(reloc_page_addr +
766 (reloc_offset & ~PAGE_MASK)));
767 }
768
769 unpins->num_unpins = pin_count;
770
771 return 0;
772
773fail:
774 if (reloc_page_addr != NULL)
775 dma_buf_kunmap(capture->requests.buf, last_page,
776 reloc_page_addr);
777
778 for (i = 0; i < unpins->num_unpins; i++)
779 unpin_memory(&unpins->data[i]);
780 devm_kfree(chan->vi->dev, unpins);
781
782 return err;
783}
784
785static void vi_capture_request_unpin(struct tegra_channel *chan,
786 uint32_t buffer_index)
787{
788 struct vi_capture *capture = chan->capture_data;
789 struct vi_capture_unpins *unpins;
790 int i = 0;
791
792 mutex_lock(&capture->unpins_list_lock);
793 unpins = &capture->unpins_list[buffer_index];
794 for (i = 0; i < unpins->num_unpins; i++)
795 unpin_memory(&unpins->data[i]);
796 unpins->num_unpins = 0u;
797 mutex_unlock(&capture->unpins_list_lock);
798}
799
800int vi_capture_request(struct tegra_channel *chan,
801 struct vi_capture_req *req)
802{
803 struct vi_capture *capture = chan->capture_data;
804 struct CAPTURE_MSG capture_desc;
805 int err = 0;
806
807 if (capture == NULL) {
808 dev_err(chan->vi->dev,
809 "%s: vi capture uninitialized\n", __func__);
810 return -ENODEV;
811 }
812
813 if (capture->channel_id == CAPTURE_CHANNEL_INVALID_ID) {
814 dev_err(chan->vi->dev,
815 "%s: setup channel first\n", __func__);
816 return -ENODEV;
817 }
818
819 memset(&capture_desc, 0, sizeof(capture_desc));
820 capture_desc.header.msg_id = CAPTURE_REQUEST_REQ;
821 capture_desc.header.channel_id = capture->channel_id;
822 capture_desc.capture_request_req.buffer_index = req->buffer_index;
823
824 /* perform surface pinning and relocation */
825 err = vi_capture_request_pin_and_reloc(chan, req);
826 if (err < 0) {
827 dev_err(chan->vi->dev, "relocation failed\n");
828 return err;
829 }
830
831 dev_dbg(chan->vi->dev, "%s: sending chan_id %u msg_id %u buf:%u\n",
832 __func__, capture_desc.header.channel_id,
833 capture_desc.header.msg_id, req->buffer_index);
834 err = tegra_capture_ivc_capture_submit(&capture_desc,
835 sizeof(capture_desc));
836 if (err < 0) {
837 dev_err(chan->vi->dev, "IVC capture submit failed\n");
838 goto fail;
839 }
840
841 return 0;
842
843fail:
844 vi_capture_request_unpin(chan, req->buffer_index);
845 return err;
846}
847
848int vi_capture_status(struct tegra_channel *chan,
849 int32_t timeout_ms)
850{
851 struct vi_capture *capture = chan->capture_data;
852 int ret = 0;
853 int err = 0;
854
855 if (capture == NULL) {
856 dev_err(chan->vi->dev,
857 "%s: vi capture uninitialized\n", __func__);
858 return -ENODEV;
859 }
860
861 if (capture->channel_id == CAPTURE_CHANNEL_INVALID_ID) {
862 dev_err(chan->vi->dev,
863 "%s: setup channel first\n", __func__);
864 return -ENODEV;
865 }
866
867 dev_dbg(chan->vi->dev, "%s: waiting for status, timeout:%d ms\n",
868 __func__, timeout_ms);
869
870 ret = wait_for_completion_killable_timeout(
871 &capture->capture_resp,
872 (unsigned long)(timeout_ms/1000*HZ));
873 if (ret <= 0) {
874 dev_err(chan->vi->dev,
875 "no reply from camera processor\n");
876 return -ETIMEDOUT;
877 }
878
879 return err;
880}
diff --git a/drivers/media/platform/tegra/camera/vi/channel.c b/drivers/media/platform/tegra/camera/vi/channel.c
new file mode 100644
index 000000000..5c8e066be
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/channel.c
@@ -0,0 +1,1650 @@
1/*
2 * NVIDIA Tegra Video Input Device
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/atomic.h>
14#include <linux/bitmap.h>
15#include <linux/clk.h>
16#include <linux/delay.h>
17#include <linux/nvhost.h>
18#include <linux/lcm.h>
19#include <linux/list.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/sched.h>
23#include <linux/slab.h>
24
25#include <media/v4l2-ctrls.h>
26#include <media/v4l2-event.h>
27#include <media/v4l2-dev.h>
28#include <media/v4l2-fh.h>
29#include <media/v4l2-ioctl.h>
30#include <media/videobuf2-core.h>
31#include <media/videobuf2-dma-contig.h>
32#include <media/camera_common.h>
33#include <media/tegra_camera_platform.h>
34#include <media/v4l2-dv-timings.h>
35
36#include <linux/clk/tegra.h>
37
38#include "mc_common.h"
39#include "vi/vi.h"
40#include "mipical/mipi_cal.h"
41
42#define TPG_CSI_GROUP_ID 10
43
44static void gang_buffer_offsets(struct tegra_channel *chan)
45{
46 int i;
47 u32 offset = 0;
48
49 for (i = 0; i < chan->total_ports; i++) {
50 switch (chan->gang_mode) {
51 case CAMERA_NO_GANG_MODE:
52 case CAMERA_GANG_L_R:
53 case CAMERA_GANG_R_L:
54 offset = chan->gang_bytesperline;
55 break;
56 case CAMERA_GANG_T_B:
57 case CAMERA_GANG_B_T:
58 offset = chan->gang_sizeimage;
59 break;
60 default:
61 offset = 0;
62 }
63 offset = ((offset + TEGRA_SURFACE_ALIGNMENT - 1) &
64 ~(TEGRA_SURFACE_ALIGNMENT - 1));
65 chan->buffer_offset[i] = i * offset;
66 }
67}
68
69static u32 gang_mode_width(enum camera_gang_mode gang_mode,
70 unsigned int width)
71{
72 if ((gang_mode == CAMERA_GANG_L_R) ||
73 (gang_mode == CAMERA_GANG_R_L))
74 return width >> 1;
75 else
76 return width;
77}
78
79static u32 gang_mode_height(enum camera_gang_mode gang_mode,
80 unsigned int height)
81{
82 if ((gang_mode == CAMERA_GANG_T_B) ||
83 (gang_mode == CAMERA_GANG_B_T))
84 return height >> 1;
85 else
86 return height;
87}
88
89static void update_gang_mode_params(struct tegra_channel *chan)
90{
91 chan->gang_width = gang_mode_width(chan->gang_mode,
92 chan->format.width);
93 chan->gang_height = gang_mode_height(chan->gang_mode,
94 chan->format.height);
95 chan->gang_bytesperline = ((chan->gang_width *
96 chan->fmtinfo->bpp.numerator) /
97 chan->fmtinfo->bpp.denominator);
98 chan->gang_sizeimage = chan->gang_bytesperline *
99 chan->format.height;
100 gang_buffer_offsets(chan);
101}
102
103static void update_gang_mode(struct tegra_channel *chan)
104{
105 int width = chan->format.width;
106 int height = chan->format.height;
107
108 /*
109 * At present only 720p, 1080p and 4k resolutions
110 * are supported and only 4K requires gang mode
111 * Update this code with CID for future extensions
112 * Also, validate width and height of images based
113 * on gang mode and surface stride alignment
114 */
115 if ((width > 1920) && (height > 1080)) {
116 chan->gang_mode = CAMERA_GANG_L_R;
117 chan->valid_ports = chan->total_ports;
118 } else {
119 chan->gang_mode = CAMERA_NO_GANG_MODE;
120 chan->valid_ports = 1;
121 }
122
123 update_gang_mode_params(chan);
124}
125
126static u32 get_aligned_buffer_size(struct tegra_channel *chan,
127 u32 bytesperline, u32 height)
128{
129 u32 height_aligned;
130 u32 temp_size, size;
131
132 height_aligned = roundup(height, chan->height_align);
133 temp_size = bytesperline * height_aligned;
134 size = roundup(temp_size, chan->size_align);
135
136 return size;
137}
138
139static void tegra_channel_fmt_align(struct tegra_channel *chan,
140 const struct tegra_video_format *vfmt,
141 u32 *width, u32 *height, u32 *bytesperline)
142{
143 unsigned int min_width;
144 unsigned int max_width;
145 unsigned int min_bpl;
146 unsigned int max_bpl;
147 unsigned int temp_width;
148 unsigned int align, fmt_align;
149 unsigned int temp_bpl;
150 unsigned int bpl;
151 unsigned int numerator, denominator;
152 const struct tegra_frac *bpp = &vfmt->bpp;
153
154 /* Init, if un-init */
155 if (!*width || !*height) {
156 *width = chan->format.width;
157 *height = chan->format.height;
158 }
159
160 denominator = (!bpp->denominator) ? 1 : bpp->denominator;
161 numerator = (!bpp->numerator) ? 1 : bpp->numerator;
162
163 bpl = (*width * numerator) / denominator;
164 if (!*bytesperline)
165 *bytesperline = bpl;
166
167 /* The transfer alignment requirements are expressed in bytes. Compute
168 * the minimum and maximum values, clamp the requested width and convert
169 * it back to pixels.
170 * use denominator for base width alignment when >1.
171 * use bytesperline to adjust width for applicaton related requriements.
172 */
173 fmt_align = (denominator == 1) ? numerator : 1;
174 align = lcm(chan->width_align, fmt_align);
175 min_width = roundup(TEGRA_MIN_WIDTH, align);
176 max_width = rounddown(TEGRA_MAX_WIDTH, align);
177 temp_width = roundup(bpl, align);
178
179 *width = (clamp(temp_width, min_width, max_width) * denominator) /
180 numerator;
181 *height = clamp(*height, TEGRA_MIN_HEIGHT, TEGRA_MAX_HEIGHT);
182
183 /* Clamp the requested bytes per line value. If the maximum bytes per
184 * line value is zero, the module doesn't support user configurable line
185 * sizes. Override the requested value with the minimum in that case.
186 */
187 min_bpl = bpl;
188 max_bpl = rounddown(TEGRA_MAX_WIDTH, chan->stride_align);
189 temp_bpl = roundup(*bytesperline, chan->stride_align);
190
191 *bytesperline = clamp(temp_bpl, min_bpl, max_bpl);
192}
193
194static void tegra_channel_update_format(struct tegra_channel *chan,
195 u32 width, u32 height, u32 fourcc,
196 const struct tegra_frac *bpp,
197 u32 preferred_stride)
198{
199 u32 denominator = (!bpp->denominator) ? 1 : bpp->denominator;
200 u32 numerator = (!bpp->numerator) ? 1 : bpp->numerator;
201 u32 bytesperline = (width * numerator / denominator);
202
203 chan->format.width = width;
204 chan->format.height = height;
205 chan->format.pixelformat = fourcc;
206 chan->format.bytesperline = preferred_stride ?: bytesperline;
207
208 tegra_channel_fmt_align(chan, chan->fmtinfo,
209 &chan->format.width,
210 &chan->format.height,
211 &chan->format.bytesperline);
212
213 /* Calculate the sizeimage per plane */
214 chan->format.sizeimage = get_aligned_buffer_size(chan,
215 chan->format.bytesperline, chan->format.height);
216
217 if (fourcc == V4L2_PIX_FMT_NV16)
218 chan->format.sizeimage *= 2;
219}
220
221static void tegra_channel_fmts_bitmap_init(struct tegra_channel *chan)
222{
223 int ret, pixel_format_index = 0, init_code = 0;
224 struct v4l2_subdev *subdev = chan->subdev_on_csi;
225 struct v4l2_subdev_format fmt = {};
226 struct v4l2_subdev_mbus_code_enum code = {
227 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
228 };
229
230 bitmap_zero(chan->fmts_bitmap, MAX_FORMAT_NUM);
231
232 /*
233 * Initialize all the formats available from
234 * the sub-device and extract the corresponding
235 * index from the pre-defined video formats and initialize
236 * the channel default format with the active code
237 * Index zero as the only sub-device is sensor
238 */
239 while (1) {
240 ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
241 NULL, &code);
242 if (ret < 0)
243 /* no more formats */
244 break;
245
246 pixel_format_index =
247 tegra_core_get_idx_by_code(chan, code.code, 0);
248 while (pixel_format_index >= 0) {
249 bitmap_set(chan->fmts_bitmap, pixel_format_index, 1);
250 /* Set init_code to the first matched format */
251 if (!init_code)
252 init_code = code.code;
253 /* Look for other formats with the same mbus code */
254 pixel_format_index = tegra_core_get_idx_by_code(chan,
255 code.code, pixel_format_index + 1);
256 }
257
258 code.index++;
259 }
260
261 if (!init_code) {
262 pixel_format_index =
263 tegra_core_get_idx_by_code(chan, TEGRA_VF_DEF, 0);
264 if (pixel_format_index >= 0) {
265 bitmap_set(chan->fmts_bitmap, pixel_format_index, 1);
266 init_code = TEGRA_VF_DEF;
267 }
268 }
269 /* Get the format based on active code of the sub-device */
270 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
271 if (ret)
272 return;
273
274 /* Initiate the channel format to the first matched format */
275 chan->fmtinfo =
276 tegra_core_get_format_by_code(chan, fmt.format.code, 0);
277 v4l2_fill_pix_format(&chan->format, &fmt.format);
278 tegra_channel_update_format(chan, chan->format.width,
279 chan->format.height,
280 chan->fmtinfo->fourcc,
281 &chan->fmtinfo->bpp, 0);
282
283 if (chan->total_ports > 1)
284 update_gang_mode(chan);
285}
286
287/*
288 * -----------------------------------------------------------------------------
289 * Tegra channel frame setup and capture operations
290 * -----------------------------------------------------------------------------
291 */
292
293void tegra_channel_init_ring_buffer(struct tegra_channel *chan)
294{
295 chan->released_bufs = 0;
296 chan->num_buffers = 0;
297 chan->save_index = 0;
298 chan->free_index = 0;
299 chan->bfirst_fstart = false;
300}
301
302void free_ring_buffers(struct tegra_channel *chan, int frames)
303{
304 struct vb2_v4l2_buffer *vbuf;
305
306 while (frames) {
307 vbuf = chan->buffers[chan->free_index];
308
309 /* release one frame */
310 vbuf->sequence = chan->sequence++;
311 vbuf->field = V4L2_FIELD_NONE;
312 vb2_set_plane_payload(&vbuf->vb2_buf,
313 0, chan->format.sizeimage);
314
315 /*
316 * WAR to force buffer state if capture state is not good
317 * WAR - After sync point timeout or error frame capture
318 * the second buffer is intermittently frame of zeros
319 * with no error status or padding.
320 */
321#if 0
322 /* This will drop the first two frames. Disable for now. */
323 if (chan->capture_state != CAPTURE_GOOD ||
324 chan->released_bufs < 2)
325 chan->buffer_state[chan->free_index] =
326 VB2_BUF_STATE_ERROR;
327#endif
328 vb2_buffer_done(&vbuf->vb2_buf,
329 chan->buffer_state[chan->free_index++]);
330
331 if (chan->free_index >= QUEUED_BUFFERS)
332 chan->free_index = 0;
333 chan->num_buffers--;
334 chan->released_bufs++;
335 frames--;
336 }
337}
338
339static void add_buffer_to_ring(struct tegra_channel *chan,
340 struct vb2_v4l2_buffer *vb)
341{
342 /* save the buffer to the ring first */
343 /* Mark buffer state as error before start */
344 chan->buffer_state[chan->save_index] = VB2_BUF_STATE_ERROR;
345 chan->buffers[chan->save_index++] = vb;
346 if (chan->save_index >= QUEUED_BUFFERS)
347 chan->save_index = 0;
348 chan->num_buffers++;
349}
350
351static void update_state_to_buffer(struct tegra_channel *chan, int state)
352{
353 int save_index = (chan->save_index - PREVIOUS_BUFFER_DEC_INDEX);
354
355 /* save index decrements by 2 as 3 bufs are added in ring buffer */
356 if (save_index < 0)
357 save_index += QUEUED_BUFFERS;
358 /* update state for the previous buffer */
359 chan->buffer_state[save_index] = state;
360
361 /* for timeout/error case update the current buffer state as well */
362 if (chan->capture_state != CAPTURE_GOOD)
363 chan->buffer_state[chan->save_index] = state;
364}
365
366void tegra_channel_ring_buffer(struct tegra_channel *chan,
367 struct vb2_v4l2_buffer *vb,
368 struct timespec *ts, int state)
369
370{
371 if (!chan->bfirst_fstart)
372 chan->bfirst_fstart = true;
373 else
374 update_state_to_buffer(chan, state);
375
376 /* Capture state is not GOOD, release all buffers and re-init state */
377 if (chan->capture_state != CAPTURE_GOOD) {
378 free_ring_buffers(chan, chan->num_buffers);
379 tegra_channel_init_ring_buffer(chan);
380 return;
381 } else {
382 /* update time stamp of the buffer */
383 vb->timestamp.tv_sec = ts->tv_sec;
384 vb->timestamp.tv_usec = ts->tv_nsec / NSEC_PER_USEC;
385 }
386
387 /* release buffer N at N+2 frame start event */
388 if (chan->num_buffers >= (QUEUED_BUFFERS - 1))
389 free_ring_buffers(chan, 1);
390}
391
392void tegra_channel_ec_close(struct tegra_mc_vi *vi)
393{
394 struct tegra_channel *chan;
395
396 /* clear all channles sync point fifo context */
397 list_for_each_entry(chan, &vi->vi_chans, list) {
398 memset(&chan->syncpoint_fifo[0], 0, TEGRA_CSI_BLOCKS);
399 }
400}
401
402struct tegra_channel_buffer *dequeue_buffer(struct tegra_channel *chan)
403{
404 struct tegra_channel_buffer *buf = NULL;
405
406 spin_lock(&chan->start_lock);
407 if (list_empty(&chan->capture))
408 goto done;
409
410 buf = list_entry(chan->capture.next,
411 struct tegra_channel_buffer, queue);
412 list_del_init(&buf->queue);
413
414 /* add dequeued buffer to the ring buffer */
415 add_buffer_to_ring(chan, &buf->buf);
416done:
417 spin_unlock(&chan->start_lock);
418 return buf;
419}
420
421/*
422 * -----------------------------------------------------------------------------
423 * videobuf2 queue operations
424 * -----------------------------------------------------------------------------
425 */
426static int
427tegra_channel_queue_setup(struct vb2_queue *vq, const void *parg,
428 unsigned int *nbuffers, unsigned int *nplanes,
429 unsigned int sizes[], void *alloc_ctxs[])
430{
431 const struct v4l2_format *fmt = parg;
432 struct tegra_channel *chan = vb2_get_drv_priv(vq);
433 /* Make sure the image size is large enough. */
434 if (fmt && fmt->fmt.pix.sizeimage < chan->format.sizeimage)
435 return -EINVAL;
436
437 *nplanes = 1;
438
439 sizes[0] = fmt ? fmt->fmt.pix.sizeimage : chan->format.sizeimage;
440 alloc_ctxs[0] = chan->alloc_ctx;
441
442 /* Make sure minimum number of buffers are passed */
443 if (*nbuffers < (QUEUED_BUFFERS - 1))
444 *nbuffers = QUEUED_BUFFERS - 1;
445
446 return 0;
447}
448
449static int tegra_channel_buffer_prepare(struct vb2_buffer *vb)
450{
451 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
452 struct tegra_channel *chan = vb2_get_drv_priv(vb->vb2_queue);
453 struct tegra_channel_buffer *buf = to_tegra_channel_buffer(vbuf);
454
455 buf->chan = chan;
456 vb2_set_plane_payload(&vbuf->vb2_buf, 0, chan->format.sizeimage);
457#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
458 buf->addr = vb2_dma_contig_plane_dma_addr(vb, 0);
459#endif
460
461 return 0;
462}
463
464static void tegra_channel_buffer_queue(struct vb2_buffer *vb)
465{
466 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
467 struct tegra_channel *chan = vb2_get_drv_priv(vb->vb2_queue);
468 struct tegra_channel_buffer *buf = to_tegra_channel_buffer(vbuf);
469
470 /* for bypass mode - do nothing */
471 if (chan->bypass)
472 return;
473
474 /* Put buffer into the capture queue */
475 spin_lock(&chan->start_lock);
476 list_add_tail(&buf->queue, &chan->capture);
477 spin_unlock(&chan->start_lock);
478
479 /* Wait up kthread for capture */
480 wake_up_interruptible(&chan->start_wait);
481}
482
483/* Return all queued buffers back to videobuf2 */
484void tegra_channel_queued_buf_done(struct tegra_channel *chan,
485 enum vb2_buffer_state state)
486{
487 struct tegra_channel_buffer *buf, *nbuf;
488 spinlock_t *lock = &chan->start_lock;
489 struct list_head *q = &chan->capture;
490
491 spin_lock(lock);
492 list_for_each_entry_safe(buf, nbuf, q, queue) {
493 vb2_buffer_done(&buf->buf.vb2_buf, state);
494 list_del(&buf->queue);
495 }
496 spin_unlock(lock);
497}
498
499#define __tegra_channel_device_call_subdevs_all_p(v4l2_dev, sd, cond, o,\
500 f, args...) \
501({ \
502 long __err = 0; \
503 long e = 0; \
504 \
505 list_for_each_entry((sd), &(v4l2_dev)->subdevs, list) { \
506 if ((cond) && (sd)->ops->o && (sd)->ops->o->f) \
507 e = (sd)->ops->o->f((sd), ##args); \
508 if (!__err && e && e != -ENOIOCTLCMD) \
509 __err = e; \
510 e = 0; \
511 } \
512 __err; \
513})
514
515/*
516 * Call the specified callback for all subdevs matching grp_id (if 0, then
517 * match them all), errors are ignored until the end, and the first error
518 * encountered is returned. If the callback returns an error other than 0 or
519 * -ENOIOCTLCMD, then return with that error code. Note that you cannot
520 * add or delete a subdev while walking the subdevs list.
521 */
522#define tegra_channel_device_call_all(v4l2_dev, grpid, o, f, args...) \
523({ \
524 struct v4l2_subdev *__sd; \
525 __tegra_channel_device_call_subdevs_all_p(v4l2_dev, __sd, \
526 !(grpid) || __sd->grp_id == (grpid), o, f, \
527 ##args); \
528})
529
530/*
531 * -----------------------------------------------------------------------------
532 * subdevice set/unset operations
533 * -----------------------------------------------------------------------------
534 */
535int tegra_channel_set_stream(struct tegra_channel *chan, bool on)
536{
537 int num_sd;
538 int ret = 0;
539
540 if (atomic_read(&chan->is_streaming) == on)
541 return 0;
542
543 for (num_sd = chan->num_subdevs - 1; num_sd >= 0; num_sd--) {
544 struct v4l2_subdev *sd = chan->subdev[num_sd];
545 int err = 0;
546
547 err = v4l2_subdev_call(sd, video, s_stream, on);
548 if (!ret && err < 0 && err != -ENOIOCTLCMD)
549 ret = err;
550 }
551
552 atomic_set(&chan->is_streaming, on);
553
554 return ret;
555}
556
557int tegra_channel_set_power(struct tegra_channel *chan, bool on)
558{
559 int num_sd;
560 int ret = 0;
561
562 for (num_sd = 0; num_sd < chan->num_subdevs; num_sd++) {
563 struct v4l2_subdev *sd = chan->subdev[num_sd];
564 int err = 0;
565
566 err = v4l2_subdev_call(sd, core, s_power, on);
567 if (!ret && err < 0 && err != -ENOIOCTLCMD)
568 ret = err;
569 }
570
571 return ret;
572}
573
574static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
575{
576 struct tegra_channel *chan = vb2_get_drv_priv(vq);
577 struct tegra_mc_vi *vi = chan->vi;
578
579 if (vi->fops)
580 return vi->fops->vi_start_streaming(vq, count);
581 return 0;
582}
583
584static void tegra_channel_stop_streaming(struct vb2_queue *vq)
585{
586 struct tegra_channel *chan = vb2_get_drv_priv(vq);
587 struct tegra_mc_vi *vi = chan->vi;
588
589 if (vi->fops)
590 vi->fops->vi_stop_streaming(vq);
591}
592
593static const struct vb2_ops tegra_channel_queue_qops = {
594 .queue_setup = tegra_channel_queue_setup,
595 .buf_prepare = tegra_channel_buffer_prepare,
596 .buf_queue = tegra_channel_buffer_queue,
597 .wait_prepare = vb2_ops_wait_prepare,
598 .wait_finish = vb2_ops_wait_finish,
599 .start_streaming = tegra_channel_start_streaming,
600 .stop_streaming = tegra_channel_stop_streaming,
601};
602
603/* -----------------------------------------------------------------------------
604 * V4L2 ioctls
605 */
606
607static int
608tegra_channel_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
609{
610 struct v4l2_fh *vfh = file->private_data;
611 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
612
613 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
614 cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
615 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
616
617 strlcpy(cap->driver, "tegra-video", sizeof(cap->driver));
618 strlcpy(cap->card, chan->video.name, sizeof(cap->card));
619 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s:%u",
620 dev_name(chan->vi->dev), chan->port[0]);
621
622 return 0;
623}
624
625static int
626tegra_channel_enum_framesizes(struct file *file, void *fh,
627 struct v4l2_frmsizeenum *sizes)
628{
629 struct v4l2_fh *vfh = file->private_data;
630 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
631 struct v4l2_subdev_frame_size_enum fse = {
632 .index = sizes->index,
633 .code = sizes->pixel_format,
634 };
635 int ret = 0;
636
637 ret = v4l2_device_call_until_err(chan->video.v4l2_dev,
638 chan->grp_id, pad, enum_frame_size, NULL, &fse);
639 if (!ret) {
640 sizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
641 sizes->discrete.width = fse.max_width;
642 sizes->discrete.height = fse.max_height;
643 }
644
645 return ret;
646}
647
648static int
649tegra_channel_enum_frameintervals(struct file *file, void *fh,
650 struct v4l2_frmivalenum *intervals)
651{
652 struct v4l2_fh *vfh = file->private_data;
653 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
654 struct v4l2_subdev_frame_interval_enum fie = {
655 .index = intervals->index,
656 .code = intervals->pixel_format,
657 .width = intervals->width,
658 .height = intervals->height,
659 };
660 int ret = 0;
661
662 ret = v4l2_device_call_until_err(chan->video.v4l2_dev,
663 chan->grp_id, pad, enum_frame_interval, NULL, &fie);
664
665 if (!ret) {
666 intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE;
667 intervals->discrete.numerator = fie.interval.numerator;
668 intervals->discrete.denominator = fie.interval.denominator;
669 }
670
671 return ret;
672}
673
674static int
675tegra_channel_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
676{
677 struct v4l2_fh *vfh = file->private_data;
678 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
679 unsigned int index = 0, i;
680 unsigned long *fmts_bitmap = chan->fmts_bitmap;
681
682 if (f->index >= bitmap_weight(fmts_bitmap, MAX_FORMAT_NUM))
683 return -EINVAL;
684
685 for (i = 0; i < f->index + 1; i++, index++)
686 index = find_next_bit(fmts_bitmap, MAX_FORMAT_NUM, index);
687
688 index -= 1;
689 f->pixelformat = tegra_core_get_fourcc_by_idx(chan, index);
690 tegra_core_get_description_by_idx(chan, index, f->description);
691
692 return 0;
693}
694
695static int
696tegra_channel_g_edid(struct file *file, void *fh, struct v4l2_edid *edid)
697{
698 struct v4l2_fh *vfh = file->private_data;
699 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
700 struct v4l2_subdev *sd = chan->subdev_on_csi;
701
702 if (!v4l2_subdev_has_op(sd, pad, get_edid))
703 return -ENOTTY;
704
705 return v4l2_subdev_call(sd, pad, get_edid, edid);
706}
707
708static int
709tegra_channel_s_edid(struct file *file, void *fh, struct v4l2_edid *edid)
710{
711 struct v4l2_fh *vfh = file->private_data;
712 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
713 struct v4l2_subdev *sd = chan->subdev_on_csi;
714
715 if (!v4l2_subdev_has_op(sd, pad, set_edid))
716 return -ENOTTY;
717
718 return v4l2_subdev_call(sd, pad, set_edid, edid);
719}
720
721static int
722tegra_channel_g_dv_timings(struct file *file, void *fh,
723 struct v4l2_dv_timings *timings)
724{
725 struct v4l2_fh *vfh = file->private_data;
726 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
727
728 if (!v4l2_subdev_has_op(chan->subdev_on_csi, video, g_dv_timings))
729 return -ENOTTY;
730
731 return v4l2_device_call_until_err(chan->video.v4l2_dev,
732 chan->grp_id, video, g_dv_timings, timings);
733}
734
735static int
736tegra_channel_s_dv_timings(struct file *file, void *fh,
737 struct v4l2_dv_timings *timings)
738{
739 struct v4l2_fh *vfh = file->private_data;
740 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
741 struct v4l2_bt_timings *bt = &timings->bt;
742 struct v4l2_dv_timings curr_timings;
743 int ret;
744
745 if (!v4l2_subdev_has_op(chan->subdev_on_csi, video, s_dv_timings))
746 return -ENOTTY;
747
748 ret = tegra_channel_g_dv_timings(file, fh, &curr_timings);
749 if (ret)
750 return ret;
751
752 if (v4l2_match_dv_timings(timings, &curr_timings, 0))
753 return 0;
754
755 if (vb2_is_busy(&chan->queue))
756 return -EBUSY;
757
758 ret = v4l2_device_call_until_err(chan->video.v4l2_dev,
759 chan->grp_id, video, s_dv_timings, timings);
760
761 if (!ret)
762 tegra_channel_update_format(chan, bt->width, bt->height,
763 chan->fmtinfo->fourcc, &chan->fmtinfo->bpp, 0);
764
765 if (chan->total_ports > 1)
766 update_gang_mode(chan);
767
768 return ret;
769}
770
771static int
772tegra_channel_query_dv_timings(struct file *file, void *fh,
773 struct v4l2_dv_timings *timings)
774{
775 struct v4l2_fh *vfh = file->private_data;
776 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
777
778 if (!v4l2_subdev_has_op(chan->subdev_on_csi, video, query_dv_timings))
779 return -ENOTTY;
780
781 return v4l2_device_call_until_err(chan->video.v4l2_dev,
782 chan->grp_id, video, query_dv_timings, timings);
783}
784
785static int
786tegra_channel_enum_dv_timings(struct file *file, void *fh,
787 struct v4l2_enum_dv_timings *timings)
788{
789 struct v4l2_fh *vfh = file->private_data;
790 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
791 struct v4l2_subdev *sd = chan->subdev_on_csi;
792
793 if (!v4l2_subdev_has_op(sd, pad, enum_dv_timings))
794 return -ENOTTY;
795
796 return v4l2_subdev_call(sd, pad, enum_dv_timings, timings);
797}
798
799static int
800tegra_channel_dv_timings_cap(struct file *file, void *fh,
801 struct v4l2_dv_timings_cap *cap)
802{
803 struct v4l2_fh *vfh = file->private_data;
804 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
805 struct v4l2_subdev *sd = chan->subdev_on_csi;
806
807 if (!v4l2_subdev_has_op(sd, pad, dv_timings_cap))
808 return -ENOTTY;
809
810 return v4l2_subdev_call(sd, pad, dv_timings_cap, cap);
811}
812
813int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl)
814{
815 struct tegra_channel *chan = container_of(ctrl->handler,
816 struct tegra_channel, ctrl_handler);
817
818 switch (ctrl->id) {
819 case V4L2_CID_VI_BYPASS_MODE:
820 if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON)
821 chan->bypass = true;
822 else if (chan->vi->bypass) {
823 dev_dbg(&chan->video.dev,
824 "can't disable bypass mode\n");
825 dev_dbg(&chan->video.dev,
826 "because the VI/CSI is in bypass mode\n");
827 chan->bypass = true;
828 } else
829 chan->bypass = false;
830 break;
831 case V4L2_CID_OVERRIDE_ENABLE:
832 {
833 struct v4l2_subdev *sd = chan->subdev_on_csi;
834 struct i2c_client *client = v4l2_get_subdevdata(sd);
835 struct camera_common_data *s_data =
836 to_camera_common_data(client);
837
838 if (!i2c_get_clientdata(client)) {
839 dev_info(&chan->video.dev,
840 "i2c_client drvdata is NULL\n");
841 break;
842 }
843 if (!s_data)
844 break;
845 if (switch_ctrl_qmenu[ctrl->val] == SWITCH_ON) {
846 s_data->override_enable = true;
847 dev_dbg(&chan->video.dev,
848 "enable override control\n");
849 } else {
850 s_data->override_enable = false;
851 dev_dbg(&chan->video.dev,
852 "disable override control\n");
853 }
854 }
855 break;
856 case V4L2_CID_VI_HEIGHT_ALIGN:
857 chan->height_align = ctrl->val;
858 tegra_channel_update_format(chan, chan->format.width,
859 chan->format.height,
860 chan->format.pixelformat,
861 &chan->fmtinfo->bpp, 0);
862 break;
863 case V4L2_CID_VI_SIZE_ALIGN:
864 chan->size_align = size_align_ctrl_qmenu[ctrl->val];
865 tegra_channel_update_format(chan, chan->format.width,
866 chan->format.height,
867 chan->format.pixelformat,
868 &chan->fmtinfo->bpp, 0);
869 break;
870 default:
871 dev_err(&chan->video.dev, "%s:Not valid ctrl\n", __func__);
872 return -EINVAL;
873 }
874
875 return 0;
876}
877
878static const struct v4l2_ctrl_ops channel_ctrl_ops = {
879 .s_ctrl = tegra_channel_s_ctrl,
880};
881
882static const struct v4l2_ctrl_config common_custom_ctrls[] = {
883 {
884 .ops = &channel_ctrl_ops,
885 .id = V4L2_CID_VI_BYPASS_MODE,
886 .name = "Bypass Mode",
887 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
888 .def = 0,
889 .min = 0,
890 .max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
891 .menu_skip_mask = 0,
892 .qmenu_int = switch_ctrl_qmenu,
893 },
894 {
895 .ops = &channel_ctrl_ops,
896 .id = V4L2_CID_OVERRIDE_ENABLE,
897 .name = "Override Enable",
898 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
899 .def = 0,
900 .min = 0,
901 .max = ARRAY_SIZE(switch_ctrl_qmenu) - 1,
902 .menu_skip_mask = 0,
903 .qmenu_int = switch_ctrl_qmenu,
904 },
905 {
906 .ops = &channel_ctrl_ops,
907 .id = V4L2_CID_VI_HEIGHT_ALIGN,
908 .name = "Height Align",
909 .type = V4L2_CTRL_TYPE_INTEGER,
910 .min = 1,
911 .max = 16,
912 .step = 1,
913 .def = 1,
914 },
915 {
916 .ops = &channel_ctrl_ops,
917 .id = V4L2_CID_VI_SIZE_ALIGN,
918 .name = "Size Align",
919 .type = V4L2_CTRL_TYPE_INTEGER_MENU,
920 .def = 0,
921 .min = 0,
922 .max = ARRAY_SIZE(size_align_ctrl_qmenu) - 1,
923 .menu_skip_mask = 0,
924 .qmenu_int = size_align_ctrl_qmenu,
925 },
926};
927
928static int tegra_channel_setup_controls(struct tegra_channel *chan)
929{
930 int num_sd = 0;
931 struct v4l2_subdev *sd = NULL;
932 struct tegra_mc_vi *vi = chan->vi;
933 int i;
934
935 /* Initialize the subdev and controls here at first open */
936 sd = chan->subdev[num_sd];
937 while ((sd = chan->subdev[num_sd++]) &&
938 (num_sd <= chan->num_subdevs)) {
939 /* Add control handler for the subdevice */
940 v4l2_ctrl_add_handler(&chan->ctrl_handler,
941 sd->ctrl_handler, NULL);
942 if (chan->ctrl_handler.error)
943 dev_err(chan->vi->dev,
944 "Failed to add sub-device controls\n");
945 }
946
947 /* Add new custom controls */
948 for (i = 0; i < ARRAY_SIZE(common_custom_ctrls); i++) {
949 /* don't create override control for pg mode */
950 if (common_custom_ctrls[i].id == V4L2_CID_OVERRIDE_ENABLE &&
951 chan->pg_mode)
952 continue;
953 v4l2_ctrl_new_custom(&chan->ctrl_handler,
954 &common_custom_ctrls[i], NULL);
955 if (chan->ctrl_handler.error) {
956 dev_err(chan->vi->dev,
957 "Failed to add %s ctrl\n",
958 common_custom_ctrls[i].name);
959 return chan->ctrl_handler.error;
960 }
961 }
962
963 vi->fops->vi_add_ctrls(chan);
964
965 if (chan->pg_mode) {
966 v4l2_ctrl_add_handler(&chan->ctrl_handler,
967 &chan->vi->ctrl_handler, NULL);
968 if (chan->ctrl_handler.error)
969 dev_err(chan->vi->dev,
970 "Failed to add VI controls\n");
971 }
972
973 /* setup the controls */
974 return v4l2_ctrl_handler_setup(&chan->ctrl_handler);
975}
976
977int tegra_channel_init_subdevices(struct tegra_channel *chan)
978{
979 struct media_entity *entity;
980 struct media_pad *pad;
981 struct v4l2_subdev *sd;
982 int index = 0;
983 int num_sd = 0;
984 int grp_id = chan->pg_mode ? (TPG_CSI_GROUP_ID + chan->port[0] + 1)
985 : chan->port[0] + 1;
986
987 /* set_stream of CSI */
988 pad = media_entity_remote_pad(&chan->pad);
989 if (!pad)
990 return -ENODEV;
991
992 entity = pad->entity;
993 sd = media_entity_to_v4l2_subdev(entity);
994 v4l2_set_subdev_hostdata(sd, chan);
995 chan->subdev[num_sd++] = sd;
996 /* Add subdev name to this video dev name with vi-output tag*/
997 snprintf(chan->video.name, sizeof(chan->video.name), "%s, %s",
998 "vi-output", sd->name);
999 sd->grp_id = grp_id;
1000 chan->grp_id = grp_id;
1001 index = pad->index - 1;
1002 while (index >= 0) {
1003 pad = &entity->pads[index];
1004 if (!(pad->flags & MEDIA_PAD_FL_SINK))
1005 break;
1006
1007 pad = media_entity_remote_pad(pad);
1008 if (pad == NULL ||
1009 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
1010 break;
1011
1012 if (num_sd >= MAX_SUBDEVICES)
1013 break;
1014
1015 entity = pad->entity;
1016 sd = media_entity_to_v4l2_subdev(entity);
1017 v4l2_set_subdev_hostdata(sd, chan);
1018 sd->grp_id = grp_id;
1019 chan->subdev[num_sd++] = sd;
1020 /* Add subdev name to this video dev name with vi-output tag*/
1021 snprintf(chan->video.name, sizeof(chan->video.name), "%s, %s",
1022 "vi-output", sd->name);
1023
1024 index = pad->index - 1;
1025 }
1026 chan->num_subdevs = num_sd;
1027 /*
1028 * Each CSI channel has only one final remote source,
1029 * Mark that subdev as subdev_on_csi
1030 */
1031 chan->subdev_on_csi = sd;
1032
1033 /* initialize the available formats */
1034 if (chan->num_subdevs)
1035 tegra_channel_fmts_bitmap_init(chan);
1036
1037 return tegra_channel_setup_controls(chan);
1038}
1039
1040static int
1041tegra_channel_get_format(struct file *file, void *fh,
1042 struct v4l2_format *format)
1043{
1044 struct v4l2_fh *vfh = file->private_data;
1045 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
1046 struct v4l2_pix_format *pix = &format->fmt.pix;
1047
1048 *pix = chan->format;
1049
1050 return 0;
1051}
1052
1053static int
1054__tegra_channel_try_format(struct tegra_channel *chan,
1055 struct v4l2_pix_format *pix)
1056{
1057 const struct tegra_video_format *vfmt;
1058 struct v4l2_subdev_format fmt;
1059 struct v4l2_subdev *sd = chan->subdev_on_csi;
1060 int ret = 0;
1061
1062 /* Use the channel format if pixformat is not supported */
1063 vfmt = tegra_core_get_format_by_fourcc(chan, pix->pixelformat);
1064 if (!vfmt) {
1065 pix->pixelformat = chan->format.pixelformat;
1066 vfmt = tegra_core_get_format_by_fourcc(chan, pix->pixelformat);
1067 }
1068
1069 fmt.which = V4L2_SUBDEV_FORMAT_TRY;
1070 fmt.pad = 0;
1071 v4l2_fill_mbus_format(&fmt.format, pix, vfmt->code);
1072
1073 ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt);
1074 if (ret == -ENOIOCTLCMD)
1075 return -ENOTTY;
1076
1077 v4l2_fill_pix_format(pix, &fmt.format);
1078
1079 tegra_channel_fmt_align(chan, vfmt,
1080 &pix->width, &pix->height, &pix->bytesperline);
1081 pix->sizeimage = get_aligned_buffer_size(chan,
1082 pix->bytesperline, pix->height);
1083 if (chan->fmtinfo->fourcc == V4L2_PIX_FMT_NV16)
1084 pix->sizeimage *= 2;
1085
1086 return ret;
1087}
1088
1089static int
1090tegra_channel_try_format(struct file *file, void *fh,
1091 struct v4l2_format *format)
1092{
1093 struct v4l2_fh *vfh = file->private_data;
1094 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
1095
1096 return __tegra_channel_try_format(chan, &format->fmt.pix);
1097}
1098
1099static int
1100__tegra_channel_set_format(struct tegra_channel *chan,
1101 struct v4l2_pix_format *pix)
1102{
1103 const struct tegra_video_format *vfmt;
1104 struct v4l2_subdev_format fmt;
1105 struct v4l2_subdev *sd = chan->subdev_on_csi;
1106 int ret = 0;
1107
1108 vfmt = tegra_core_get_format_by_fourcc(chan, pix->pixelformat);
1109
1110 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
1111 fmt.pad = 0;
1112 v4l2_fill_mbus_format(&fmt.format, pix, vfmt->code);
1113
1114 ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt);
1115 if (ret == -ENOIOCTLCMD)
1116 return -ENOTTY;
1117
1118 v4l2_fill_pix_format(pix, &fmt.format);
1119
1120 if (!ret) {
1121 chan->format = *pix;
1122 chan->fmtinfo = vfmt;
1123 tegra_channel_update_format(chan, pix->width,
1124 pix->height, vfmt->fourcc, &vfmt->bpp,
1125 pix->bytesperline);
1126
1127 *pix = chan->format;
1128
1129 if (chan->total_ports > 1)
1130 update_gang_mode(chan);
1131 }
1132
1133 return ret;
1134}
1135
1136static int
1137tegra_channel_set_format(struct file *file, void *fh,
1138 struct v4l2_format *format)
1139{
1140 struct v4l2_fh *vfh = file->private_data;
1141 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
1142 int ret = 0;
1143
1144 /* get the suppod format by try_fmt */
1145 ret = __tegra_channel_try_format(chan, &format->fmt.pix);
1146 if (ret)
1147 return ret;
1148
1149 if (vb2_is_busy(&chan->queue))
1150 return -EBUSY;
1151
1152 return __tegra_channel_set_format(chan, &format->fmt.pix);
1153}
1154
1155static int tegra_channel_subscribe_event(struct v4l2_fh *fh,
1156 const struct v4l2_event_subscription *sub)
1157{
1158 switch (sub->type) {
1159 case V4L2_EVENT_SOURCE_CHANGE:
1160 return v4l2_event_subscribe(fh, sub, 4, NULL);
1161 }
1162 return v4l2_ctrl_subscribe_event(fh, sub);
1163}
1164
1165static int
1166tegra_channel_enum_input(struct file *file, void *fh, struct v4l2_input *inp)
1167{
1168 struct v4l2_fh *vfh = file->private_data;
1169 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
1170 struct v4l2_subdev *sd_on_csi = chan->subdev_on_csi;
1171 int ret;
1172
1173 if (inp->index)
1174 return -EINVAL;
1175
1176 ret = v4l2_device_call_until_err(chan->video.v4l2_dev,
1177 chan->grp_id, video, g_input_status, &inp->status);
1178
1179 if (ret == -ENODEV || sd_on_csi == NULL)
1180 return -ENODEV;
1181
1182 inp->type = V4L2_INPUT_TYPE_CAMERA;
1183 if (v4l2_subdev_has_op(sd_on_csi, video, s_dv_timings)) {
1184 inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
1185 snprintf(inp->name,
1186 sizeof(inp->name), "HDMI %u",
1187 chan->port[0]);
1188 } else
1189 snprintf(inp->name,
1190 sizeof(inp->name), "Camera %u",
1191 chan->port[0]);
1192
1193 return ret;
1194}
1195
1196static int tegra_channel_g_input(struct file *file, void *priv, unsigned int *i)
1197{
1198 *i = 0;
1199 return 0;
1200}
1201
1202static int tegra_channel_s_input(struct file *file, void *priv, unsigned int i)
1203{
1204 if (i > 0)
1205 return -EINVAL;
1206 return 0;
1207}
1208
1209static int tegra_channel_log_status(struct file *file, void *priv)
1210{
1211 struct v4l2_fh *vfh = file->private_data;
1212 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
1213
1214 v4l2_device_call_all(chan->video.v4l2_dev,
1215 chan->grp_id, core, log_status);
1216 return 0;
1217}
1218
1219static long tegra_channel_default_ioctl(struct file *file, void *fh,
1220 bool use_prio, unsigned int cmd, void *arg)
1221{
1222 struct v4l2_fh *vfh = file->private_data;
1223 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
1224 struct tegra_mc_vi *vi = chan->vi;
1225 long ret = 0;
1226
1227 if (vi->fops && vi->fops->vi_default_ioctl)
1228 ret = vi->fops->vi_default_ioctl(file, fh, use_prio, cmd, arg);
1229
1230 return ret;
1231}
1232
1233#ifdef CONFIG_COMPAT
1234static long tegra_channel_compat_ioctl(struct file *filp,
1235 unsigned int cmd, unsigned long arg)
1236{
1237 struct video_device *vdev = video_devdata(filp);
1238 int ret = -ENODEV;
1239
1240 if (vdev->fops->unlocked_ioctl) {
1241 struct mutex *lock = v4l2_ioctl_get_lock(vdev, cmd);
1242
1243 if (lock && mutex_lock_interruptible(lock))
1244 return -ERESTARTSYS;
1245 if (video_is_registered(vdev))
1246 ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
1247 if (lock)
1248 mutex_unlock(lock);
1249 } else
1250 ret = -ENOTTY;
1251
1252 return ret;
1253}
1254#endif
1255
1256static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = {
1257 .vidioc_querycap = tegra_channel_querycap,
1258 .vidioc_enum_framesizes = tegra_channel_enum_framesizes,
1259 .vidioc_enum_frameintervals = tegra_channel_enum_frameintervals,
1260 .vidioc_enum_fmt_vid_cap = tegra_channel_enum_format,
1261 .vidioc_g_fmt_vid_cap = tegra_channel_get_format,
1262 .vidioc_s_fmt_vid_cap = tegra_channel_set_format,
1263 .vidioc_try_fmt_vid_cap = tegra_channel_try_format,
1264 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1265 .vidioc_querybuf = vb2_ioctl_querybuf,
1266 .vidioc_qbuf = vb2_ioctl_qbuf,
1267 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1268 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1269 .vidioc_expbuf = vb2_ioctl_expbuf,
1270 .vidioc_streamon = vb2_ioctl_streamon,
1271 .vidioc_streamoff = vb2_ioctl_streamoff,
1272 .vidioc_g_edid = tegra_channel_g_edid,
1273 .vidioc_s_edid = tegra_channel_s_edid,
1274 .vidioc_s_dv_timings = tegra_channel_s_dv_timings,
1275 .vidioc_g_dv_timings = tegra_channel_g_dv_timings,
1276 .vidioc_query_dv_timings = tegra_channel_query_dv_timings,
1277 .vidioc_enum_dv_timings = tegra_channel_enum_dv_timings,
1278 .vidioc_dv_timings_cap = tegra_channel_dv_timings_cap,
1279 .vidioc_subscribe_event = tegra_channel_subscribe_event,
1280 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1281 .vidioc_enum_input = tegra_channel_enum_input,
1282 .vidioc_g_input = tegra_channel_g_input,
1283 .vidioc_s_input = tegra_channel_s_input,
1284 .vidioc_log_status = tegra_channel_log_status,
1285 .vidioc_default = tegra_channel_default_ioctl,
1286};
1287
1288static int tegra_channel_close(struct file *fp);
1289static int tegra_channel_open(struct file *fp)
1290{
1291 int ret;
1292 struct video_device *vdev = video_devdata(fp);
1293 struct tegra_channel *chan = video_get_drvdata(vdev);
1294#ifdef T210
1295 struct vi *tegra_vi;
1296#endif
1297 struct tegra_mc_vi *vi;
1298 struct tegra_csi_device *csi;
1299
1300 mutex_lock(&chan->video_lock);
1301 ret = v4l2_fh_open(fp);
1302 if (ret || !v4l2_fh_is_singular_file(fp)) {
1303 mutex_unlock(&chan->video_lock);
1304 return ret;
1305 }
1306
1307 if (chan->subdev[0] == NULL) {
1308 ret = -ENODEV;
1309 goto fail;
1310 }
1311
1312 vi = chan->vi;
1313#ifdef T210
1314 tegra_vi = vi->vi;
1315#endif
1316 csi = vi->csi;
1317
1318 /* The first open then turn on power */
1319 if (vi->fops)
1320 ret = vi->fops->vi_power_on(chan);
1321 if (ret < 0)
1322 goto fail;
1323
1324 chan->fh = (struct v4l2_fh *)fp->private_data;
1325
1326 mutex_unlock(&chan->video_lock);
1327 return 0;
1328
1329fail:
1330 tegra_channel_close(fp);
1331 mutex_unlock(&chan->video_lock);
1332 return ret;
1333}
1334
1335static int tegra_channel_close(struct file *fp)
1336{
1337 int ret = 0;
1338 struct video_device *vdev = video_devdata(fp);
1339 struct tegra_channel *chan = video_get_drvdata(vdev);
1340 struct tegra_mc_vi *vi = chan->vi;
1341 bool is_singular;
1342
1343 mutex_lock(&chan->video_lock);
1344 is_singular = v4l2_fh_is_singular_file(fp);
1345 ret = _vb2_fop_release(fp, NULL);
1346
1347 if (!is_singular) {
1348 mutex_unlock(&chan->video_lock);
1349 return ret;
1350 }
1351 vi->fops->vi_power_off(chan);
1352
1353 mutex_unlock(&chan->video_lock);
1354 return ret;
1355}
1356
1357/* -----------------------------------------------------------------------------
1358 * V4L2 file operations
1359 */
1360static const struct v4l2_file_operations tegra_channel_fops = {
1361 .owner = THIS_MODULE,
1362 .unlocked_ioctl = video_ioctl2,
1363#ifdef CONFIG_COMPAT
1364 .compat_ioctl32 = tegra_channel_compat_ioctl,
1365#endif
1366 .open = tegra_channel_open,
1367 .release = tegra_channel_close,
1368 .read = vb2_fop_read,
1369 .poll = vb2_fop_poll,
1370 .mmap = vb2_fop_mmap,
1371};
1372
1373static int tegra_channel_csi_init(struct tegra_channel *chan)
1374{
1375 int numlanes = 0;
1376 int idx = 0;
1377 struct tegra_mc_vi *vi = chan->vi;
1378 int ret = 0;
1379
1380 chan->gang_mode = CAMERA_NO_GANG_MODE;
1381 chan->total_ports = 0;
1382 memset(&chan->port[0], INVALID_CSI_PORT, TEGRA_CSI_BLOCKS);
1383 memset(&chan->syncpoint_fifo[0], 0, TEGRA_CSI_BLOCKS);
1384 if (chan->pg_mode) {
1385 /* If VI has 4 existing channels, chan->id will start
1386 * from 4 for the first TPG channel, which uses PORT_A(0).
1387 * To get the correct PORT number, subtract existing number of
1388 * channels from chan->id.
1389 */
1390 chan->port[0] = chan->id - vi->num_channels;
1391 WARN_ON(chan->port[0] > TPG_CHANNELS);
1392 chan->numlanes = 2;
1393 } else {
1394 ret = tegra_vi_get_port_info(chan, vi->dev->of_node, chan->id);
1395 if (ret) {
1396 dev_err(vi->dev, "%s:Fail to parse port info\n",
1397 __func__);
1398 return ret;
1399 }
1400 }
1401
1402 for (idx = 0; csi_port_is_valid(chan->port[idx]); idx++) {
1403 chan->total_ports++;
1404 numlanes = chan->numlanes - (idx * MAX_CSI_BLOCK_LANES);
1405 numlanes = numlanes > MAX_CSI_BLOCK_LANES ?
1406 MAX_CSI_BLOCK_LANES : numlanes;
1407 /* maximum of 4 lanes are present per CSI block */
1408 chan->csibase[idx] = vi->iomem +
1409 TEGRA_VI_CSI_BASE(chan->port[idx]);
1410#ifdef T210
1411 set_csi_portinfo(vi->csi, chan->port[idx], numlanes);
1412#endif
1413 }
1414 /* based on gang mode valid ports will be updated - set default to 1 */
1415 chan->valid_ports = chan->total_ports ? 1 : 0;
1416 return ret;
1417}
1418
1419int tegra_channel_init(struct tegra_channel *chan)
1420{
1421 int ret;
1422 struct tegra_mc_vi *vi = chan->vi;
1423
1424#ifdef T210
1425 chan->fops = vi->vi->data->channel_fops;
1426#endif
1427 ret = tegra_channel_csi_init(chan);
1428 if (ret)
1429 return ret;
1430
1431 chan->width_align = TEGRA_WIDTH_ALIGNMENT;
1432 chan->stride_align = TEGRA_STRIDE_ALIGNMENT;
1433 chan->num_subdevs = 0;
1434 mutex_init(&chan->video_lock);
1435 INIT_LIST_HEAD(&chan->capture);
1436 init_waitqueue_head(&chan->start_wait);
1437 spin_lock_init(&chan->start_lock);
1438 mutex_init(&chan->stop_kthread_lock);
1439 atomic_set(&chan->is_streaming, DISABLE);
1440 spin_lock_init(&chan->capture_state_lock);
1441
1442 /* Init video format */
1443 vi->fops->vi_init_video_formats(chan);
1444 chan->fmtinfo = tegra_core_get_default_format();
1445 tegra_channel_update_format(chan, TEGRA_DEF_WIDTH,
1446 TEGRA_DEF_HEIGHT,
1447 chan->fmtinfo->fourcc,
1448 &chan->fmtinfo->bpp, 0);
1449
1450 chan->buffer_offset[0] = 0;
1451
1452 /* Initialize the media entity... */
1453 chan->pad.flags = MEDIA_PAD_FL_SINK;
1454
1455 ret = media_entity_init(&chan->video.entity, 1, &chan->pad, 0);
1456 if (ret < 0) {
1457 dev_err(&chan->video.dev, "failed to init video entity\n");
1458 return ret;
1459 }
1460
1461 /* init control handler */
1462 ret = v4l2_ctrl_handler_init(&chan->ctrl_handler, MAX_CID_CONTROLS);
1463 if (chan->ctrl_handler.error) {
1464 dev_err(&chan->video.dev, "failed to init control handler\n");
1465 goto ctrl_init_error;
1466 }
1467
1468 /* init video node... */
1469 chan->video.fops = &tegra_channel_fops;
1470 chan->video.v4l2_dev = &vi->v4l2_dev;
1471 chan->video.queue = &chan->queue;
1472 snprintf(chan->video.name, sizeof(chan->video.name), "%s-%s-%u",
1473 dev_name(vi->dev), chan->pg_mode ? "tpg" : "output",
1474 chan->port[0]);
1475 chan->video.vfl_type = VFL_TYPE_GRABBER;
1476 chan->video.vfl_dir = VFL_DIR_RX;
1477 chan->video.release = video_device_release_empty;
1478 chan->video.ioctl_ops = &tegra_channel_ioctl_ops;
1479 chan->video.ctrl_handler = &chan->ctrl_handler;
1480 chan->video.lock = &chan->video_lock;
1481
1482 set_bit(_IOC_NR(VIDIOC_G_PRIORITY), chan->video.valid_ioctls);
1483 set_bit(_IOC_NR(VIDIOC_S_PRIORITY), chan->video.valid_ioctls);
1484
1485 video_set_drvdata(&chan->video, chan);
1486
1487#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
1488 /* get the buffers queue... */
1489 chan->alloc_ctx = vb2_dma_contig_init_ctx(chan->vi->dev);
1490 if (IS_ERR(chan->alloc_ctx)) {
1491 dev_err(chan->vi->dev, "failed to init vb2 buffer\n");
1492 ret = -ENOMEM;
1493 goto vb2_init_error;
1494 }
1495#endif
1496
1497 chan->queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1498 chan->queue.io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ | VB2_USERPTR;
1499 chan->queue.lock = &chan->video_lock;
1500 chan->queue.drv_priv = chan;
1501 chan->queue.buf_struct_size = sizeof(struct tegra_channel_buffer);
1502 chan->queue.ops = &tegra_channel_queue_qops;
1503#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
1504 chan->queue.mem_ops = &vb2_dma_contig_memops;
1505#endif
1506 chan->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
1507 | V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
1508 ret = vb2_queue_init(&chan->queue);
1509 if (ret < 0) {
1510 dev_err(chan->vi->dev, "failed to initialize VB2 queue\n");
1511 goto vb2_queue_error;
1512 }
1513
1514 chan->init_done = true;
1515 return 0;
1516
1517vb2_queue_error:
1518#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
1519 vb2_dma_contig_cleanup_ctx(chan->alloc_ctx);
1520vb2_init_error:
1521#endif
1522 v4l2_ctrl_handler_free(&chan->ctrl_handler);
1523ctrl_init_error:
1524 media_entity_cleanup(&chan->video.entity);
1525 return ret;
1526}
1527
1528int tegra_channel_cleanup(struct tegra_channel *chan)
1529{
1530 v4l2_ctrl_handler_free(&chan->ctrl_handler);
1531 vb2_queue_release(&chan->queue);
1532#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG)
1533 vb2_dma_contig_cleanup_ctx(chan->alloc_ctx);
1534#endif
1535
1536 media_entity_cleanup(&chan->video.entity);
1537
1538 return 0;
1539}
1540
1541int tegra_vi_channels_register(struct tegra_mc_vi *vi)
1542{
1543 int ret = 0;
1544 struct tegra_channel *it;
1545 int count = 0;
1546
1547 list_for_each_entry(it, &vi->vi_chans, list) {
1548 if (!it->init_done)
1549 continue;
1550 ret = video_register_device(&it->video, VFL_TYPE_GRABBER, -1);
1551 if (ret < 0) {
1552 dev_err(&it->video.dev, "failed to register %s\n",
1553 it->video.name);
1554 continue;
1555 }
1556 count++;
1557 }
1558
1559 if (count == 0) {
1560 dev_err(vi->dev, "all channel register failed\n");
1561 return ret;
1562 }
1563
1564 return 0;
1565}
1566
1567void tegra_vi_channels_unregister(struct tegra_mc_vi *vi)
1568{
1569 struct tegra_channel *it;
1570
1571 list_for_each_entry(it, &vi->vi_chans, list) {
1572 if (it->video.cdev != NULL)
1573 video_unregister_device(&it->video);
1574 }
1575}
1576
1577int tegra_vi_channels_init(struct tegra_mc_vi *vi)
1578{
1579 int ret = 0;
1580 struct tegra_channel *it;
1581 int count = 0;
1582
1583 list_for_each_entry(it, &vi->vi_chans, list) {
1584 it->vi = vi;
1585 ret = tegra_channel_init(it);
1586 if (ret < 0) {
1587 dev_err(vi->dev, "channel init failed\n");
1588 continue;
1589 }
1590 count++;
1591 }
1592
1593 if (count == 0) {
1594 dev_err(vi->dev, "all channel init failed\n");
1595 return ret;
1596 }
1597
1598 return 0;
1599}
1600EXPORT_SYMBOL(tegra_vi_channels_init);
1601
1602int tegra_vi_channels_cleanup(struct tegra_mc_vi *vi)
1603{
1604 int ret = 0, err = 0;
1605 struct tegra_channel *it;
1606
1607 list_for_each_entry(it, &vi->vi_chans, list) {
1608 if (!it->init_done)
1609 continue;
1610 err = tegra_channel_cleanup(it);
1611 if (err < 0) {
1612 ret = err;
1613 dev_err(vi->dev, "channel cleanup failed, err %d\n",
1614 err);
1615 }
1616 }
1617 return ret;
1618}
1619EXPORT_SYMBOL(tegra_vi_channels_cleanup);
1620
1621int tegra_clean_unlinked_channels(struct tegra_mc_vi *vi)
1622{
1623 int ret, err = 0;
1624 struct tegra_channel *chan;
1625
1626 list_for_each_entry(chan, &vi->vi_chans, list) {
1627 struct v4l2_subdev *sd = chan->subdev_on_csi;
1628 bool is_csi = false;
1629
1630 /*
1631 * If subdevice on csi is csi itself,
1632 * then sensor subdevice is not connected
1633 */
1634 if (sd)
1635 is_csi = strstr(sd->name, "nvcsi") != NULL;
1636
1637 if (chan->num_subdevs && !is_csi)
1638 continue;
1639
1640 ret = tegra_channel_cleanup(chan);
1641 if (ret < 0) {
1642 err = ret;
1643 dev_err(vi->dev, "channel cleanup failed, err %d\n",
1644 err);
1645 }
1646 }
1647
1648 return err;
1649}
1650EXPORT_SYMBOL(tegra_clean_unlinked_channels);
diff --git a/drivers/media/platform/tegra/camera/vi/core.c b/drivers/media/platform/tegra/camera/vi/core.c
new file mode 100644
index 000000000..97de67085
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/core.c
@@ -0,0 +1,173 @@
1/*
2 * NVIDIA Tegra Video Input Device Driver Core Helpers
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/export.h>
14#include <linux/kernel.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17
18#include "camera/vi/mc_common.h"
19
20static const struct tegra_video_format tegra_default_format[] = {
21 {
22 TEGRA_VF_DEF,
23 10,
24 MEDIA_BUS_FMT_SRGGB10_1X10,
25 {2, 1},
26 TEGRA_IMAGE_FORMAT_DEF,
27 TEGRA_IMAGE_DT_RAW10,
28 V4L2_PIX_FMT_SRGGB10,
29 "RGRG.. GBGB..",
30 },
31};
32
33/* -----------------------------------------------------------------------------
34 * Helper functions
35 */
36
37/**
38 * tegra_core_get_fourcc_by_idx - get fourcc of a tegra_video format
39 * @index: array index of the tegra_video_formats
40 *
41 * Return: fourcc code
42 */
43u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan,
44 unsigned int index)
45{
46 /* return default fourcc format if the index out of bounds */
47 if (index > (chan->num_video_formats - 1))
48 return V4L2_PIX_FMT_SGRBG10;
49
50 return chan->video_formats[index]->fourcc;
51}
52
53/**
54 * tegra_core_get_description_by_idx - get description of a tegra_video format
55 * @index: array index of the tegra_video_formats
56 */
57void tegra_core_get_description_by_idx(struct tegra_channel *chan,
58 unsigned int index, __u8 *description)
59{
60 if (index > (chan->num_video_formats - 1))
61 return;
62
63 if (description)
64 strlcpy(description,
65 chan->video_formats[index]->description,
66 sizeof(chan->video_formats[index]->description));
67}
68
69/**
70 * tegra_core_get_word_count - Calculate word count
71 * @frame_width: number of pixels per line
72 * @fmt: Tegra Video format struct which has BPP information
73 *
74 * Return: word count number
75 */
76u32 tegra_core_get_word_count(unsigned int frame_width,
77 const struct tegra_video_format *fmt)
78{
79 return frame_width * fmt->width / 8;
80}
81
82/**
83 * tegra_core_get_idx_by_code - Retrieve index for a media bus code
84 * @code: the format media bus code
85 *
86 * Return: a index to the format information structure corresponding to the
87 * given V4L2 media bus format @code, or -1 if no corresponding format can
88 * be found.
89 */
90int tegra_core_get_idx_by_code(struct tegra_channel *chan,
91 unsigned int code, unsigned offset)
92{
93 unsigned int i;
94
95 for (i = offset; i < chan->num_video_formats; ++i) {
96 if (chan->video_formats[i]->code == code)
97 return i;
98 }
99
100 return -1;
101}
102
103/**
104 * tegra_core_get_default_format - Get default format
105 *
106 * Return: pointer to the format where the default format needs
107 * to be filled in.
108 */
109const struct tegra_video_format *tegra_core_get_default_format(void)
110{
111 return &tegra_default_format[0];
112}
113
114/**
115 * tegra_core_get_format_by_code - Retrieve format information for a media
116 * bus code
117 * @code: the format media bus code
118 *
119 * Return: a pointer to the format information structure corresponding to the
120 * given V4L2 media bus format @code, or NULL if no corresponding format can
121 * be found.
122 */
123const struct tegra_video_format *
124tegra_core_get_format_by_code(struct tegra_channel *chan,
125 unsigned int code, unsigned offset)
126{
127 unsigned int i;
128
129 for (i = offset; i < chan->num_video_formats; ++i) {
130 if (chan->video_formats[i]->code == code)
131 return chan->video_formats[i];
132 }
133
134 return NULL;
135}
136
137/**
138 * tegra_core_get_format_by_fourcc - Retrieve format information for a 4CC
139 * @fourcc: the format 4CC
140 *
141 * Return: a pointer to the format information structure corresponding to the
142 * given V4L2 format @fourcc, or NULL if no corresponding format can be
143 * found.
144 */
145const struct tegra_video_format *
146tegra_core_get_format_by_fourcc(struct tegra_channel *chan, u32 fourcc)
147{
148 unsigned int i;
149
150 for (i = 0; i < chan->num_video_formats; ++i) {
151 if (chan->video_formats[i]->fourcc == fourcc)
152 return chan->video_formats[i];
153 }
154
155 return NULL;
156}
157
158/**
159 * tegra_core_bytes_per_line - Calculate bytes per line in one frame
160 * @width: frame width
161 * @align: number of alignment bytes
162 * @fmt: Tegra Video format
163 *
164 * Simply calcualte the bytes_per_line and if it's not aligned it
165 * will be padded to alignment boundary.
166 */
167u32 tegra_core_bytes_per_line(unsigned int width, unsigned int align,
168 const struct tegra_video_format *fmt)
169{
170 u32 value = ((width * fmt->bpp.numerator) / fmt->bpp.denominator);
171
172 return roundup(value, align);
173}
diff --git a/drivers/media/platform/tegra/camera/vi/core.h b/drivers/media/platform/tegra/camera/vi/core.h
new file mode 100644
index 000000000..56b24fd59
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/core.h
@@ -0,0 +1,127 @@
1/*
2 * NVIDIA Tegra Video Input Device Driver Core Helpers
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __TEGRA_CORE_H__
14#define __TEGRA_CORE_H__
15
16#include <media/v4l2-subdev.h>
17
18/* Minimum and maximum width and height common to Tegra video input device. */
19#define TEGRA_MIN_WIDTH 32U
20#define TEGRA_MAX_WIDTH 32768U
21#define TEGRA_MIN_HEIGHT 32U
22#define TEGRA_MAX_HEIGHT 32768U
23/* Width alignment */
24#define TEGRA_WIDTH_ALIGNMENT 1
25/* Stride alignment is 256, for VIC worse case */
26#define TEGRA_STRIDE_ALIGNMENT 256
27
28/* 1080p resolution as default resolution for test pattern generator */
29#define TEGRA_DEF_WIDTH 1920
30#define TEGRA_DEF_HEIGHT 1080
31
32#define TEGRA_VF_DEF MEDIA_BUS_FMT_SRGGB10_1X10
33#define TEGRA_IMAGE_FORMAT_DEF 32
34
35enum tegra_image_dt {
36 TEGRA_IMAGE_DT_YUV420_8 = 24,
37 TEGRA_IMAGE_DT_YUV420_10,
38
39 TEGRA_IMAGE_DT_YUV420CSPS_8 = 28,
40 TEGRA_IMAGE_DT_YUV420CSPS_10,
41 TEGRA_IMAGE_DT_YUV422_8,
42 TEGRA_IMAGE_DT_YUV422_10,
43 TEGRA_IMAGE_DT_RGB444,
44 TEGRA_IMAGE_DT_RGB555,
45 TEGRA_IMAGE_DT_RGB565,
46 TEGRA_IMAGE_DT_RGB666,
47 TEGRA_IMAGE_DT_RGB888,
48
49 TEGRA_IMAGE_DT_RAW6 = 40,
50 TEGRA_IMAGE_DT_RAW7,
51 TEGRA_IMAGE_DT_RAW8,
52 TEGRA_IMAGE_DT_RAW10,
53 TEGRA_IMAGE_DT_RAW12,
54 TEGRA_IMAGE_DT_RAW14,
55};
56
57/* Supported CSI to VI Data Formats */
58enum tegra_vf_code {
59 TEGRA_VF_RAW6 = 0,
60 TEGRA_VF_RAW7,
61 TEGRA_VF_RAW8,
62 TEGRA_VF_RAW10,
63 TEGRA_VF_RAW12,
64 TEGRA_VF_RAW14,
65 TEGRA_VF_EMBEDDED8,
66 TEGRA_VF_RGB565,
67 TEGRA_VF_RGB555,
68 TEGRA_VF_RGB888,
69 TEGRA_VF_RGB444,
70 TEGRA_VF_RGB666,
71 TEGRA_VF_YUV422,
72 TEGRA_VF_YUV420,
73 TEGRA_VF_YUV420_CSPS,
74};
75
76/**
77 * struct tegra_frac
78 * @numerator: numerator of the fraction
79 * @denominator: denominator of the fraction
80 */
81struct tegra_frac {
82 unsigned int numerator;
83 unsigned int denominator;
84};
85
86/**
87 * struct tegra_video_format - Tegra video format description
88 * @vf_code: video format code
89 * @width: format width in bits per component
90 * @code: media bus format code
91 * @bpp: bytes per pixel fraction (when stored in memory)
92 * @img_fmt: image format
93 * @img_dt: image data type
94 * @fourcc: V4L2 pixel format FCC identifier
95 * @description: format description, suitable for userspace
96 */
97struct tegra_video_format {
98 enum tegra_vf_code vf_code;
99 unsigned int width;
100 unsigned int code;
101 struct tegra_frac bpp;
102 u32 img_fmt;
103 enum tegra_image_dt img_dt;
104 u32 fourcc;
105 __u8 description[32];
106};
107
108#define TEGRA_VIDEO_FORMAT(VF_CODE, BPP, MBUS_CODE, FRAC_BPP_NUM, \
109 FRAC_BPP_DEN, FORMAT, DATA_TYPE, FOURCC, DESCRIPTION) \
110{ \
111 TEGRA_VF_##VF_CODE, \
112 BPP, \
113 MEDIA_BUS_FMT_##MBUS_CODE, \
114 {FRAC_BPP_NUM, FRAC_BPP_DEN}, \
115 TEGRA_IMAGE_FORMAT_##FORMAT, \
116 TEGRA_IMAGE_DT_##DATA_TYPE, \
117 V4L2_PIX_FMT_##FOURCC, \
118 DESCRIPTION, \
119}
120
121u32 tegra_core_get_word_count(unsigned int frame_width,
122 const struct tegra_video_format *fmt);
123u32 tegra_core_bytes_per_line(unsigned int width, unsigned int align,
124 const struct tegra_video_format *fmt);
125const struct tegra_video_format *tegra_core_get_default_format(void);
126
127#endif
diff --git a/drivers/media/platform/tegra/camera/vi/graph.c b/drivers/media/platform/tegra/camera/vi/graph.c
new file mode 100644
index 000000000..c2dd058a1
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/graph.c
@@ -0,0 +1,602 @@
1/*
2 * NVIDIA Media controller graph management
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/clk.h>
13#include <linux/list.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/of_graph.h>
17#include <linux/of_device.h>
18#include <linux/platform_device.h>
19#include <linux/regulator/consumer.h>
20#include <linux/reset.h>
21#include <linux/slab.h>
22#include <linux/tegra-soc.h>
23#include <linux/tegra_pm_domains.h>
24
25#include <media/media-device.h>
26#include <media/v4l2-async.h>
27#include <media/v4l2-common.h>
28#include <media/v4l2-device.h>
29#include <media/v4l2-of.h>
30#include <media/tegra_v4l2_camera.h>
31
32#include "camera/vi/mc_common.h"
33#include "camera/csi/csi.h"
34#include "vi/vi4.h"
35#include "nvcsi/nvcsi.h"
36
37/* -----------------------------------------------------------------------------
38 * Graph Management
39 */
40
41static struct tegra_vi_graph_entity *
42tegra_vi_graph_find_entity(struct tegra_mc_vi *vi,
43 const struct device_node *node)
44{
45 struct tegra_vi_graph_entity *entity;
46
47 list_for_each_entry(entity, &vi->entities, list) {
48 if (entity->node == node)
49 return entity;
50 }
51
52 return NULL;
53}
54
55static int tegra_vi_graph_build_one(struct tegra_mc_vi *vi,
56 struct tegra_vi_graph_entity *entity)
57{
58 u32 link_flags = MEDIA_LNK_FL_ENABLED;
59 struct media_entity *local;
60 struct media_entity *remote;
61 struct media_pad *local_pad;
62 struct media_pad *remote_pad;
63 struct tegra_vi_graph_entity *ent;
64 struct v4l2_of_link link;
65 struct device_node *ep = NULL;
66 struct device_node *next;
67 int ret = 0;
68
69 if (!entity->subdev) {
70 dev_err(vi->dev, "%s:No subdev under entity, skip linking\n",
71 __func__);
72 return 0;
73 }
74
75 local = entity->entity;
76 dev_dbg(vi->dev, "creating links for entity %s\n", local->name);
77
78 do {
79 /* Get the next endpoint and parse its link. */
80 next = of_graph_get_next_endpoint(entity->node, ep);
81 if (next == NULL)
82 break;
83
84 ep = next;
85
86 dev_dbg(vi->dev, "processing endpoint %s\n", ep->full_name);
87
88 ret = v4l2_of_parse_link(ep, &link);
89 if (ret < 0) {
90 dev_err(vi->dev, "failed to parse link for %s\n",
91 ep->full_name);
92 continue;
93 }
94
95 /* Skip sink ports, they will be processed from the other end of
96 * the link.
97 */
98 if (link.local_port >= local->num_pads) {
99 dev_err(vi->dev, "invalid port number %u on %s\n",
100 link.local_port, link.local_node->full_name);
101 v4l2_of_put_link(&link);
102 ret = -EINVAL;
103 break;
104 }
105
106 local_pad = &local->pads[link.local_port];
107
108 if (local_pad->flags & MEDIA_PAD_FL_SINK) {
109 dev_dbg(vi->dev, "skipping sink port %s:%u\n",
110 link.local_node->full_name, link.local_port);
111 v4l2_of_put_link(&link);
112 continue;
113 }
114
115 /* Skip channel entity , they will be processed separately. */
116 if (link.remote_node == vi->dev->of_node) {
117 dev_dbg(vi->dev, "skipping channel port %s:%u\n",
118 link.local_node->full_name, link.local_port);
119 v4l2_of_put_link(&link);
120 continue;
121 }
122
123 /* Find the remote entity. */
124 ent = tegra_vi_graph_find_entity(vi, link.remote_node);
125 if (ent == NULL) {
126 dev_err(vi->dev, "no entity found for %s\n",
127 link.remote_node->full_name);
128 v4l2_of_put_link(&link);
129 ret = -EINVAL;
130 break;
131 }
132
133 remote = ent->entity;
134
135 if (link.remote_port >= remote->num_pads) {
136 dev_err(vi->dev, "invalid port number %u on %s\n",
137 link.remote_port, link.remote_node->full_name);
138 v4l2_of_put_link(&link);
139 ret = -EINVAL;
140 break;
141 }
142
143 remote_pad = &remote->pads[link.remote_port];
144
145 v4l2_of_put_link(&link);
146
147 /* Create the media link. */
148 dev_dbg(vi->dev, "creating %s:%u -> %s:%u link\n",
149 local->name, local_pad->index,
150 remote->name, remote_pad->index);
151
152 ret = media_entity_create_link(local, local_pad->index,
153 remote, remote_pad->index,
154 link_flags);
155 if (ret < 0) {
156 dev_err(vi->dev,
157 "failed to create %s:%u -> %s:%u link\n",
158 local->name, local_pad->index,
159 remote->name, remote_pad->index);
160 break;
161 }
162 } while (next);
163
164 return ret;
165}
166
167static int tegra_vi_graph_build_links(struct tegra_mc_vi *vi)
168{
169 u32 link_flags = MEDIA_LNK_FL_ENABLED;
170 struct device_node *node = vi->dev->of_node;
171 struct media_entity *source;
172 struct media_entity *sink;
173 struct media_pad *source_pad;
174 struct media_pad *sink_pad;
175 struct tegra_vi_graph_entity *ent;
176 struct v4l2_of_link link;
177 struct device_node *ep = NULL;
178 struct device_node *next;
179 struct tegra_channel *chan;
180 int ret = 0;
181
182 dev_dbg(vi->dev, "creating links for channels\n");
183
184 chan = list_first_entry(&vi->vi_chans, struct tegra_channel, list);
185 do {
186 /* Get the next endpoint and parse its link. */
187 next = of_graph_get_next_endpoint(node, ep);
188 if (next == NULL || !of_device_is_available(next))
189 break;
190
191 /* Device not registered */
192 if (!chan->init_done) {
193 chan = list_next_entry(chan, list);
194 continue;
195 }
196
197 ep = next;
198
199 dev_dbg(vi->dev, "processing endpoint %s\n", ep->full_name);
200
201 ret = v4l2_of_parse_link(ep, &link);
202 if (ret < 0) {
203 dev_err(vi->dev, "failed to parse link for %s\n",
204 ep->full_name);
205 continue;
206 }
207
208 if (link.local_port >= vi->num_channels) {
209 dev_err(vi->dev, "wrong channel number for port %u\n",
210 link.local_port);
211 v4l2_of_put_link(&link);
212 ret = -EINVAL;
213 break;
214 }
215
216 dev_dbg(vi->dev, "creating link for channel %s\n",
217 chan->video.name);
218
219 /* Find the remote entity. */
220 ent = tegra_vi_graph_find_entity(vi, link.remote_node);
221 if (ent == NULL) {
222 dev_err(vi->dev, "no entity found for %s\n",
223 link.remote_node->full_name);
224 v4l2_of_put_link(&link);
225 ret = -EINVAL;
226 break;
227 }
228
229 if (ent->entity == NULL) {
230 dev_err(vi->dev, "entity not bounded %s\n",
231 link.remote_node->full_name);
232 continue;
233 }
234
235 source = ent->entity;
236 source_pad = &source->pads[link.remote_port];
237 sink = &chan->video.entity;
238 sink_pad = &chan->pad;
239
240 v4l2_of_put_link(&link);
241
242 /* Create the media link. */
243 dev_dbg(vi->dev, "creating %s:%u -> %s:%u link\n",
244 source->name, source_pad->index,
245 sink->name, sink_pad->index);
246
247 ret = media_entity_create_link(source, source_pad->index,
248 sink, sink_pad->index,
249 link_flags);
250 if (ret < 0) {
251 dev_err(vi->dev,
252 "failed to create %s:%u -> %s:%u link\n",
253 source->name, source_pad->index,
254 sink->name, sink_pad->index);
255 break;
256 }
257
258 tegra_channel_init_subdevices(chan);
259 chan = list_next_entry(chan, list);
260 } while (next != NULL);
261
262 return ret;
263}
264
265static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
266{
267 struct tegra_mc_vi *vi =
268 container_of(notifier, struct tegra_mc_vi, notifier);
269 struct tegra_vi_graph_entity *entity;
270 int ret;
271
272 dev_dbg(vi->dev, "notify complete, all subdevs registered\n");
273
274 /* Create links for every entity. */
275 list_for_each_entry(entity, &vi->entities, list) {
276 if (entity->entity != NULL) {
277 ret = tegra_vi_graph_build_one(vi, entity);
278 if (ret < 0)
279 return ret;
280 }
281 }
282
283 /* Create links for channels */
284 ret = tegra_vi_graph_build_links(vi);
285 if (ret < 0)
286 return ret;
287
288 ret = v4l2_device_register_subdev_nodes(&vi->v4l2_dev);
289 if (ret < 0)
290 dev_err(vi->dev, "failed to register subdev nodes\n");
291
292 vi->link_status++;
293
294 return ret;
295}
296
297static int tegra_vi_graph_notify_bound(struct v4l2_async_notifier *notifier,
298 struct v4l2_subdev *subdev,
299 struct v4l2_async_subdev *asd)
300{
301 struct tegra_mc_vi *vi =
302 container_of(notifier, struct tegra_mc_vi, notifier);
303 struct tegra_vi_graph_entity *entity;
304
305 /* Locate the entity corresponding to the bound subdev and store the
306 * subdev pointer.
307 */
308 list_for_each_entry(entity, &vi->entities, list) {
309 if (entity->node != subdev->dev->of_node &&
310 entity->node != subdev->of_node)
311 continue;
312
313 if (entity->subdev) {
314 dev_err(vi->dev, "duplicate subdev for node %s\n",
315 entity->node->full_name);
316 return -EINVAL;
317 }
318
319 dev_dbg(vi->dev, "subdev %s bound\n", subdev->name);
320 entity->entity = &subdev->entity;
321 entity->subdev = subdev;
322 vi->subdevs_bound++;
323 return 0;
324 }
325
326 dev_err(vi->dev, "no entity for subdev %s\n", subdev->name);
327 return -EINVAL;
328}
329
330void tegra_vi_graph_cleanup(struct tegra_mc_vi *vi)
331{
332 struct tegra_vi_graph_entity *entityp;
333 struct tegra_vi_graph_entity *entity;
334
335 v4l2_async_notifier_unregister(&vi->notifier);
336
337 list_for_each_entry_safe(entity, entityp, &vi->entities, list) {
338 of_node_put(entity->node);
339 list_del(&entity->list);
340 }
341}
342
343int tegra_vi_get_port_info(struct tegra_channel *chan,
344 struct device_node *node, unsigned int index)
345{
346 struct device_node *ep = NULL;
347 struct device_node *ports;
348 struct device_node *port;
349 int value = 0xFFFF;
350 int ret = 0, i;
351
352 ports = of_get_child_by_name(node, "ports");
353 if (ports == NULL)
354 ports = node;
355
356 for_each_child_of_node(ports, port) {
357 if (!port->name || of_node_cmp(port->name, "port"))
358 continue;
359
360 ret = of_property_read_u32(port, "reg", &value);
361 if (ret < 0)
362 continue;
363
364 if (value != index)
365 continue;
366
367 for_each_child_of_node(port, ep) {
368 if (!ep->name || of_node_cmp(ep->name, "endpoint"))
369 continue;
370
371 /* Get CSI port */
372 ret = of_property_read_u32(ep, "csi-port", &value);
373 if (ret < 0)
374 dev_err(&chan->video.dev, "csi port error\n");
375 chan->port[0] = value;
376
377 /* Get number of data lanes for the endpoint */
378 ret = of_property_read_u32(ep, "bus-width", &value);
379 if (ret < 0)
380 dev_err(&chan->video.dev, "num lanes error\n");
381 chan->numlanes = value;
382
383 if (value > 12) {
384 dev_err(&chan->video.dev, "num lanes >12!\n");
385 return -EINVAL;
386 }
387 /*
388 * for numlanes greater than 4 multiple CSI bricks
389 * are needed to capture the image, the logic below
390 * checks for numlanes > 4 and add a new CSI brick
391 * as a valid port. Loops around the three CSI
392 * bricks to add as many ports necessary.
393 */
394 value -= 4;
395 for (i = 1; value > 0; i++, value -= 4) {
396 int next_port = chan->port[i-1] + 2;
397
398 next_port = (next_port % (PORT_F + 1));
399 chan->port[i] = next_port;
400 }
401 }
402 }
403
404 return ret;
405}
406
407static int tegra_vi_graph_parse_one(struct tegra_mc_vi *vi,
408 struct device_node *node)
409{
410 struct device_node *ep = NULL;
411 struct device_node *next;
412 struct device_node *remote = NULL;
413 struct tegra_vi_graph_entity *entity;
414 int ret = 0;
415
416 dev_dbg(vi->dev, "parsing node %s\n", node->full_name);
417
418 do {
419 /* Parse all the remote entities and put them into the list */
420 next = of_graph_get_next_endpoint(node, ep);
421 if (next == NULL || !of_device_is_available(next))
422 break;
423 ep = next;
424
425 dev_dbg(vi->dev, "handling endpoint %s\n", ep->full_name);
426
427 remote = of_graph_get_remote_port_parent(ep);
428 if (!remote) {
429 ret = -EINVAL;
430 break;
431 }
432
433 /* Skip entities that we have already processed. */
434 if (remote == vi->dev->of_node ||
435 tegra_vi_graph_find_entity(vi, remote) ||
436 !of_device_is_available(remote))
437 continue;
438
439 entity = devm_kzalloc(vi->dev, sizeof(*entity),
440 GFP_KERNEL);
441 if (entity == NULL) {
442 ret = -ENOMEM;
443 break;
444 }
445
446 entity->node = remote;
447 entity->asd.match_type = V4L2_ASYNC_MATCH_OF;
448 entity->asd.match.of.node = remote;
449 list_add_tail(&entity->list, &vi->entities);
450 vi->num_subdevs++;
451 } while (next);
452
453 return ret;
454}
455
456int tegra_vi_tpg_graph_init(struct tegra_mc_vi *mc_vi)
457{
458 int err = 0;
459 u32 link_flags = MEDIA_LNK_FL_ENABLED;
460 struct tegra_csi_device *csi = mc_vi->csi;
461 struct tegra_channel *vi_it;
462 struct tegra_csi_channel *csi_it;
463
464 if (!csi) {
465 dev_err(mc_vi->dev, "CSI is NULL\n");
466 return -EINVAL;
467 }
468 mc_vi->num_subdevs = mc_vi->num_channels;
469 vi_it = mc_vi->tpg_start;
470 csi_it = csi->tpg_start;
471
472 list_for_each_entry_from(vi_it, &mc_vi->vi_chans, list) {
473 /* Device not registered */
474 if (!vi_it->init_done)
475 continue;
476
477 list_for_each_entry_from(csi_it, &csi->csi_chans, list) {
478 struct media_entity *source = &csi_it->subdev.entity;
479 struct media_entity *sink = &vi_it->video.entity;
480 struct media_pad *source_pad = csi_it->pads;
481 struct media_pad *sink_pad = &vi_it->pad;
482
483 vi_it->bypass = 0;
484 err = v4l2_device_register_subdev(&mc_vi->v4l2_dev,
485 &csi_it->subdev);
486 if (err) {
487 dev_err(mc_vi->dev,
488 "%s:Fail to register subdev\n",
489 __func__);
490 goto register_fail;
491 }
492 dev_dbg(mc_vi->dev, "creating %s:%u -> %s:%u link\n",
493 source->name, source_pad->index,
494 sink->name, sink_pad->index);
495
496 err = media_entity_create_link(source,
497 source_pad->index,
498 sink, sink_pad->index,
499 link_flags);
500 if (err < 0) {
501 dev_err(mc_vi->dev,
502 "failed to create %s:%u -> %s:%u link\n",
503 source->name, source_pad->index,
504 sink->name, sink_pad->index);
505 goto register_fail;
506 }
507 err = tegra_channel_init_subdevices(vi_it);
508 if (err) {
509 dev_err(mc_vi->dev,
510 "%s:Init subdevice error\n", __func__);
511 goto register_fail;
512 }
513 csi_it = list_next_entry(csi_it, list);
514 break;
515 }
516 }
517
518 return 0;
519register_fail:
520 csi_it = csi->tpg_start;
521 list_for_each_entry_from(csi_it, &csi->csi_chans, list)
522 v4l2_device_unregister_subdev(&csi_it->subdev);
523 return err;
524}
525
526int tegra_vi_graph_init(struct tegra_mc_vi *vi)
527{
528 struct tegra_vi_graph_entity *entity;
529 struct v4l2_async_subdev **subdevs = NULL;
530 unsigned int num_subdevs = 0;
531 int ret = 0, i;
532
533 /*
534 * Walk the links to parse the full graph. Start by parsing the
535 * composite node and then parse entities in turn. The list_for_each
536 * loop will handle entities added at the end of the list while walking
537 * the links.
538 */
539 ret = tegra_vi_graph_parse_one(vi, vi->dev->of_node);
540 if (ret < 0)
541 return 0;
542
543 list_for_each_entry(entity, &vi->entities, list) {
544 ret = tegra_vi_graph_parse_one(vi, entity->node);
545 if (ret < 0)
546 break;
547 }
548
549 if (!vi->num_subdevs) {
550 dev_dbg(vi->dev, "warning: no subdev found in graph\n");
551 goto done;
552 }
553
554 /* Register the subdevices notifier. */
555 num_subdevs = vi->num_subdevs;
556 subdevs = devm_kzalloc(vi->dev, sizeof(*subdevs) * num_subdevs,
557 GFP_KERNEL);
558 if (subdevs == NULL) {
559 ret = -ENOMEM;
560 goto done;
561 }
562
563 /*
564 * Add code to check for sensors and
565 * set TPG mode for VI if no sensors found
566 * logic varies for different platforms
567 */
568 i = 0;
569 list_for_each_entry(entity, &vi->entities, list)
570 subdevs[i++] = &entity->asd;
571
572 vi->notifier.subdevs = subdevs;
573 vi->notifier.num_subdevs = num_subdevs;
574 vi->notifier.bound = tegra_vi_graph_notify_bound;
575 vi->notifier.complete = tegra_vi_graph_notify_complete;
576 vi->link_status = 0;
577 vi->subdevs_bound = 0;
578
579 ret = v4l2_async_notifier_register(&vi->v4l2_dev, &vi->notifier);
580 if (ret < 0) {
581 dev_err(vi->dev, "notifier registration failed\n");
582 goto done;
583 }
584
585 if (!vi->link_status) {
586 if (vi->subdevs_bound) {
587 ret = tegra_vi_graph_notify_complete(&vi->notifier);
588 if (ret < 0)
589 goto done;
590 }
591 tegra_clean_unlinked_channels(vi);
592 }
593
594 return 0;
595
596done:
597 tegra_clean_unlinked_channels(vi);
598 if (ret < 0)
599 tegra_vi_graph_cleanup(vi);
600
601 return ret;
602}
diff --git a/drivers/media/platform/tegra/camera/vi/mc_common.c b/drivers/media/platform/tegra/camera/vi/mc_common.c
new file mode 100644
index 000000000..11acb7cfe
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/mc_common.c
@@ -0,0 +1,346 @@
1/*
2 * Tegra Video Input device common APIs
3 *
4 * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/export.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/of_platform.h>
19
20#include <media/tegra_v4l2_camera.h>
21#include <media/camera_common.h>
22#include <media/v4l2-event.h>
23#include <media/tegra_camera_platform.h>
24
25#include "dev.h"
26#include "camera/vi/mc_common.h"
27#include "vi/vi.h"
28#include "vi/vi4.h"
29#include "host1x/host1x.h"
30#include "camera/vi/registers.h"
31
32/* In TPG mode, VI only support 2 formats */
33static void vi_tpg_fmts_bitmap_init(struct tegra_channel *chan)
34{
35 int index;
36
37 bitmap_zero(chan->fmts_bitmap, MAX_FORMAT_NUM);
38
39 index = tegra_core_get_idx_by_code(chan,
40 MEDIA_BUS_FMT_SRGGB10_1X10, 0);
41 bitmap_set(chan->fmts_bitmap, index, 1);
42
43 index = tegra_core_get_idx_by_code(chan,
44 MEDIA_BUS_FMT_RGB888_1X32_PADHI, 0);
45 bitmap_set(chan->fmts_bitmap, index, 1);
46}
47
48/* -----------------------------------------------------------------------------
49 * Media Controller and V4L2
50 */
51
52static const char *const vi_pattern_strings[] = {
53 "Disabled",
54 "Black/White Direct Mode",
55 "Color Patch Mode",
56};
57
58static int vi_s_ctrl(struct v4l2_ctrl *ctrl)
59{
60 struct tegra_mc_vi *vi = container_of(ctrl->handler, struct tegra_mc_vi,
61 ctrl_handler);
62
63 switch (ctrl->id) {
64 case V4L2_CID_TEST_PATTERN:
65 /*
66 * TPG control is only avaiable to TPG driver,
67 * it can't be changed to 0 to disable TPG mode.
68 */
69 if (ctrl->val) {
70 dev_info(&vi->ndev->dev, "Set TPG mode to %d\n",
71 ctrl->val);
72 vi->pg_mode = ctrl->val;
73 }
74 break;
75 default:
76 dev_err(vi->dev, "%s:Not valid ctrl\n", __func__);
77 return -EINVAL;
78 }
79
80 return 0;
81}
82
83static const struct v4l2_ctrl_ops vi_ctrl_ops = {
84 .s_ctrl = vi_s_ctrl,
85};
86
87void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi)
88{
89 v4l2_ctrl_handler_free(&vi->ctrl_handler);
90 v4l2_device_unregister(&vi->v4l2_dev);
91 if (!vi->pg_mode)
92 media_device_unregister(&vi->media_dev);
93}
94EXPORT_SYMBOL(tegra_vi_v4l2_cleanup);
95
96static void tegra_vi_notify(struct v4l2_subdev *sd,
97 unsigned int notification, void *arg)
98{
99 struct tegra_mc_vi *vi = container_of(sd->v4l2_dev,
100 struct tegra_mc_vi, v4l2_dev);
101 unsigned i;
102 struct tegra_channel *chan;
103
104 if (notification != V4L2_DEVICE_NOTIFY_EVENT)
105 return;
106
107 list_for_each_entry(chan, &vi->vi_chans, list) {
108 for (i = 0; i < chan->num_subdevs; i++)
109 if (sd == chan->subdev[i])
110 v4l2_event_queue(&chan->video, arg);
111 }
112}
113
114int tegra_vi_v4l2_init(struct tegra_mc_vi *vi)
115{
116 int ret;
117
118 vi->media_dev.dev = vi->dev;
119 strlcpy(vi->media_dev.model, "NVIDIA Tegra Video Input Device",
120 sizeof(vi->media_dev.model));
121 vi->media_dev.hw_revision = 3;
122
123 ret = media_device_register(&vi->media_dev);
124 if (ret < 0) {
125 dev_err(vi->dev,
126 "media device registration failed (%d)\n",
127 ret);
128 return ret;
129 }
130
131 mutex_init(&vi->bw_update_lock);
132 vi->v4l2_dev.mdev = &vi->media_dev;
133 vi->v4l2_dev.notify = tegra_vi_notify;
134 ret = v4l2_device_register(vi->dev, &vi->v4l2_dev);
135 if (ret < 0) {
136 dev_err(vi->dev, "V4L2 device registration failed (%d)\n",
137 ret);
138 goto register_error;
139 }
140
141 return 0;
142
143register_error:
144 media_device_unregister(&vi->media_dev);
145 return ret;
146}
147
148static int vi_parse_dt(struct tegra_mc_vi *vi, struct platform_device *dev)
149{
150 int err = 0;
151 int num_channels = 0;
152 int i;
153 struct tegra_channel *item;
154 struct device_node *node = dev->dev.of_node;
155
156 err = of_property_read_u32(node, "num-channels", &num_channels);
157 if (err) {
158 dev_dbg(&dev->dev,
159 "Failed to find num of channels, set to 0\n");
160 num_channels = 0;
161 }
162 vi->num_channels = num_channels;
163 for (i = 0; i < num_channels; i++) {
164 item = devm_kzalloc(vi->dev, sizeof(*item), GFP_KERNEL);
165 if (!item)
166 return -ENOMEM;
167 item->id = i;
168 list_add_tail(&item->list, &vi->vi_chans);
169 }
170
171 return 0;
172}
173
174static void set_vi_register_base(struct tegra_mc_vi *mc_vi,
175 void __iomem *regbase)
176{
177 mc_vi->iomem = regbase;
178}
179int tpg_vi_media_controller_init(struct tegra_mc_vi *mc_vi, int pg_mode)
180{
181 int err = 0, i;
182 struct tegra_channel *item;
183 int count = 0;
184
185 /* Allocate TPG channel */
186 v4l2_ctrl_handler_init(&mc_vi->ctrl_handler, 1);
187 mc_vi->pattern = v4l2_ctrl_new_std_menu_items(&mc_vi->ctrl_handler,
188 &vi_ctrl_ops, V4L2_CID_TEST_PATTERN,
189 ARRAY_SIZE(vi_pattern_strings) - 1,
190 0, mc_vi->pg_mode, vi_pattern_strings);
191
192 if (mc_vi->ctrl_handler.error) {
193 dev_err(mc_vi->dev, "failed to add controls\n");
194 err = mc_vi->ctrl_handler.error;
195 goto ctrl_error;
196 }
197
198 mc_vi->tpg_start = NULL;
199 for (i = 0; i < TPG_CHANNELS; i++) {
200 item = devm_kzalloc(mc_vi->dev, sizeof(*item), GFP_KERNEL);
201 if (!item)
202 continue;
203 item->id = mc_vi->num_channels + i;
204 item->pg_mode = pg_mode;
205 item->vi = mc_vi;
206
207 err = tegra_channel_init(item);
208 if (err) {
209 devm_kfree(mc_vi->dev, item);
210 continue;
211 }
212 vi_tpg_fmts_bitmap_init(item);
213 /* only inited tpg channels are added */
214 list_add_tail(&item->list, &mc_vi->vi_chans);
215 mc_vi->num_channels++;
216 if (mc_vi->tpg_start == NULL)
217 mc_vi->tpg_start = item;
218 }
219
220 err = tegra_vi_tpg_graph_init(mc_vi);
221 if (err)
222 goto channel_init_error;
223
224 list_for_each_entry(item, &mc_vi->vi_chans, list) {
225 if (!item->pg_mode)
226 continue;
227 err = video_register_device(&item->video, VFL_TYPE_GRABBER, -1);
228 if (err < 0) {
229 dev_err(&item->video.dev, "failed to register %s\n",
230 item->video.name);
231 continue;
232 }
233 count++;
234 }
235
236 if (count == 0) {
237 dev_err(mc_vi->dev, "all tpg register failed\n");
238 goto channel_init_error;
239 }
240
241 return err;
242
243channel_init_error:
244 dev_err(mc_vi->dev, "%s: channel init failed\n", __func__);
245 if (!mc_vi->tpg_start)
246 tpg_vi_media_controller_cleanup(mc_vi);
247 return err;
248ctrl_error:
249 v4l2_ctrl_handler_free(&mc_vi->ctrl_handler);
250 dev_err(mc_vi->dev, "%s: v2l4_ctl error\n", __func__);
251 return err;
252}
253EXPORT_SYMBOL(tpg_vi_media_controller_init);
254
255void tpg_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi)
256{
257 struct tegra_channel *item;
258 struct tegra_channel *itemn;
259
260 list_for_each_entry_safe(item, itemn, &mc_vi->vi_chans, list) {
261 if (!item->pg_mode)
262 continue;
263 if (item->video.cdev != NULL)
264 video_unregister_device(&item->video);
265 tegra_channel_cleanup(item);
266 list_del(&item->list);
267 devm_kfree(mc_vi->dev, item);
268 /* decrement media device entity count */
269 mc_vi->media_dev.entity_id--;
270 mc_vi->num_channels--;
271 }
272 mc_vi->tpg_start = NULL;
273 v4l2_ctrl_handler_free(&mc_vi->ctrl_handler);
274}
275EXPORT_SYMBOL(tpg_vi_media_controller_cleanup);
276
277int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
278 struct platform_device *pdev)
279{
280 int err = 0;
281 struct nvhost_device_data *pdata = (struct nvhost_device_data *)
282 platform_get_drvdata(pdev);
283
284 if (!pdata)
285 return -EINVAL;
286 set_vi_register_base(mc_vi, pdata->aperture[0]);
287
288 mc_vi->ndev = pdev;
289 mc_vi->dev = &pdev->dev;
290 INIT_LIST_HEAD(&mc_vi->vi_chans);
291 INIT_LIST_HEAD(&mc_vi->entities);
292 mutex_init(&mc_vi->mipical_lock);
293
294 err = vi_parse_dt(mc_vi, pdev);
295 if (err)
296 goto mc_init_fail;
297
298 /*
299 * if there is no vi channels listed in DT,
300 * no need to init the channel and graph
301 */
302 if (mc_vi->num_channels == 0)
303 return 0;
304
305 err = tegra_vi_v4l2_init(mc_vi);
306 if (err < 0)
307 goto mc_init_fail;
308
309 /* Init Tegra VI channels */
310 err = tegra_vi_channels_init(mc_vi);
311 if (err < 0) {
312 dev_err(&pdev->dev, "Init channel failed\n");
313 goto channels_error;
314 }
315
316 /* Setup media links between VI and external sensor subdev. */
317 err = tegra_vi_graph_init(mc_vi);
318 if (err < 0)
319 goto graph_error;
320
321 err = tegra_vi_channels_register(mc_vi);
322 if (err < 0)
323 goto register_error;
324
325 return 0;
326
327register_error:
328 tegra_vi_graph_cleanup(mc_vi);
329graph_error:
330 tegra_vi_channels_cleanup(mc_vi);
331channels_error:
332 tegra_vi_v4l2_cleanup(mc_vi);
333mc_init_fail:
334 dev_err(&pdev->dev, "%s: failed\n", __func__);
335 return err;
336}
337EXPORT_SYMBOL(tegra_vi_media_controller_init);
338
339void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi)
340{
341 tegra_vi_channels_unregister(mc_vi);
342 tegra_vi_graph_cleanup(mc_vi);
343 tegra_vi_channels_cleanup(mc_vi);
344 tegra_vi_v4l2_cleanup(mc_vi);
345}
346EXPORT_SYMBOL(tegra_vi_media_controller_cleanup);
diff --git a/drivers/media/platform/tegra/camera/vi/mc_common.h b/drivers/media/platform/tegra/camera/vi/mc_common.h
new file mode 100644
index 000000000..42982bef8
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/mc_common.h
@@ -0,0 +1,352 @@
1/*
2 * drivers/media/platform/tegra/camera/mc_common.h
3 *
4 * Tegra Media controller common APIs
5 *
6 * Copyright (c) 2012-2017, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __CAMERA_MC_COMMON_H__
22#define __CAMERA_MC_COMMON_H__
23
24#include <media/media-device.h>
25#include <media/media-entity.h>
26#include <media/v4l2-async.h>
27#include <media/v4l2-ctrls.h>
28#include <media/v4l2-device.h>
29#include <media/v4l2-dev.h>
30#include <media/videobuf2-core.h>
31#include <linux/workqueue.h>
32
33#include "core.h"
34#include "../csi/csi.h"
35
36#define MAX_FORMAT_NUM 64
37#define MAX_SUBDEVICES 4
38#define QUEUED_BUFFERS 4
39#define ENABLE 1
40#define DISABLE 0
41#define MAX_SYNCPT_PER_CHANNEL 3
42#define TPG_CHANNELS 6
43
44#define TEGRA_MEM_FORMAT 0
45#define TEGRA_ISP_FORMAT 1
46
47enum channel_capture_state {
48 CAPTURE_IDLE = 0,
49 CAPTURE_GOOD,
50 CAPTURE_TIMEOUT,
51 CAPTURE_ERROR,
52};
53
54enum tegra_vi_pg_mode {
55 TEGRA_VI_PG_DISABLED = 0,
56 TEGRA_VI_PG_DIRECT,
57 TEGRA_VI_PG_PATCH,
58};
59
60/**
61 * struct tegra_channel_buffer - video channel buffer
62 * @buf: vb2 buffer base object
63 * @queue: buffer list entry in the channel queued buffers list
64 * @chan: channel that uses the buffer
65 * @addr: Tegra IOVA buffer address for VI output
66 */
67struct tegra_channel_buffer {
68 struct vb2_v4l2_buffer buf;
69 struct list_head queue;
70 struct tegra_channel *chan;
71
72 dma_addr_t addr;
73};
74
75#define to_tegra_channel_buffer(vb) \
76 container_of(vb, struct tegra_channel_buffer, buf)
77
78/**
79 * struct tegra_vi_graph_entity - Entity in the video graph
80 * @list: list entry in a graph entities list
81 * @node: the entity's DT node
82 * @entity: media entity, from the corresponding V4L2 subdev
83 * @asd: subdev asynchronous registration information
84 * @subdev: V4L2 subdev
85 */
86struct tegra_vi_graph_entity {
87 struct list_head list;
88 struct device_node *node;
89 struct media_entity *entity;
90
91 struct v4l2_async_subdev asd;
92 struct v4l2_subdev *subdev;
93};
94
95/**
96 * struct tegra_channel - Tegra video channel
97 * @list: list entry in a composite device dmas list
98 * @video: V4L2 video device associated with the video channel
99 * @video_lock:
100 * @pad: media pad for the video device entity
101 * @pipe: pipeline belonging to the channel
102 *
103 * @vi: composite device DT node port number for the channel
104 *
105 * @kthread_capture: kernel thread task structure of this video channel
106 * @wait: wait queue structure for kernel thread
107 *
108 * @format: active V4L2 pixel format
109 * @fmtinfo: format information corresponding to the active @format
110 *
111 * @queue: vb2 buffers queue
112 * @alloc_ctx: allocation context for the vb2 @queue
113 * @sequence: V4L2 buffers sequence number
114 *
115 * @capture: list of queued buffers for capture
116 * @queued_lock: protects the buf_queued list
117 *
118 * @csi: CSI register bases
119 * @stride_align: channel buffer stride alignment, default is 64
120 * @width_align: image width alignment, default is 4
121 * @height_align: channel buffer height alignment, default is 1
122 * @size_align: channel buffer size alignment, default is 128K bytes
123 * @port: CSI port of this video channel
124 * @io_id: Tegra IO rail ID of this video channel
125 *
126 * @fmts_bitmap: a bitmap for formats supported
127 * @bypass: bypass flag for VI bypass mode
128 */
129struct tegra_channel {
130 int id;
131 struct list_head list;
132 struct video_device video;
133 struct media_pad pad;
134 struct media_pipeline pipe;
135 struct mutex video_lock;
136
137 struct tegra_mc_vi *vi;
138 struct v4l2_subdev *subdev[MAX_SUBDEVICES];
139 struct v4l2_subdev *subdev_on_csi;
140
141 struct v4l2_ctrl_handler ctrl_handler;
142 struct v4l2_pix_format format;
143 const struct tegra_video_format *fmtinfo;
144 const struct tegra_video_format *video_formats[MAX_FORMAT_NUM];
145 unsigned int num_video_formats;
146 struct mutex stop_kthread_lock;
147
148 unsigned char port[TEGRA_CSI_BLOCKS];
149 unsigned int syncpt[TEGRA_CSI_BLOCKS][MAX_SYNCPT_PER_CHANNEL];
150 unsigned int syncpoint_fifo[TEGRA_CSI_BLOCKS];
151 unsigned int buffer_offset[TEGRA_CSI_BLOCKS];
152 unsigned int buffer_state[QUEUED_BUFFERS];
153 struct vb2_v4l2_buffer *buffers[QUEUED_BUFFERS];
154 unsigned int timeout;
155 unsigned int save_index;
156 unsigned int free_index;
157 unsigned int num_buffers;
158 unsigned int released_bufs;
159
160 struct task_struct *kthread_capture_start;
161 wait_queue_head_t start_wait;
162 struct vb2_queue queue;
163 void *alloc_ctx;
164 bool init_done;
165 struct list_head capture;
166 spinlock_t start_lock;
167 struct work_struct status_work;
168 struct work_struct error_work;
169
170 void __iomem *csibase[TEGRA_CSI_BLOCKS];
171 unsigned int stride_align;
172 unsigned int width_align;
173 unsigned int height_align;
174 unsigned int size_align;
175 unsigned int valid_ports;
176 unsigned int total_ports;
177 unsigned int numlanes;
178 unsigned int io_id;
179 unsigned int num_subdevs;
180 unsigned int sequence;
181 unsigned int saved_ctx_bypass;
182 unsigned int saved_ctx_pgmode;
183 unsigned int gang_mode;
184 unsigned int gang_width;
185 unsigned int gang_height;
186 unsigned int gang_bytesperline;
187 unsigned int gang_sizeimage;
188
189 DECLARE_BITMAP(fmts_bitmap, MAX_FORMAT_NUM);
190 atomic_t power_on_refcnt;
191 struct v4l2_fh *fh;
192 bool bypass;
193 bool write_ispformat;
194 enum tegra_vi_pg_mode pg_mode;
195 bool bfirst_fstart;
196 enum channel_capture_state capture_state;
197 spinlock_t capture_state_lock;
198 atomic_t is_streaming;
199 int requested_kbyteps;
200 unsigned long requested_hz;
201
202 struct vi_notify_channel *vnc[TEGRA_CSI_BLOCKS];
203 int vnc_id[TEGRA_CSI_BLOCKS];
204 int grp_id;
205
206 struct vi_capture *capture_data;
207};
208
209#define to_tegra_channel(vdev) \
210 container_of(vdev, struct tegra_channel, video)
211
212/**
213 * struct tegra_mc_vi - NVIDIA Tegra Media controller structure
214 * @v4l2_dev: V4L2 device
215 * @media_dev: media device
216 * @dev: device struct
217 * @tegra_camera: tegra camera structure
218 * @nvhost_device_data: NvHost VI device information
219 *
220 * @notifier: V4L2 asynchronous subdevs notifier
221 * @entities: entities in the graph as a list of tegra_vi_graph_entity
222 * @num_subdevs: number of subdevs in the pipeline
223 *
224 * @channels: list of channels at the pipeline output and input
225 *
226 * @ctrl_handler: V4L2 control handler
227 * @pattern: test pattern generator V4L2 control
228 * @pg_mode: test pattern generator mode (disabled/direct/patch)
229 *
230 * @has_sensors: a flag to indicate whether is a real sensor connecting
231 */
232struct tegra_mc_vi {
233 struct vi *vi;
234 struct platform_device *ndev;
235 struct v4l2_device v4l2_dev;
236 struct media_device media_dev;
237 struct device *dev;
238 struct nvhost_device_data *ndata;
239
240 struct regulator *reg;
241 struct clk *clk;
242 struct clk *parent_clk;
243
244 struct v4l2_async_notifier notifier;
245 struct list_head entities;
246 unsigned int num_channels;
247 unsigned int num_subdevs;
248
249 struct tegra_csi_device *csi;
250 struct list_head vi_chans;
251 struct tegra_channel *tpg_start;
252 void __iomem *iomem;
253
254 struct v4l2_ctrl_handler ctrl_handler;
255 struct v4l2_ctrl *pattern;
256 enum tegra_vi_pg_mode pg_mode;
257
258 bool has_sensors;
259 atomic_t power_on_refcnt;
260 unsigned int link_status;
261 unsigned int subdevs_bound;
262 struct mutex bw_update_lock;
263 unsigned long aggregated_kbyteps;
264 unsigned long max_requested_hz;
265 struct mutex mipical_lock;
266
267 bool bypass;
268
269 struct tegra_vi_fops *fops;
270};
271
272int tegra_vi_get_port_info(struct tegra_channel *chan,
273 struct device_node *node, unsigned int index);
274void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi);
275int tegra_vi_v4l2_init(struct tegra_mc_vi *vi);
276int tegra_vi_tpg_graph_init(struct tegra_mc_vi *vi);
277int tegra_vi_graph_init(struct tegra_mc_vi *vi);
278void tegra_vi_graph_cleanup(struct tegra_mc_vi *vi);
279int tegra_channel_init(struct tegra_channel *chan);
280int tegra_vi_channels_register(struct tegra_mc_vi *vi);
281void tegra_vi_channels_unregister(struct tegra_mc_vi *vi);
282int tegra_vi_channels_init(struct tegra_mc_vi *vi);
283int tegra_channel_cleanup(struct tegra_channel *chan);
284int tegra_vi_channels_cleanup(struct tegra_mc_vi *vi);
285int tegra_channel_init_subdevices(struct tegra_channel *chan);
286int tegra_vi2_power_on(struct tegra_mc_vi *vi);
287void tegra_vi2_power_off(struct tegra_mc_vi *vi);
288int tegra_vi4_power_on(struct tegra_mc_vi *vi);
289void tegra_vi4_power_off(struct tegra_mc_vi *vi);
290int tegra_clean_unlinked_channels(struct tegra_mc_vi *vi);
291int tegra_channel_s_ctrl(struct v4l2_ctrl *ctrl);
292int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
293 struct platform_device *pdev);
294void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi);
295void tegra_channel_ec_close(struct tegra_mc_vi *mc_vi);
296void tegra_channel_query_hdmiin_unplug(struct tegra_channel *chan,
297 struct v4l2_event *event);
298int tpg_vi_media_controller_init(struct tegra_mc_vi *mc_vi, int pg_mode);
299void tpg_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi);
300
301u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan,
302 unsigned int index);
303int tegra_core_get_idx_by_code(struct tegra_channel *chan,
304 unsigned int code, unsigned offset);
305const struct tegra_video_format *tegra_core_get_format_by_code(
306 struct tegra_channel *chan,
307 unsigned int code, unsigned offset);
308const struct tegra_video_format *tegra_core_get_format_by_fourcc(
309 struct tegra_channel *chan, u32 fourcc);
310void tegra_core_get_description_by_idx(struct tegra_channel *chan,
311 unsigned int index, __u8 *description);
312
313struct tegra_vi_fops {
314 int (*vi_power_on)(struct tegra_channel *chan);
315 void (*vi_power_off)(struct tegra_channel *chan);
316 int (*vi_start_streaming)(struct vb2_queue *vq, u32 count);
317 int (*vi_stop_streaming)(struct vb2_queue *vq);
318 int (*vi_add_ctrls)(struct tegra_channel *chan);
319 void (*vi_init_video_formats)(struct tegra_channel *chan);
320 long (*vi_default_ioctl)(struct file *file, void *fh,
321 bool use_prio, unsigned int cmd, void *arg);
322};
323
324struct tegra_csi_fops {
325 int (*csi_power_on)(struct tegra_csi_device *csi);
326 int (*csi_power_off)(struct tegra_csi_device *csi);
327 int (*csi_start_streaming)(struct tegra_csi_channel *chan,
328 enum tegra_csi_port_num port_num);
329 void (*csi_stop_streaming)(struct tegra_csi_channel *chan,
330 enum tegra_csi_port_num port_num);
331 void (*csi_override_format)(struct tegra_csi_channel *chan,
332 enum tegra_csi_port_num port_num);
333 int (*mipical)(struct tegra_csi_channel *chan);
334 int (*hw_init)(struct tegra_csi_device *csi);
335};
336
337struct tegra_t210_vi_data {
338 struct nvhost_device_data *info;
339 struct tegra_vi_fops *vi_fops;
340 struct tegra_csi_fops *csi_fops;
341};
342
343struct tegra_vi_data {
344 struct nvhost_device_data *info;
345 struct tegra_vi_fops *vi_fops;
346};
347
348struct tegra_csi_data {
349 struct nvhost_device_data *info;
350 struct tegra_csi_fops *csi_fops;
351};
352#endif
diff --git a/drivers/media/platform/tegra/camera/vi/registers.h b/drivers/media/platform/tegra/camera/vi/registers.h
new file mode 100644
index 000000000..176575dff
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/registers.h
@@ -0,0 +1,223 @@
1/*
2 * drivers/media/platform/tegra/camera/registers.h
3 *
4 * Tegra VI/CSI register offsets
5 *
6 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __REGISTERS_H__
22#define __REGISTERS_H__
23
24/* VI registers */
25#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT 200
26#define TEGRA_VI_CFG_VI_INCR_SYNCPT 0x000
27#define VI_CFG_VI_INCR_SYNCPT_COND(x) (x << 8)
28#define VI_CSI_PP_LINE_START(port) (4 + (port) * 4)
29#define VI_CSI_PP_FRAME_START(port) (5 + (port) * 4)
30#define VI_CSI_MW_REQ_DONE(port) (6 + (port) * 4)
31#define VI_CSI_MW_ACK_DONE(port) (7 + (port) * 4)
32
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 VI_CG_2ND_LEVEL_EN 0x1
58#define TEGRA_VI_CFG_VI_MCCIF_FIFOCTRL 0x0e4
59#define TEGRA_VI_CFG_TIMEOUT_WCOAL_VI 0x0e8
60#define TEGRA_VI_CFG_DVFS 0x0f0
61#define TEGRA_VI_CFG_RESERVE 0x0f4
62#define TEGRA_VI_CFG_RESERVE_1 0x0f8
63
64/* CSI registers */
65#define TEGRA_VI_CSI_BASE(x) (0x100 + (x) * 0x100)
66
67#define TEGRA_VI_CSI_SW_RESET 0x000
68#define TEGRA_VI_CSI_SINGLE_SHOT 0x004
69#define SINGLE_SHOT_CAPTURE 0x1
70#define CAPTURE_GOOD_FRAME 0x1
71#define TEGRA_VI_CSI_SINGLE_SHOT_STATE_UPDATE 0x008
72#define TEGRA_VI_CSI_IMAGE_DEF 0x00c
73#define BYPASS_PXL_TRANSFORM_OFFSET 24
74#define IMAGE_DEF_FORMAT_OFFSET 16
75#define IMAGE_DEF_DEST_MEM 0x1
76#define TEGRA_VI_CSI_RGB2Y_CTRL 0x010
77#define TEGRA_VI_CSI_MEM_TILING 0x014
78#define TEGRA_VI_CSI_IMAGE_SIZE 0x018
79#define IMAGE_SIZE_HEIGHT_OFFSET 16
80#define TEGRA_VI_CSI_IMAGE_SIZE_WC 0x01c
81#define TEGRA_VI_CSI_IMAGE_DT 0x020
82#define TEGRA_VI_CSI_SURFACE0_OFFSET_MSB 0x024
83#define TEGRA_VI_CSI_SURFACE0_OFFSET_LSB 0x028
84#define TEGRA_VI_CSI_SURFACE1_OFFSET_MSB 0x02c
85#define TEGRA_VI_CSI_SURFACE1_OFFSET_LSB 0x030
86#define TEGRA_VI_CSI_SURFACE2_OFFSET_MSB 0x034
87#define TEGRA_VI_CSI_SURFACE2_OFFSET_LSB 0x038
88#define TEGRA_VI_CSI_SURFACE0_BF_OFFSET_MSB 0x03c
89#define TEGRA_VI_CSI_SURFACE0_BF_OFFSET_LSB 0x040
90#define TEGRA_VI_CSI_SURFACE1_BF_OFFSET_MSB 0x044
91#define TEGRA_VI_CSI_SURFACE1_BF_OFFSET_LSB 0x048
92#define TEGRA_VI_CSI_SURFACE2_BF_OFFSET_MSB 0x04c
93#define TEGRA_VI_CSI_SURFACE2_BF_OFFSET_LSB 0x050
94#define TEGRA_VI_CSI_SURFACE0_STRIDE 0x054
95#define TEGRA_VI_CSI_SURFACE1_STRIDE 0x058
96#define TEGRA_VI_CSI_SURFACE2_STRIDE 0x05c
97#define TEGRA_VI_CSI_SURFACE_HEIGHT0 0x060
98#define TEGRA_VI_CSI_ISPINTF_CONFIG 0x064
99#define TEGRA_VI_CSI_ERROR_STATUS 0x084
100#define TEGRA_VI_CSI_ERROR_INT_MASK 0x088
101#define TEGRA_VI_CSI_WD_CTRL 0x08c
102#define TEGRA_VI_CSI_WD_PERIOD 0x090
103
104/* CSI Pixel Parser registers: Starts from 0x838, offset 0x0 */
105#define TEGRA_CSI_INPUT_STREAM_CONTROL 0x000
106#define CSI_SKIP_PACKET_THRESHOLD_OFFSET 16
107
108#define TEGRA_CSI_PIXEL_STREAM_CONTROL0 0x004
109#define CSI_PP_PACKET_HEADER_SENT (0x1 << 4)
110#define CSI_PP_DATA_IDENTIFIER_ENABLE (0x1 << 5)
111#define CSI_PP_WORD_COUNT_SELECT_HEADER (0x1 << 6)
112#define CSI_PP_CRC_CHECK_ENABLE (0x1 << 7)
113#define CSI_PP_WC_CHECK (0x1 << 8)
114#define CSI_PP_OUTPUT_FORMAT_STORE (0x3 << 16)
115#define CSI_PPA_PAD_LINE_NOPAD (0x2 << 24)
116#define CSI_PP_HEADER_EC_DISABLE (0x1 << 27)
117#define CSI_PPA_PAD_FRAME_NOPAD (0x2 << 28)
118
119#define TEGRA_CSI_PIXEL_STREAM_CONTROL1 0x008
120#define CSI_PP_TOP_FIELD_FRAME_OFFSET 0
121#define CSI_PP_TOP_FIELD_FRAME_MASK_OFFSET 4
122
123#define TEGRA_CSI_PIXEL_STREAM_GAP 0x00c
124#define PP_FRAME_MIN_GAP_OFFSET 16
125
126#define TEGRA_CSI_PIXEL_STREAM_PP_COMMAND 0x010
127#define CSI_PP_ENABLE 0x1
128#define CSI_PP_DISABLE 0x2
129#define CSI_PP_RST 0x3
130#define CSI_PP_SINGLE_SHOT_ENABLE (0x1 << 2)
131#define CSI_PP_START_MARKER_FRAME_MAX_OFFSET 12
132
133#define TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME 0x014
134#define TEGRA_CSI_PIXEL_PARSER_INTERRUPT_MASK 0x018
135#define TEGRA_CSI_PIXEL_PARSER_STATUS 0x01c
136#define TEGRA_CSI_CSI_SW_SENSOR_RESET 0x020
137
138/* CSI PHY registers */
139/* CSI_PHY_CIL_COMMAND_0 offset 0x0d0 from TEGRA_CSI_PIXEL_PARSER_0_BASE */
140#define TEGRA_CSI_PHY_CIL_COMMAND 0x0d0
141#define CSI_A_PHY_CIL_ENABLE 0x1
142#define CSI_B_PHY_CIL_ENABLE (0x1 << 8)
143
144/* CSI CIL registers: Starts from 0x92c, offset 0xF4 */
145#define TEGRA_CSI_CIL_OFFSET 0x0f4
146
147#define TEGRA_CSI_CIL_PAD_CONFIG0 0x000
148#define BRICK_CLOCK_A_4X (0x1 << 16)
149#define BRICK_CLOCK_B_4X (0x2 << 16)
150#define TEGRA_CSI_CIL_PAD_CONFIG1 0x004
151#define TEGRA_CSI_CIL_PHY_CONTROL 0x008
152#define BYPASS_LP_SEQ (0x1 << 6)
153#define TEGRA_CSI_CIL_INTERRUPT_MASK 0x00c
154#define TEGRA_CSI_CIL_STATUS 0x010
155#define TEGRA_CSI_CILX_STATUS 0x014
156#define TEGRA_CSI_CIL_ESCAPE_MODE_COMMAND 0x018
157#define TEGRA_CSI_CIL_ESCAPE_MODE_DATA 0x01c
158#define TEGRA_CSI_CIL_SW_SENSOR_RESET 0x020
159
160/* CSI Pattern Generator registers: Starts from 0x9c4, offset 0x18c */
161#define TEGRA_CSI_TPG_OFFSET 0x18c
162
163#define TEGRA_CSI_PATTERN_GENERATOR_CTRL 0x000
164#define PG_MODE_OFFSET 2
165#define PG_ENABLE 0x1
166#define PG_DISABLE 0x0
167
168#define PG_VBLANK_OFFSET 16
169#define TEGRA_CSI_PG_BLANK 0x004
170#define TEGRA_CSI_PG_PHASE 0x008
171#define TEGRA_CSI_PG_RED_FREQ 0x00c
172#define PG_RED_VERT_INIT_FREQ_OFFSET 16
173#define PG_RED_HOR_INIT_FREQ_OFFSET 0
174
175#define TEGRA_CSI_PG_RED_FREQ_RATE 0x010
176#define TEGRA_CSI_PG_GREEN_FREQ 0x014
177#define PG_GREEN_VERT_INIT_FREQ_OFFSET 16
178#define PG_GREEN_HOR_INIT_FREQ_OFFSET 0
179
180#define TEGRA_CSI_PG_GREEN_FREQ_RATE 0x018
181#define TEGRA_CSI_PG_BLUE_FREQ 0x01c
182#define PG_BLUE_VERT_INIT_FREQ_OFFSET 16
183#define PG_BLUE_HOR_INIT_FREQ_OFFSET 0
184
185#define TEGRA_CSI_PG_BLUE_FREQ_RATE 0x020
186#define TEGRA_CSI_PG_AOHDR 0x024
187
188#define TEGRA_CSI_DPCM_CTRL_A 0xa2c
189#define TEGRA_CSI_DPCM_CTRL_B 0xa30
190
191/* Other CSI registers: Starts from 0xa44, offset 0x20c */
192#define TEGRA_CSI_STALL_COUNTER 0x20c
193#define TEGRA_CSI_CSI_READONLY_STATUS 0x210
194#define TEGRA_CSI_CSI_SW_STATUS_RESET 0x214
195#define TEGRA_CSI_CLKEN_OVERRIDE 0x218
196#define TEGRA_CSI_DEBUG_CONTROL 0x21c
197#define TEGRA_CSI_DEBUG_COUNTER_0 0x220
198#define TEGRA_CSI_DEBUG_COUNTER_1 0x224
199#define TEGRA_CSI_DEBUG_COUNTER_2 0x228
200
201
202/* CSI Pixel Parser registers */
203#define TEGRA_CSI_PIXEL_PARSER_0_BASE 0x0838
204#define TEGRA_CSI_PIXEL_PARSER_1_BASE 0x086c
205#define TEGRA_CSI_PIXEL_PARSER_2_BASE 0x1038
206#define TEGRA_CSI_PIXEL_PARSER_3_BASE 0x106c
207#define TEGRA_CSI_PIXEL_PARSER_4_BASE 0x1838
208#define TEGRA_CSI_PIXEL_PARSER_5_BASE 0x186c
209
210/* CSIA to CSIB register offset */
211#define TEGRA_CSI_PORT_OFFSET 0x34
212
213#define INVALID_CSI_PORT 0xFF
214#define TEGRA_CSI_BLOCKS 3
215#define SYNCPT_FIFO_DEPTH 2
216#define PREVIOUS_BUFFER_DEC_INDEX 2
217
218#define TEGRA_CLOCK_VI_MAX 793600000
219#define TEGRA_CLOCK_TPG 927000000
220#define TEGRA_CLOCK_CSI_PORT_MAX 102000000
221
222#define TEGRA_SURFACE_ALIGNMENT 64
223#endif
diff --git a/drivers/media/platform/tegra/camera/vi/vi2_fops.c b/drivers/media/platform/tegra/camera/vi/vi2_fops.c
new file mode 100644
index 000000000..fa081b9e0
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi2_fops.c
@@ -0,0 +1,825 @@
1/*
2 * Tegra Video Input 2 device common APIs
3 *
4 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bryan Wu <pengw@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/device.h>
13#include <linux/nvhost.h>
14#include <linux/tegra-powergate.h>
15#include <linux/kthread.h>
16#include <linux/freezer.h>
17#include <media/tegra_camera_platform.h>
18#include "nvhost_acm.h"
19#include "camera/vi/mc_common.h"
20#include "camera/csi/csi2_fops.h"
21#include "vi2_formats.h"
22#include "vi/vi.h"
23
24#define DEFAULT_FRAMERATE 30
25#define DEFAULT_CSI_FREQ 204000000
26#define BPP_MEM 2
27#define NUM_PPC 2
28#define VI_CSI_CLK_SCALE 110
29
30extern void tegra_channel_queued_buf_done(struct tegra_channel *chan,
31 enum vb2_buffer_state state);
32static void tegra_channel_stop_kthreads(struct tegra_channel *chan);
33extern int tegra_channel_set_stream(struct tegra_channel *chan, bool on);
34extern void tegra_channel_ring_buffer(struct tegra_channel *chan,
35 struct vb2_v4l2_buffer *vb,
36 struct timespec *ts, int state);
37extern struct tegra_channel_buffer *dequeue_buffer(struct tegra_channel *chan);
38extern void tegra_channel_init_ring_buffer(struct tegra_channel *chan);
39extern void free_ring_buffers(struct tegra_channel *chan, int frames);
40extern int tegra_channel_set_power(struct tegra_channel *chan, bool on);
41
42static void vi_write(struct tegra_mc_vi *vi, unsigned int addr, u32 val)
43{
44 writel(val, vi->iomem + addr);
45}
46
47static u32 tegra_channel_read(struct tegra_channel *chan,
48 unsigned int addr)
49{
50 return readl(chan->vi->iomem + addr);
51}
52
53static void tegra_channel_write(struct tegra_channel *chan,
54 unsigned int addr, u32 val)
55{
56 writel(val, chan->vi->iomem + addr);
57}
58
59/* CSI registers */
60static void csi_write(struct tegra_channel *chan, unsigned int index,
61 unsigned int addr, u32 val)
62{
63 writel(val, chan->csibase[index] + addr);
64}
65
66static u32 csi_read(struct tegra_channel *chan, unsigned int index,
67 unsigned int addr)
68{
69 return readl(chan->csibase[index] + addr);
70}
71
72static void vi_channel_syncpt_init(struct tegra_channel *chan)
73{
74 int i;
75
76 for (i = 0; i < chan->total_ports; i++)
77 chan->syncpt[i][0] =
78 nvhost_get_syncpt_client_managed(chan->vi->ndev, "vi");
79}
80
81static void vi_channel_syncpt_free(struct tegra_channel *chan)
82{
83 int i;
84
85 for (i = 0; i < chan->total_ports; i++)
86 nvhost_syncpt_put_ref_ext(chan->vi->ndev, chan->syncpt[i][0]);
87}
88
89void vi2_init_video_formats(struct tegra_channel *chan)
90{
91 int i;
92
93 chan->num_video_formats = ARRAY_SIZE(vi2_video_formats);
94 for (i = 0; i < chan->num_video_formats; i++)
95 chan->video_formats[i] = &vi2_video_formats[i];
96}
97
98int tegra_vi2_s_ctrl(struct v4l2_ctrl *ctrl)
99{
100 struct tegra_channel *chan = container_of(ctrl->handler,
101 struct tegra_channel, ctrl_handler);
102 int err = 0;
103
104 switch (ctrl->id) {
105 case V4L2_CID_WRITE_ISPFORMAT:
106 chan->write_ispformat = ctrl->val;
107 break;
108 default:
109 dev_err(&chan->video.dev, "%s:Not valid ctrl\n", __func__);
110 return -EINVAL;
111 }
112
113 return err;
114}
115
116static const struct v4l2_ctrl_ops vi2_ctrl_ops = {
117 .s_ctrl = tegra_vi2_s_ctrl,
118};
119
120static const struct v4l2_ctrl_config vi2_custom_ctrls[] = {
121 {
122 .ops = &vi2_ctrl_ops,
123 .id = V4L2_CID_WRITE_ISPFORMAT,
124 .name = "Write ISP format",
125 .type = V4L2_CTRL_TYPE_BOOLEAN,
126 .def = 0,
127 .min = 0,
128 .step = 1,
129 .max = 1,
130 },
131};
132
133int vi2_add_ctrls(struct tegra_channel *chan)
134{
135 int i;
136
137 /* Add vi2 custom controls */
138 for (i = 0; i < ARRAY_SIZE(vi2_custom_ctrls); i++) {
139 v4l2_ctrl_new_custom(&chan->ctrl_handler,
140 &vi2_custom_ctrls[i], NULL);
141 if (chan->ctrl_handler.error) {
142 dev_err(chan->vi->dev,
143 "Failed to add %s ctrl\n",
144 vi2_custom_ctrls[i].name);
145 return chan->ctrl_handler.error;
146 }
147 }
148
149 return 0;
150}
151
152static struct tegra_csi_channel *find_linked_csi_channel(
153 struct tegra_channel *chan, struct tegra_csi_device *csi)
154{
155 struct tegra_csi_channel *csi_it;
156 struct tegra_csi_channel *csi_chan = NULL;
157 int i;
158 /* Find connected csi_channel */
159 list_for_each_entry(csi_it, &csi->csi_chans, list) {
160 for (i = 0; i < chan->num_subdevs; i++) {
161 if (chan->subdev[i] == &csi_it->subdev) {
162 csi_chan = csi_it;
163 break;
164 }
165 }
166 }
167 return csi_chan;
168}
169static int tegra_channel_capture_setup(struct tegra_channel *chan)
170{
171 u32 height = chan->format.height;
172 u32 width = chan->format.width;
173 u32 format = chan->fmtinfo->img_fmt;
174 u32 data_type = chan->fmtinfo->img_dt;
175 u32 word_count = tegra_core_get_word_count(width, chan->fmtinfo);
176 u32 bypass_pixel_transform = 1;
177 int index;
178
179 if (chan->valid_ports > 1) {
180 height = chan->gang_height;
181 width = chan->gang_width;
182 word_count = tegra_core_get_word_count(width, chan->fmtinfo);
183 }
184
185 if (chan->pg_mode ||
186 (chan->write_ispformat == TEGRA_ISP_FORMAT) ||
187 (chan->fmtinfo->vf_code == TEGRA_VF_YUV422) ||
188 (chan->fmtinfo->vf_code == TEGRA_VF_RGB888))
189 bypass_pixel_transform = 0;
190
191 for (index = 0; index < chan->valid_ports; index++) {
192 csi_write(chan, index, TEGRA_VI_CSI_ERROR_STATUS, 0xFFFFFFFF);
193 csi_write(chan, index, TEGRA_VI_CSI_IMAGE_DEF,
194 (bypass_pixel_transform << BYPASS_PXL_TRANSFORM_OFFSET) |
195 (format << IMAGE_DEF_FORMAT_OFFSET));
196 csi_write(chan, index, TEGRA_VI_CSI_IMAGE_DT, data_type);
197 csi_write(chan, index, TEGRA_VI_CSI_IMAGE_SIZE_WC, word_count);
198 csi_write(chan, index, TEGRA_VI_CSI_IMAGE_SIZE,
199 (height << IMAGE_SIZE_HEIGHT_OFFSET) | width);
200 }
201
202 return 0;
203}
204
205static int tegra_channel_enable_stream(struct tegra_channel *chan)
206{
207 int ret = 0;
208 struct tegra_csi_channel *csi_chan = NULL;
209 struct tegra_csi_device *csi = chan->vi->csi;
210 /*
211 * enable pad power and perform calibration before arming
212 * single shot for first frame after the HW setup is complete
213 */
214 /* Find connected csi_channel */
215 csi_chan = find_linked_csi_channel(chan, csi);
216
217 /* start streaming */
218 ret = tegra_channel_set_stream(chan, true);
219 return ret;
220}
221
222static void tegra_channel_ec_init(struct tegra_channel *chan)
223{
224 /*
225 * error recover initialization sequence
226 * set timeout as 200 ms, use default if fps not available
227 * Time limit allow CSI to capture good frames and drop error frames
228 * Timeout units is jiffies, 1 jiffy = 10ms
229 * TODO: Get frame rate from sub-device and adopt timeout
230 */
231 chan->timeout = 20;
232
233 /*
234 * Sync point FIFO full blocks host interface
235 * Below setting enables SW to process error recovery
236 */
237 tegra_channel_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT_CNTRL, 0x100);
238}
239
240
241static void tegra_channel_clear_singleshot(struct tegra_channel *chan,
242 int index)
243{
244 /* clear single shot */
245 csi_write(chan, index, TEGRA_VI_CSI_SW_RESET, 0xF);
246 csi_write(chan, index, TEGRA_VI_CSI_SW_RESET, 0x0);
247}
248
249static void tegra_channel_vi_csi_recover(struct tegra_channel *chan)
250{
251 u32 error_val = tegra_channel_read(chan,
252 TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR);
253 u32 frame_start;
254 int index, valid_ports = chan->valid_ports;
255 struct tegra_csi_channel *csi_chan;
256 struct tegra_csi_device *csi = chan->vi->csi;
257
258 /* Disable clock gating to enable continuous clock */
259 tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, DISABLE);
260 /* Find connected csi_channel */
261 csi_chan = find_linked_csi_channel(chan, csi);
262
263 /* clear CSI state */
264 for (index = 0; index < valid_ports; index++) {
265 tegra_csi_error_recover(csi_chan, index);
266 csi_write(chan, index,
267 TEGRA_VI_CSI_IMAGE_DEF, 0);
268 tegra_channel_clear_singleshot(chan, index);
269 }
270
271 /* clear VI errors */
272 for (index = 0; index < valid_ports; index++) {
273 frame_start = VI_CSI_PP_FRAME_START(chan->port[index]);
274 if (error_val & frame_start)
275 chan->syncpoint_fifo[index] = SYNCPT_FIFO_DEPTH;
276 }
277 /* clear FIFO error status */
278 tegra_channel_write(chan,
279 TEGRA_VI_CFG_VI_INCR_SYNCPT_ERROR, error_val);
280
281 /* Enable clock gating so VI can be clock gated if necessary */
282 tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, ENABLE);
283
284 /* re-init VI and CSI */
285 tegra_channel_capture_setup(chan);
286 for (index = 0; index < valid_ports; index++) {
287 csi2_stop_streaming(csi_chan, index);
288 csi2_start_streaming(csi_chan, index);
289 nvhost_syncpt_set_min_eq_max_ext(chan->vi->ndev,
290 chan->syncpt[index][0]);
291 }
292}
293
294static void tegra_channel_capture_error(struct tegra_channel *chan)
295{
296 u32 val;
297 int index = 0;
298 struct tegra_csi_channel *csi_chan;
299 struct tegra_csi_device *csi = chan->vi->csi;
300
301 /* Find connected csi_channel */
302 csi_chan = find_linked_csi_channel(chan, csi);
303
304 for (index = 0; index < chan->valid_ports; index++) {
305 val = csi_read(chan, index, TEGRA_VI_CSI_ERROR_STATUS);
306 dev_dbg(&chan->video.dev,
307 "TEGRA_VI_CSI_ERROR_STATUS 0x%08x\n", val);
308 tegra_csi_status(csi_chan, index);
309 }
310}
311
312static void tegra_channel_ec_recover(struct tegra_channel *chan)
313{
314 tegra_channel_capture_error(chan);
315 tegra_channel_vi_csi_recover(chan);
316}
317
318static int tegra_channel_error_status(struct tegra_channel *chan)
319{
320 u32 val;
321 int err = 0;
322 int index = 0;
323 struct tegra_csi_channel *csi_chan;
324 struct tegra_csi_device *csi = chan->vi->csi;
325
326 /* Find connected csi_channel */
327 csi_chan = find_linked_csi_channel(chan, csi);
328
329 for (index = 0; index < chan->valid_ports; index++) {
330 /* Ignore error based on resolution but reset status */
331 val = csi_read(chan, index, TEGRA_VI_CSI_ERROR_STATUS);
332 csi_write(chan, index, TEGRA_VI_CSI_ERROR_STATUS, val);
333 err = tegra_csi_error(csi_chan, index);
334 }
335
336 if (err)
337 dev_err(chan->vi->dev, "%s:error %x frame %d\n",
338 __func__, err, chan->sequence);
339 return err;
340}
341
342static int tegra_channel_capture_frame(struct tegra_channel *chan,
343 struct tegra_channel_buffer *buf)
344{
345 struct vb2_v4l2_buffer *vb = &buf->buf;
346 struct timespec ts;
347 int err = 0;
348 u32 val, frame_start;
349 int bytes_per_line = chan->format.bytesperline;
350 int index = 0;
351 u32 thresh[TEGRA_CSI_BLOCKS] = { 0 };
352 int valid_ports = chan->valid_ports;
353 int state = VB2_BUF_STATE_DONE;
354
355 /* Init registers related to each frames */
356 for (index = 0; index < valid_ports; index++) {
357 /* Program buffer address by using surface 0 */
358 csi_write(chan, index, TEGRA_VI_CSI_SURFACE0_OFFSET_MSB, 0x0);
359 csi_write(chan, index, TEGRA_VI_CSI_SURFACE0_OFFSET_LSB,
360 (buf->addr + chan->buffer_offset[index]));
361 csi_write(chan, index,
362 TEGRA_VI_CSI_SURFACE0_STRIDE, bytes_per_line);
363
364 /* Program syncpoints */
365 thresh[index] = nvhost_syncpt_incr_max_ext(chan->vi->ndev,
366 chan->syncpt[index][0], 1);
367 /* Do not arm sync points if FIFO had entries before */
368 if (!chan->syncpoint_fifo[index]) {
369 frame_start = VI_CSI_PP_FRAME_START(chan->port[index]);
370 val = VI_CFG_VI_INCR_SYNCPT_COND(frame_start) |
371 chan->syncpt[index][0];
372 tegra_channel_write(chan,
373 TEGRA_VI_CFG_VI_INCR_SYNCPT, val);
374 } else
375 chan->syncpoint_fifo[index]--;
376 }
377
378 /* enable input stream once the VI registers are configured */
379 if (!chan->bfirst_fstart) {
380 err = tegra_channel_enable_stream(chan);
381 if (err) {
382 state = VB2_BUF_STATE_ERROR;
383 chan->capture_state = CAPTURE_ERROR;
384 tegra_channel_ring_buffer(chan, vb, &ts, state);
385 return err;
386 }
387 /* Bit controls VI memory write, enable after all regs */
388 for (index = 0; index < valid_ports; index++) {
389 val = csi_read(chan, index,
390 TEGRA_VI_CSI_IMAGE_DEF);
391 csi_write(chan, index, TEGRA_VI_CSI_IMAGE_DEF,
392 val | IMAGE_DEF_DEST_MEM);
393 }
394 }
395
396 /* Ensure all CSI ports are ready with setup to avoid timing issue */
397 for (index = 0; index < valid_ports; index++)
398 csi_write(chan, index,
399 TEGRA_VI_CSI_SINGLE_SHOT, SINGLE_SHOT_CAPTURE);
400
401 chan->capture_state = CAPTURE_GOOD;
402 for (index = 0; index < valid_ports; index++) {
403 err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
404 chan->syncpt[index][0], thresh[index],
405 chan->timeout, NULL, &ts);
406 if (err) {
407 dev_err(&chan->video.dev,
408 "frame start syncpt timeout!%d\n", index);
409 state = VB2_BUF_STATE_ERROR;
410 /* perform error recovery for timeout */
411 tegra_channel_ec_recover(chan);
412 chan->capture_state = CAPTURE_TIMEOUT;
413 break;
414 }
415 }
416
417 if (!err && !chan->pg_mode) {
418 /* Marking error frames and resume capture */
419 /* TODO: TPG has frame height short error always set */
420 err = tegra_channel_error_status(chan);
421 if (err) {
422 state = VB2_BUF_STATE_ERROR;
423 chan->capture_state = CAPTURE_ERROR;
424 /* do we have to run recover here ?? */
425 /* tegra_channel_ec_recover(chan); */
426 }
427 }
428
429 tegra_channel_ring_buffer(chan, vb, &ts, state);
430
431 return 0;
432}
433
434static void tegra_channel_capture_done(struct tegra_channel *chan)
435{
436 struct timespec ts;
437 int index, err;
438 int bytes_per_line = chan->format.bytesperline;
439 u32 val, mw_ack_done;
440 u32 thresh[TEGRA_CSI_BLOCKS] = { 0 };
441 struct tegra_channel_buffer *buf;
442 int state = VB2_BUF_STATE_DONE;
443
444 /* dequeue buffer and return if no buffer exists */
445 buf = dequeue_buffer(chan);
446 if (!buf)
447 return;
448
449 for (index = 0; index < chan->valid_ports; index++) {
450 /* Program buffer address by using surface 0 */
451 csi_write(chan, index, TEGRA_VI_CSI_SURFACE0_OFFSET_MSB, 0x0);
452 csi_write(chan, index, TEGRA_VI_CSI_SURFACE0_OFFSET_LSB,
453 (buf->addr + chan->buffer_offset[index]));
454 csi_write(chan, index,
455 TEGRA_VI_CSI_SURFACE0_STRIDE, bytes_per_line);
456
457 /* Program syncpoints */
458 thresh[index] = nvhost_syncpt_incr_max_ext(chan->vi->ndev,
459 chan->syncpt[index][0], 1);
460 mw_ack_done = VI_CSI_MW_ACK_DONE(chan->port[index]);
461 val = VI_CFG_VI_INCR_SYNCPT_COND(mw_ack_done) |
462 chan->syncpt[index][0];
463 tegra_channel_write(chan, TEGRA_VI_CFG_VI_INCR_SYNCPT, val);
464 csi_write(chan, index,
465 TEGRA_VI_CSI_SINGLE_SHOT, SINGLE_SHOT_CAPTURE);
466 }
467
468 for (index = 0; index < chan->valid_ports; index++) {
469 err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
470 chan->syncpt[index][0], thresh[index],
471 chan->timeout, NULL, &ts);
472 if (err) {
473 dev_err(&chan->video.dev,
474 "MW_ACK_DONE syncpoint time out!%d\n", index);
475 state = VB2_BUF_STATE_ERROR;
476 /* perform error recovery for timeout */
477 tegra_channel_ec_recover(chan);
478 chan->capture_state = CAPTURE_TIMEOUT;
479 break;
480 }
481 }
482
483 /* Mark capture state to IDLE as capture is finished */
484 chan->capture_state = CAPTURE_IDLE;
485
486 tegra_channel_ring_buffer(chan, &buf->buf, &ts, state);
487}
488
489static int tegra_channel_kthread_capture_start(void *data)
490{
491 struct tegra_channel *chan = data;
492 struct tegra_channel_buffer *buf;
493 int err = 0;
494
495 set_freezable();
496
497 while (1) {
498
499 try_to_freeze();
500
501 wait_event_interruptible(chan->start_wait,
502 !list_empty(&chan->capture) ||
503 kthread_should_stop());
504
505 if (kthread_should_stop())
506 break;
507
508 /* source is not streaming if error is non-zero */
509 /* wait till kthread stop and dont DeQ buffers */
510 if (err)
511 continue;
512
513 buf = dequeue_buffer(chan);
514 if (!buf)
515 continue;
516
517 err = tegra_channel_capture_frame(chan, buf);
518 }
519
520 return 0;
521}
522
523static void tegra_channel_stop_kthreads(struct tegra_channel *chan)
524{
525 mutex_lock(&chan->stop_kthread_lock);
526 /* Stop the kthread for capture */
527 if (chan->kthread_capture_start) {
528 kthread_stop(chan->kthread_capture_start);
529 chan->kthread_capture_start = NULL;
530 }
531 mutex_unlock(&chan->stop_kthread_lock);
532}
533
534static int tegra_channel_update_clknbw(
535 struct tegra_channel *chan, u8 on) __maybe_unused;
536static int tegra_channel_update_clknbw(struct tegra_channel *chan, u8 on)
537{
538 int ret = 0;
539 unsigned long request_pixelrate;
540 struct v4l2_subdev_frame_interval fie;
541 unsigned long csi_freq = 0;
542
543 fie.interval.denominator = DEFAULT_FRAMERATE;
544 fie.interval.numerator = 1;
545
546 if (v4l2_subdev_has_op(chan->subdev_on_csi,
547 video, g_frame_interval))
548 v4l2_subdev_call(chan->subdev_on_csi, video,
549 g_frame_interval, &fie);
550 if (on) {
551 /**
552 * TODO: use real sensor pixelrate
553 * See PowerService code
554 */
555 request_pixelrate = (long long)(chan->format.width
556 * chan->format.height
557 * fie.interval.denominator / 100)
558 * VI_CSI_CLK_SCALE;
559 /* for PG, get csi frequency from nvhost */
560 if (chan->pg_mode) {
561 ret = nvhost_module_get_rate(
562 chan->vi->csi->pdev, &csi_freq, 0);
563 csi_freq = ret ? DEFAULT_CSI_FREQ : csi_freq;
564 } else
565 /* Use default csi4 frequency for t186 for now
566 * We can't get the frequency from nvhost because
567 * vi4 does not has access to csi4
568 */
569 csi_freq = DEFAULT_CSI_FREQ;
570
571 /* VI clk should be slightly faster than CSI clk*/
572 ret = nvhost_module_set_rate(chan->vi->ndev, &chan->video,
573 max(request_pixelrate,
574 csi_freq * VI_CSI_CLK_SCALE * NUM_PPC / 100),
575 0, NVHOST_PIXELRATE);
576 if (ret) {
577 dev_err(chan->vi->dev, "Fail to update vi clk\n");
578 return ret;
579 }
580 } else {
581 ret = nvhost_module_set_rate(chan->vi->ndev, &chan->video, 0, 0,
582 NVHOST_PIXELRATE);
583 if (ret) {
584 dev_err(chan->vi->dev, "Fail to update vi clk\n");
585 return ret;
586 }
587 }
588
589 chan->requested_kbyteps = (on > 0 ? 1 : -1) *
590 ((long long)(chan->format.width * chan->format.height
591 * fie.interval.denominator * BPP_MEM) * 115 / 100) / 1000;
592
593 mutex_lock(&chan->vi->bw_update_lock);
594 chan->vi->aggregated_kbyteps += chan->requested_kbyteps;
595 ret = vi_v4l2_update_isobw(chan->vi->aggregated_kbyteps, 0);
596 mutex_unlock(&chan->vi->bw_update_lock);
597 if (ret)
598 dev_info(chan->vi->dev,
599 "WAR:Calculation not precise.Ignore BW request failure\n");
600#if 0
601 ret = vi4_v4l2_set_la(chan->vi->ndev, 0, 0);
602 if (ret)
603 dev_info(chan->vi->dev,
604 "WAR:Calculation not precise.Ignore LA failure\n");
605#endif
606 return 0;
607}
608
609int vi2_channel_start_streaming(struct vb2_queue *vq, u32 count)
610{
611 struct tegra_channel *chan = vb2_get_drv_priv(vq);
612 struct media_pipeline *pipe = chan->video.entity.pipe;
613 int ret = 0, i;
614 struct tegra_csi_channel *csi_chan = NULL;
615 struct tegra_csi_device *csi = chan->vi->csi;
616 struct v4l2_ctrl *override_ctrl;
617
618 vi_channel_syncpt_init(chan);
619
620 tegra_channel_ec_init(chan);
621
622 /* Start the pipeline. */
623 ret = media_entity_pipeline_start(&chan->video.entity, pipe);
624 if (ret < 0)
625 goto error_pipeline_start;
626
627 if (chan->bypass) {
628 ret = tegra_channel_set_stream(chan, true);
629 if (ret < 0)
630 goto error_set_stream;
631 return ret;
632 }
633 chan->capture_state = CAPTURE_IDLE;
634 /* Find connected csi_channel */
635 csi_chan = find_linked_csi_channel(chan, csi);
636
637 if (!csi_chan)
638 goto error_set_stream;
639 for (i = 0; i < chan->valid_ports; i++) {
640 /* csi2_start_streaming(csi_chan, i); */
641 /* ensure sync point state is clean */
642 nvhost_syncpt_set_min_eq_max_ext(chan->vi->ndev,
643 chan->syncpt[i][0]);
644 }
645
646 /* Note: Program VI registers after TPG, sensors and CSI streaming */
647 ret = tegra_channel_capture_setup(chan);
648 if (ret < 0)
649 goto error_capture_setup;
650
651 chan->sequence = 0;
652 tegra_channel_init_ring_buffer(chan);
653
654 /* disable override for vi mode */
655 override_ctrl = v4l2_ctrl_find(
656 &chan->ctrl_handler, V4L2_CID_OVERRIDE_ENABLE);
657 if (!chan->pg_mode) {
658 if (override_ctrl) {
659 ret = v4l2_ctrl_s_ctrl(override_ctrl, false);
660 if (ret < 0)
661 dev_err(&chan->video.dev,
662 "failed to disable override control\n");
663 } else
664 dev_err(&chan->video.dev,
665 "No override control\n");
666 }
667 /* Update clock and bandwidth based on the format */
668 tegra_channel_update_clknbw(chan, 1);
669
670 /* Start kthread to capture data to buffer */
671 chan->kthread_capture_start = kthread_run(
672 tegra_channel_kthread_capture_start,
673 chan, chan->video.name);
674 if (IS_ERR(chan->kthread_capture_start)) {
675 dev_err(&chan->video.dev,
676 "failed to run kthread for capture start\n");
677 ret = PTR_ERR(chan->kthread_capture_start);
678 goto error_capture_setup;
679 }
680
681 return 0;
682
683error_capture_setup:
684 if (!chan->pg_mode)
685 tegra_channel_set_stream(chan, false);
686error_set_stream:
687 if (!chan->pg_mode)
688 media_entity_pipeline_stop(&chan->video.entity);
689error_pipeline_start:
690 vq->start_streaming_called = 0;
691 tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_QUEUED);
692
693 return ret;
694}
695
696void vi2_channel_stop_streaming(struct vb2_queue *vq)
697{
698 struct tegra_channel *chan = vb2_get_drv_priv(vq);
699 int index;
700 bool is_streaming = atomic_read(&chan->is_streaming);
701 struct tegra_csi_channel *csi_chan = NULL;
702 struct tegra_csi_device *csi = chan->vi->csi;
703
704 if (!chan->bypass) {
705 tegra_channel_stop_kthreads(chan);
706 /* wait for last frame memory write ack */
707 if (is_streaming && chan->capture_state == CAPTURE_GOOD)
708 tegra_channel_capture_done(chan);
709 /* free all the ring buffers */
710 free_ring_buffers(chan, chan->num_buffers);
711 /* dequeue buffers back to app which are in capture queue */
712 tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_ERROR);
713
714 /* Disable clock gating to enable continuous clock */
715 tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, DISABLE);
716 /* Find connected csi_channel */
717 csi_chan = find_linked_csi_channel(chan, csi);
718 if (!csi_chan)
719 pr_err("%s, no csi_chan found\n", __func__);
720 for (index = 0; index < chan->valid_ports; index++) {
721 /* csi2_stop_streaming(csi_chan, index); */
722 /* Always clear single shot if armed at close */
723 if (csi_read(chan, index, TEGRA_VI_CSI_SINGLE_SHOT))
724 tegra_channel_clear_singleshot(chan, index);
725 }
726 /* Enable clock gating so VI can be clock gated if necessary */
727 tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, ENABLE);
728 }
729
730 tegra_channel_set_stream(chan, false);
731 media_entity_pipeline_stop(&chan->video.entity);
732
733 if (!chan->bypass)
734 tegra_channel_update_clknbw(chan, 0);
735
736 vi_channel_syncpt_free(chan);
737}
738
739int tegra_vi2_power_on(struct tegra_mc_vi *vi)
740{
741 int ret;
742
743 ret = nvhost_module_busy(vi->ndev);
744 if (ret) {
745 dev_err(vi->dev, "%s:nvhost module is busy\n", __func__);
746 return ret;
747 }
748
749 vi_write(vi, TEGRA_VI_CFG_CG_CTRL, 1);
750
751 ret = tegra_camera_emc_clk_enable();
752 if (ret)
753 goto err_emc_enable;
754
755 return 0;
756
757err_emc_enable:
758 nvhost_module_idle(vi->ndev);
759
760 return ret;
761}
762
763void tegra_vi2_power_off(struct tegra_mc_vi *vi)
764{
765 tegra_channel_ec_close(vi);
766 tegra_camera_emc_clk_disable();
767 nvhost_module_idle(vi->ndev);
768}
769
770int vi2_power_on(struct tegra_channel *chan)
771{
772 int ret = 0;
773 struct tegra_mc_vi *vi;
774 struct vi *tegra_vi;
775 struct tegra_csi_device *csi;
776
777 vi = chan->vi;
778 tegra_vi = vi->vi;
779 csi = vi->csi;
780
781 ret = nvhost_module_add_client(vi->ndev, &chan->video);
782 if (ret)
783 return ret;
784
785 if (atomic_add_return(1, &vi->power_on_refcnt) == 1) {
786 tegra_vi2_power_on(vi);
787 if (chan->pg_mode)
788 tegra_vi->tpg_opened = true;
789 else
790 tegra_vi->sensor_opened = true;
791 }
792
793 if ((atomic_add_return(1, &chan->power_on_refcnt) == 1))
794 ret = tegra_channel_set_power(chan, 1);
795
796 return ret;
797}
798
799void vi2_power_off(struct tegra_channel *chan)
800{
801 int ret = 0;
802 struct tegra_mc_vi *vi;
803 struct vi *tegra_vi;
804 struct tegra_csi_device *csi;
805
806 vi = chan->vi;
807 tegra_vi = vi->vi;
808 csi = vi->csi;
809
810 if (atomic_dec_and_test(&chan->power_on_refcnt)) {
811 ret = tegra_channel_set_power(chan, 0);
812 if (ret < 0)
813 dev_err(vi->dev, "Failed to power off subdevices\n");
814 }
815
816 /* The last release then turn off power */
817 if (atomic_dec_and_test(&vi->power_on_refcnt)) {
818 tegra_vi2_power_off(vi);
819 if (vi->pg_mode)
820 tegra_vi->tpg_opened = false;
821 else
822 tegra_vi->sensor_opened = false;
823 }
824 nvhost_module_remove_client(vi->ndev, &chan->video);
825}
diff --git a/drivers/media/platform/tegra/camera/vi/vi2_fops.h b/drivers/media/platform/tegra/camera/vi/vi2_fops.h
new file mode 100644
index 000000000..66c59879c
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi2_fops.h
@@ -0,0 +1,34 @@
1/*
2 * Tegra Video Input 2 device common APIs
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
7 *
8 * Author: Bryan Wu <pengw@nvidia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __T210_VI_H__
16#define __T210_VI_H__
17
18int vi2_power_on(struct tegra_channel *chan);
19void vi2_power_off(struct tegra_channel *chan);
20int vi2_channel_start_streaming(struct vb2_queue *vq, u32 count);
21int vi2_channel_stop_streaming(struct vb2_queue *vq);
22int vi2_add_ctrls(struct tegra_channel *chan);
23void vi2_init_video_formats(struct tegra_channel *chan);
24
25struct tegra_vi_fops vi2_fops = {
26 .vi_power_on = vi2_power_on,
27 .vi_power_off = vi2_power_off,
28 .vi_start_streaming = vi2_channel_start_streaming,
29 .vi_stop_streaming = vi2_channel_stop_streaming,
30 .vi_add_ctrls = vi2_add_ctrls,
31 .vi_init_video_formats = vi2_init_video_formats,
32};
33
34#endif
diff --git a/drivers/media/platform/tegra/camera/vi/vi2_formats.h b/drivers/media/platform/tegra/camera/vi/vi2_formats.h
new file mode 100644
index 000000000..c272eac3e
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi2_formats.h
@@ -0,0 +1,131 @@
1/*
2 * NVIDIA Tegra Video Input Device Driver VI2 formats
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bhanu Murthy V <bmurthyv@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __VI2_FORMATS_H_
14#define __VI2_FORMATS_H_
15
16#include "camera/vi/core.h"
17
18/*
19 * These go into the TEGRA_VI_CSI_n_IMAGE_DEF registers bits 23:16
20 * Output pixel memory format for the VI channel.
21 */
22enum tegra_image_format {
23 TEGRA_IMAGE_FORMAT_T_L8 = 16,
24
25 TEGRA_IMAGE_FORMAT_T_R16_I = 32,
26 TEGRA_IMAGE_FORMAT_T_B5G6R5,
27 TEGRA_IMAGE_FORMAT_T_R5G6B5,
28 TEGRA_IMAGE_FORMAT_T_A1B5G5R5,
29 TEGRA_IMAGE_FORMAT_T_A1R5G5B5,
30 TEGRA_IMAGE_FORMAT_T_B5G5R5A1,
31 TEGRA_IMAGE_FORMAT_T_R5G5B5A1,
32 TEGRA_IMAGE_FORMAT_T_A4B4G4R4,
33 TEGRA_IMAGE_FORMAT_T_A4R4G4B4,
34 TEGRA_IMAGE_FORMAT_T_B4G4R4A4,
35 TEGRA_IMAGE_FORMAT_T_R4G4B4A4,
36
37 TEGRA_IMAGE_FORMAT_T_A8B8G8R8 = 64,
38 TEGRA_IMAGE_FORMAT_T_A8R8G8B8,
39 TEGRA_IMAGE_FORMAT_T_B8G8R8A8,
40 TEGRA_IMAGE_FORMAT_T_R8G8B8A8,
41 TEGRA_IMAGE_FORMAT_T_A2B10G10R10,
42 TEGRA_IMAGE_FORMAT_T_A2R10G10B10,
43 TEGRA_IMAGE_FORMAT_T_B10G10R10A2,
44 TEGRA_IMAGE_FORMAT_T_R10G10B10A2,
45
46 TEGRA_IMAGE_FORMAT_T_A8Y8U8V8 = 193,
47 TEGRA_IMAGE_FORMAT_T_V8U8Y8A8,
48
49 TEGRA_IMAGE_FORMAT_T_A2Y10U10V10 = 197,
50 TEGRA_IMAGE_FORMAT_T_V10U10Y10A2,
51
52 TEGRA_IMAGE_FORMAT_T_Y8_U8__Y8_V8 = 200,
53 TEGRA_IMAGE_FORMAT_T_Y8_V8__Y8_U8,
54 TEGRA_IMAGE_FORMAT_T_U8_Y8__V8_Y8,
55 TEGRA_IMAGE_FORMAT_T_T_V8_Y8__U8_Y8,
56
57 TEGRA_IMAGE_FORMAT_T_T_Y8__U8__V8_N444 = 224,
58 TEGRA_IMAGE_FORMAT_T_Y8__U8V8_N444,
59 TEGRA_IMAGE_FORMAT_T_Y8__V8U8_N444,
60 TEGRA_IMAGE_FORMAT_T_Y8__U8__V8_N422,
61 TEGRA_IMAGE_FORMAT_T_Y8__U8V8_N422,
62 TEGRA_IMAGE_FORMAT_T_Y8__V8U8_N422,
63 TEGRA_IMAGE_FORMAT_T_Y8__U8__V8_N420,
64 TEGRA_IMAGE_FORMAT_T_Y8__U8V8_N420,
65 TEGRA_IMAGE_FORMAT_T_Y8__V8U8_N420,
66 TEGRA_IMAGE_FORMAT_T_X2Lc10Lb10La10,
67 TEGRA_IMAGE_FORMAT_T_A2R6R6R6R6R6,
68};
69
70static const struct tegra_video_format vi2_video_formats[] = {
71 /* RAW 6: TODO */
72
73 /* RAW 7: TODO */
74
75 /* RAW 8 */
76 TEGRA_VIDEO_FORMAT(RAW8, 8, SRGGB8_1X8, 1, 1, T_L8,
77 RAW8, SRGGB8, "RGRG.. GBGB.."),
78 TEGRA_VIDEO_FORMAT(RAW8, 8, SGRBG8_1X8, 1, 1, T_L8,
79 RAW8, SGRBG8, "GRGR.. BGBG.."),
80 TEGRA_VIDEO_FORMAT(RAW8, 8, SGBRG8_1X8, 1, 1, T_L8,
81 RAW8, SGBRG8, "GBGB.. RGRG.."),
82 TEGRA_VIDEO_FORMAT(RAW8, 8, SBGGR8_1X8, 1, 1, T_L8,
83 RAW8, SBGGR8, "BGBG.. GRGR.."),
84
85 /* RAW 10 */
86 TEGRA_VIDEO_FORMAT(RAW10, 10, SRGGB10_1X10, 2, 1, T_R16_I,
87 RAW10, SRGGB10, "RGRG.. GBGB.."),
88 TEGRA_VIDEO_FORMAT(RAW10, 10, SGRBG10_1X10, 2, 1, T_R16_I,
89 RAW10, SGRBG10, "GRGR.. BGBG.."),
90 TEGRA_VIDEO_FORMAT(RAW10, 10, SGBRG10_1X10, 2, 1, T_R16_I,
91 RAW10, SGBRG10, "GBGB.. RGRG.."),
92 TEGRA_VIDEO_FORMAT(RAW10, 10, SBGGR10_1X10, 2, 1, T_R16_I,
93 RAW10, SBGGR10, "BGBG.. GRGR.."),
94
95 /* RAW 10 Packed format */
96 TEGRA_VIDEO_FORMAT(RAW10, 10, XBGGR10P_3X10, 4, 3, T_X2Lc10Lb10La10,
97 RAW10, XBGGR10P, "BGBG.. GRGR.."),
98 TEGRA_VIDEO_FORMAT(RAW10, 10, XRGGB10P_3X10, 4, 3, T_X2Lc10Lb10La10,
99 RAW10, XRGGB10P, "RGRG.. GBGB.."),
100
101 /* RAW 12 */
102 TEGRA_VIDEO_FORMAT(RAW12, 12, SRGGB12_1X12, 2, 1, T_R16_I,
103 RAW12, SRGGB12, "RGRG.. GBGB.."),
104 TEGRA_VIDEO_FORMAT(RAW12, 12, SGRBG12_1X12, 2, 1, T_R16_I,
105 RAW12, SGRBG12, "GRGR.. BGBG.."),
106 TEGRA_VIDEO_FORMAT(RAW12, 12, SGBRG12_1X12, 2, 1, T_R16_I,
107 RAW12, SGBRG12, "GBGB.. RGRG.."),
108 TEGRA_VIDEO_FORMAT(RAW12, 12, SBGGR12_1X12, 2, 1, T_R16_I,
109 RAW12, SBGGR12, "BGBG.. GRGR.."),
110
111 /* RGB888 */
112 TEGRA_VIDEO_FORMAT(RGB888, 24, RGB888_1X24, 4, 1, T_A8R8G8B8,
113 RGB888, ABGR32, "BGRA-8-8-8-8"),
114 TEGRA_VIDEO_FORMAT(RGB888, 24, RGB888_1X32_PADHI, 4, 1, T_A8B8G8R8,
115 RGB888, RGB32, "RGB-8-8-8-8"),
116
117 /* YUV422 */
118 TEGRA_VIDEO_FORMAT(YUV422, 16, UYVY8_1X16, 2, 1, T_U8_Y8__V8_Y8,
119 YUV422_8, UYVY, "YUV 4:2:2"),
120 TEGRA_VIDEO_FORMAT(YUV422, 16, UYVY8_1X16, 1, 1, T_Y8__V8U8_N422,
121 YUV422_8, NV16, "NV16"),
122 TEGRA_VIDEO_FORMAT(YUV422, 16, UYVY8_2X8, 2, 1, T_U8_Y8__V8_Y8,
123 YUV422_8, UYVY, "YUV 4:2:2 UYVY"),
124 TEGRA_VIDEO_FORMAT(YUV422, 16, VYUY8_2X8, 2, 1, T_T_V8_Y8__U8_Y8,
125 YUV422_8, VYUY, "YUV 4:2:2 VYUY"),
126 TEGRA_VIDEO_FORMAT(YUV422, 16, YUYV8_2X8, 2, 1, T_Y8_U8__Y8_V8,
127 YUV422_8, YUYV, "YUV 4:2:2 YUYV"),
128 TEGRA_VIDEO_FORMAT(YUV422, 16, YVYU8_2X8, 2, 1, T_Y8_V8__Y8_U8,
129 YUV422_8, YVYU, "YUV 4:2:2 YVYU"),
130};
131#endif
diff --git a/drivers/media/platform/tegra/camera/vi/vi4_fops.c b/drivers/media/platform/tegra/camera/vi/vi4_fops.c
new file mode 100644
index 000000000..d78ed3421
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi4_fops.c
@@ -0,0 +1,1056 @@
1/*
2 * Tegra Video Input 4 device common APIs
3 *
4 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Frank Chen <frank@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/freezer.h>
13#include <linux/kthread.h>
14#include <linux/nvhost.h>
15#include <linux/tegra-powergate.h>
16#include <media/capture.h>
17#include <media/tegra_camera_platform.h>
18#include "linux/nvhost_ioctl.h"
19#include "mc_common.h"
20#include "nvhost_acm.h"
21#include "vi4_formats.h"
22#include "vi4_registers.h"
23#include "vi/vi4.h"
24#include "vi/vi_notify.h"
25
26#define DEFAULT_FRAMERATE 30
27#define DEFAULT_CSI_FREQ 204000000
28#define BPP_MEM 2
29#define MAX_VI_CHANNEL 12
30#define NUM_PPC 8
31#define VI_CSI_CLK_SCALE 110
32#define SOF_SYNCPT_IDX 0
33#define FE_SYNCPT_IDX 1
34
35void tegra_channel_queued_buf_done(struct tegra_channel *chan,
36 enum vb2_buffer_state state);
37int tegra_channel_set_stream(struct tegra_channel *chan, bool on);
38void tegra_channel_ring_buffer(struct tegra_channel *chan,
39 struct vb2_v4l2_buffer *vb,
40 struct timespec *ts, int state);
41struct tegra_channel_buffer *dequeue_buffer(struct tegra_channel *chan);
42void tegra_channel_init_ring_buffer(struct tegra_channel *chan);
43void free_ring_buffers(struct tegra_channel *chan, int frames);
44int tegra_channel_set_power(struct tegra_channel *chan, bool on);
45static void tegra_channel_stop_kthreads(struct tegra_channel *chan);
46static int tegra_channel_stop_increments(struct tegra_channel *chan);
47static void tegra_channel_notify_status_callback(
48 struct vi_notify_channel *,
49 const struct vi_capture_status *,
50 void *);
51static void tegra_channel_error_worker(struct work_struct *status_work);
52static void tegra_channel_notify_error_callback(void *);
53
54u32 csimux_config_stream[] = {
55 CSIMUX_CONFIG_STREAM_0,
56 CSIMUX_CONFIG_STREAM_1,
57 CSIMUX_CONFIG_STREAM_2,
58 CSIMUX_CONFIG_STREAM_3,
59 CSIMUX_CONFIG_STREAM_4,
60 CSIMUX_CONFIG_STREAM_5
61};
62
63static void vi4_write(struct tegra_channel *chan, unsigned int addr, u32 val)
64{
65 writel(val, chan->vi->iomem + addr);
66}
67
68static u32 vi4_read(struct tegra_channel *chan, unsigned int addr)
69{
70 return readl(chan->vi->iomem + addr);
71}
72
73static void vi4_channel_write(struct tegra_channel *chan,
74 unsigned int index, unsigned int addr, u32 val)
75{
76 writel(val,
77 chan->vi->iomem + VI4_CHANNEL_OFFSET * (index + 1) + addr);
78}
79
80void vi4_init_video_formats(struct tegra_channel *chan)
81{
82 int i;
83
84 chan->num_video_formats = ARRAY_SIZE(vi4_video_formats);
85 for (i = 0; i < chan->num_video_formats; i++)
86 chan->video_formats[i] = &vi4_video_formats[i];
87}
88
89long vi4_default_ioctl(struct file *file, void *fh,
90 bool use_prio, unsigned int cmd, void *arg)
91{
92 struct v4l2_fh *vfh = file->private_data;
93 struct tegra_channel *chan = to_tegra_channel(vfh->vdev);
94 long err = 0;
95
96 switch (_IOC_NR(cmd)) {
97#if defined(CONFIG_TEGRA_CAMERA_RTCPU)
98 case _IOC_NR(VIDIOC_CAPTURE_SETUP):
99 if (chan->bypass)
100 err = vi_capture_setup(chan,
101 (struct vi_capture_setup *)arg);
102 else {
103 dev_err(&chan->video.dev, "not in bypass mode\n");
104 err = -ENODEV;
105 }
106 if (err)
107 dev_err(&chan->video.dev, "capture setup failed\n");
108 break;
109 case _IOC_NR(VIDIOC_CAPTURE_RESET):
110 if (chan->bypass)
111 err = vi_capture_reset(chan, *(uint32_t *)arg);
112 else {
113 dev_err(&chan->video.dev, "not in bypass mode\n");
114 err = -ENODEV;
115 }
116 if (err)
117 dev_err(&chan->video.dev, "capture reset failed\n");
118 break;
119 case _IOC_NR(VIDIOC_CAPTURE_RELEASE):
120 if (chan->bypass)
121 err = vi_capture_release(chan, *(uint32_t *)arg);
122 else {
123 dev_err(&chan->video.dev, "not in bypass mode\n");
124 err = -ENODEV;
125 }
126 if (err)
127 dev_err(&chan->video.dev, "capture release failed\n");
128 break;
129 case _IOC_NR(VIDIOC_CAPTURE_GET_INFO):
130 if (chan->bypass)
131 err = vi_capture_get_info(chan,
132 (struct vi_capture_info *)arg);
133 else {
134 dev_err(&chan->video.dev, "not in bypass mode\n");
135 err = -ENODEV;
136 }
137 if (err)
138 dev_err(&chan->video.dev, "capture get info failed\n");
139 break;
140 case _IOC_NR(VIDIOC_CAPTURE_SET_CONFIG):
141 if (chan->bypass)
142 err = vi_capture_control_message(chan,
143 (struct vi_capture_control_msg *)arg);
144 else {
145 dev_err(&chan->video.dev, "not in bypass mode\n");
146 err = -ENODEV;
147 }
148 if (err)
149 dev_err(&chan->video.dev, "capture config failed\n");
150 break;
151 case _IOC_NR(VIDIOC_CAPTURE_REQUEST):
152 if (chan->bypass)
153 err = vi_capture_request(chan,
154 (struct vi_capture_req *)arg);
155 else {
156 dev_err(&chan->video.dev, "not in bypass mode\n");
157 err = -ENODEV;
158 }
159 if (err)
160 dev_err(&chan->video.dev,
161 "capture request submit failed\n");
162 break;
163 case _IOC_NR(VIDIOC_CAPTURE_STATUS):
164 if (chan->bypass)
165 err = vi_capture_status(chan, *(uint32_t *)arg);
166 else {
167 dev_err(&chan->video.dev, "not in bypass mode\n");
168 err = -ENODEV;
169 }
170 if (err)
171 dev_err(&chan->video.dev,
172 "capture get status failed\n");
173 break;
174#endif
175 default:
176 dev_err(&chan->video.dev, "%s:Unknown ioctl\n", __func__);
177 return -ENOIOCTLCMD;
178 }
179
180 return err;
181}
182
183
184int tegra_vi4_s_ctrl(struct v4l2_ctrl *ctrl)
185{
186 struct tegra_channel *chan = container_of(ctrl->handler,
187 struct tegra_channel, ctrl_handler);
188 int err = 0;
189
190 switch (ctrl->id) {
191 case V4L2_CID_WRITE_ISPFORMAT:
192 chan->write_ispformat = ctrl->val;
193 break;
194 default:
195 dev_err(&chan->video.dev, "%s:Not valid ctrl\n", __func__);
196 return -EINVAL;
197 }
198
199 return err;
200}
201
202static const struct v4l2_ctrl_ops vi4_ctrl_ops = {
203 .s_ctrl = tegra_vi4_s_ctrl,
204};
205
206static const struct v4l2_ctrl_config vi4_custom_ctrls[] = {
207 {
208 .ops = &vi4_ctrl_ops,
209 .id = V4L2_CID_WRITE_ISPFORMAT,
210 .name = "Write ISP format",
211 .type = V4L2_CTRL_TYPE_INTEGER,
212 .def = 1,
213 .min = 1,
214 .max = 1,
215 .step = 1,
216 },
217};
218
219int vi4_add_ctrls(struct tegra_channel *chan)
220{
221 int i;
222
223 /* Add vi4 custom controls */
224 for (i = 0; i < ARRAY_SIZE(vi4_custom_ctrls); i++) {
225 v4l2_ctrl_new_custom(&chan->ctrl_handler,
226 &vi4_custom_ctrls[i], NULL);
227 if (chan->ctrl_handler.error) {
228 dev_err(chan->vi->dev,
229 "Failed to add %s ctrl\n",
230 vi4_custom_ctrls[i].name);
231 return chan->ctrl_handler.error;
232 }
233 }
234
235 return 0;
236}
237
238static bool vi4_init(struct tegra_channel *chan)
239{
240 vi4_write(chan, CFG_INTERRUPT_MASK, 0x3f0000f9);
241 vi4_write(chan, CFG_INTERRUPT_STATUS, 0x3f000001);
242 vi4_write(chan, NOTIFY_ERROR, 0x1);
243 vi4_write(chan, NOTIFY_TAG_CLASSIFY_0, 0xe39c08e3);
244 return true;
245}
246
247static bool vi4_check_status(struct tegra_channel *chan)
248{
249 int status;
250
251 /* check interrupt status error */
252 status = vi4_read(chan, CFG_INTERRUPT_STATUS);
253 if (status & 0x1)
254 dev_err(chan->vi->dev,
255 "VI_CFG_INTERRUPT_STATUS_0: MASTER_ERR_STATUS error!\n");
256
257 /* Check VI NOTIFY input FIFO error */
258 status = vi4_read(chan, NOTIFY_ERROR);
259 if (status & 0x1)
260 dev_err(chan->vi->dev,
261 "VI_NOTIFY_ERROR_0: NOTIFY_FIFO_OVERFLOW error!\n");
262
263 return true;
264}
265
266static bool vi_notify_wait(struct tegra_channel *chan,
267 struct timespec *ts)
268{
269 int i, err;
270 u32 thresh[TEGRA_CSI_BLOCKS], temp;
271
272 /*
273 * Increment syncpt for ATOMP_FE
274 *
275 * This is needed in order to keep the syncpt max up to date,
276 * even if we are not waiting for ATOMP_FE here
277 */
278 for (i = 0; i < chan->valid_ports; i++)
279 temp = nvhost_syncpt_incr_max_ext(chan->vi->ndev,
280 chan->syncpt[i][FE_SYNCPT_IDX], 1);
281
282 /*
283 * Increment syncpt for PXL_SOF
284 *
285 * Increment and retrieve PXL_SOF syncpt max value.
286 * This value will be used to wait for next syncpt
287 */
288 for (i = 0; i < chan->valid_ports; i++)
289 thresh[i] = nvhost_syncpt_incr_max_ext(chan->vi->ndev,
290 chan->syncpt[i][SOF_SYNCPT_IDX], 1);
291
292 /*
293 * Wait for PXL_SOF syncpt
294 *
295 * Use the syncpt max value we just set as threshold
296 */
297 for (i = 0; i < chan->valid_ports; i++) {
298 err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
299 chan->syncpt[i][SOF_SYNCPT_IDX], thresh[i],
300 250, NULL, NULL);
301 if (unlikely(err))
302 dev_err(chan->vi->dev,
303 "PXL_SOF syncpt timeout! err = %d\n", err);
304 else {
305 struct vi_capture_status status;
306
307 err = vi_notify_get_capture_status(chan->vnc[i],
308 chan->vnc_id[i],
309 thresh[i], &status);
310 if (unlikely(err))
311 dev_err(chan->vi->dev,
312 "no capture status! err = %d\n", err);
313 else
314 *ts = ns_to_timespec((s64)status.sof_ts);
315 }
316 }
317 return true;
318}
319
320static void tegra_channel_surface_setup(
321 struct tegra_channel *chan, struct tegra_channel_buffer *buf, int index)
322{
323 int vnc_id = chan->vnc_id[index];
324 unsigned int offset = chan->buffer_offset[index];
325
326 vi4_channel_write(chan, vnc_id, ATOMP_EMB_SURFACE_OFFSET0, 0x0);
327 vi4_channel_write(chan, vnc_id, ATOMP_EMB_SURFACE_OFFSET0_H, 0x0);
328 vi4_channel_write(chan, vnc_id, ATOMP_EMB_SURFACE_STRIDE0, 0x0);
329 vi4_channel_write(chan, vnc_id,
330 ATOMP_SURFACE_OFFSET0, buf->addr + offset);
331 vi4_channel_write(chan, vnc_id,
332 ATOMP_SURFACE_STRIDE0, chan->format.bytesperline);
333 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_OFFSET0_H, 0x0);
334
335 if (chan->fmtinfo->fourcc == V4L2_PIX_FMT_NV16) {
336 vi4_channel_write(chan, vnc_id,
337 ATOMP_SURFACE_OFFSET1, buf->addr + offset +
338 chan->format.sizeimage / 2);
339 vi4_channel_write(chan, vnc_id,
340 ATOMP_SURFACE_OFFSET1_H, 0x0);
341 vi4_channel_write(chan, vnc_id,
342 ATOMP_SURFACE_STRIDE1, chan->format.bytesperline);
343
344 } else {
345 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_OFFSET1, 0x0);
346 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_OFFSET1_H, 0x0);
347 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_STRIDE1, 0x0);
348 }
349
350 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_OFFSET2, 0x0);
351 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_OFFSET2_H, 0x0);
352 vi4_channel_write(chan, vnc_id, ATOMP_SURFACE_STRIDE2, 0x0);
353}
354
355static void tegra_channel_handle_error(struct tegra_channel *chan)
356{
357 struct v4l2_subdev *sd_on_csi = chan->subdev_on_csi;
358 static const struct v4l2_event source_ev_fmt = {
359 .type = V4L2_EVENT_SOURCE_CHANGE,
360 .u.src_change.changes = V4L2_EVENT_SRC_ERROR,
361 };
362
363 tegra_channel_stop_increments(chan);
364 vb2_queue_error(&chan->queue);
365
366 /* Application gets notified after CSI Tx's are reset */
367 if (sd_on_csi->devnode)
368 v4l2_subdev_notify_event(sd_on_csi, &source_ev_fmt);
369}
370
371static void tegra_channel_status_worker(struct work_struct *status_work)
372{
373 struct tegra_channel *chan;
374
375 chan = container_of(status_work, struct tegra_channel, status_work);
376
377 tegra_channel_handle_error(chan);
378}
379
380static void tegra_channel_notify_status_callback(
381 struct vi_notify_channel *vnc,
382 const struct vi_capture_status *status,
383 void *client_data)
384{
385 struct tegra_channel *chan = (struct tegra_channel *)client_data;
386 int i;
387
388 spin_lock(&chan->capture_state_lock);
389 if (chan->capture_state == CAPTURE_GOOD)
390 chan->capture_state = CAPTURE_ERROR;
391 else {
392 spin_unlock(&chan->capture_state_lock);
393 return;
394 }
395 spin_unlock(&chan->capture_state_lock);
396
397 for (i = 0; i < chan->valid_ports; i++)
398 dev_err(chan->vi->dev, "Status: %2u channel:%02X frame:%04X\n",
399 status->status, chan->vnc_id[i], status->frame);
400 dev_err(chan->vi->dev, " timestamp sof %llu eof %llu data 0x%08x\n",
401 status->sof_ts, status->eof_ts, status->data);
402 dev_err(chan->vi->dev, " capture_id %u stream %2u vchan %2u\n",
403 status->capture_id, status->st, status->vc);
404
405 schedule_work(&chan->status_work);
406}
407
408static int tegra_channel_notify_enable(
409 struct tegra_channel *chan, unsigned int index)
410{
411 struct tegra_vi4_syncpts_req req;
412 int i, err;
413
414 chan->vnc_id[index] = -1;
415 for (i = 0; i < MAX_VI_CHANNEL; i++) {
416 chan->vnc[index] = vi_notify_channel_open(i);
417 if (!IS_ERR(chan->vnc[index])) {
418 chan->vnc_id[index] = i;
419 break;
420 }
421 }
422 if (chan->vnc_id[index] < 0) {
423 dev_err(chan->vi->dev, "No VI channel available!\n");
424 return -EFAULT;
425 }
426
427 vi_notify_channel_set_notify_funcs(chan->vnc[index],
428 &tegra_channel_notify_status_callback,
429 &tegra_channel_notify_error_callback,
430 (void *)chan);
431
432 /* get PXL_SOF syncpt id */
433 chan->syncpt[index][SOF_SYNCPT_IDX] =
434 nvhost_get_syncpt_client_managed(chan->vi->ndev, "tegra-vi4");
435 if (chan->syncpt[index][SOF_SYNCPT_IDX] == 0) {
436 dev_err(chan->vi->dev, "Failed to get PXL_SOF syncpt!\n");
437 return -EFAULT;
438 }
439
440 /* get ATOMP_FE syncpt id */
441 chan->syncpt[index][FE_SYNCPT_IDX] =
442 nvhost_get_syncpt_client_managed(chan->vi->ndev, "tegra-vi4");
443 if (chan->syncpt[index][FE_SYNCPT_IDX] == 0) {
444 dev_err(chan->vi->dev, "Failed to get ATOMP_FE syncpt!\n");
445 nvhost_syncpt_put_ref_ext(
446 chan->vi->ndev, chan->syncpt[index][SOF_SYNCPT_IDX]);
447 return -EFAULT;
448 }
449
450 nvhost_syncpt_set_min_eq_max_ext(
451 chan->vi->ndev, chan->syncpt[index][SOF_SYNCPT_IDX]);
452 nvhost_syncpt_set_min_eq_max_ext(
453 chan->vi->ndev, chan->syncpt[index][FE_SYNCPT_IDX]);
454
455 /* enable VI Notify report */
456 req.syncpt_ids[0] = chan->syncpt[index][SOF_SYNCPT_IDX]; /* PXL_SOF */
457 req.syncpt_ids[1] = chan->syncpt[index][FE_SYNCPT_IDX]; /* ATOMP_FE */
458 req.syncpt_ids[2] = 0xffffffff;
459 req.stream = chan->port[index];
460 req.vc = 0;
461 req.pad = 0;
462
463 err = vi_notify_channel_enable_reports(
464 chan->vnc_id[index], chan->vnc[index], &req);
465 if (err < 0)
466 dev_err(chan->vi->dev,
467 "Failed to enable report for VI Notify, err = %d\n",
468 err);
469
470 return err;
471}
472
473static int tegra_channel_notify_disable(
474 struct tegra_channel *chan, unsigned int index)
475{
476 int err;
477 int ret = 0;
478 struct tegra_vi4_syncpts_req req;
479
480 /* free syncpts */
481 nvhost_syncpt_put_ref_ext(
482 chan->vi->ndev, chan->syncpt[index][SOF_SYNCPT_IDX]);
483 nvhost_syncpt_put_ref_ext(
484 chan->vi->ndev, chan->syncpt[index][FE_SYNCPT_IDX]);
485
486 /* close vi-notifier */
487 req.syncpt_ids[0] = 0xffffffff;
488 req.syncpt_ids[1] = 0xffffffff;
489 req.syncpt_ids[2] = 0xffffffff;
490 req.stream = chan->port[index];
491 req.vc = 0;
492 req.pad = 0;
493
494 err = vi_notify_channel_reset(
495 chan->vnc_id[index], chan->vnc[index], &req);
496 if (err < 0) {
497 dev_err(chan->vi->dev,
498 "VI Notify channel reset failed, err = %d\n", err);
499 if (!ret)
500 ret = err;
501 }
502
503 err = vi_notify_channel_close(chan->vnc_id[index], chan->vnc[index]);
504 if (err < 0) {
505 dev_err(chan->vi->dev,
506 "VI Notify channel close failed, err = %d\n", err);
507 if (!ret)
508 ret = err;
509 }
510
511 return ret;
512}
513
514static int tegra_channel_capture_setup(struct tegra_channel *chan,
515 unsigned int index)
516{
517 u32 height = chan->format.height;
518 u32 width = chan->format.width;
519 u32 format = chan->fmtinfo->img_fmt;
520 u32 data_type = chan->fmtinfo->img_dt;
521 u32 csi_port = chan->port[index];
522 u32 stream = 1U << csi_port;
523 u32 virtual_ch = 1U << 0;
524 u32 vnc_id;
525 int err;
526
527 if (chan->valid_ports > 1) {
528 height = chan->gang_height;
529 width = chan->gang_width;
530 }
531
532 err = tegra_channel_notify_enable(chan, index);
533 if (err < 0) {
534 dev_err(chan->vi->dev,
535 "Failed to setup VI Notifier, err = %d\n", err);
536 return err;
537 }
538
539 vnc_id = chan->vnc_id[index];
540
541 vi4_write(chan, csimux_config_stream[csi_port], 0x1);
542
543 vi4_channel_write(chan, vnc_id, MATCH,
544 ((stream << STREAM_SHIFT) & STREAM) |
545 STREAM_MASK |
546 ((virtual_ch << VIRTUAL_CHANNEL_SHIFT) &
547 VIRTUAL_CHANNEL) |
548 VIRTUAL_CHANNEL_MASK);
549
550 vi4_channel_write(chan, vnc_id, MATCH_DATATYPE,
551 ((data_type << DATATYPE_SHIFT) & DATATYPE) |
552 DATATYPE_MASK);
553
554 vi4_channel_write(chan, vnc_id, DT_OVERRIDE, 0x0);
555
556 vi4_channel_write(chan, vnc_id, MATCH_FRAMEID,
557 ((0 << FRAMEID_SHIFT) & FRAMEID) | 0);
558
559 vi4_channel_write(chan, vnc_id, FRAME_X, width);
560 vi4_channel_write(chan, vnc_id, FRAME_Y, height);
561 vi4_channel_write(chan, vnc_id, SKIP_X, 0x0);
562 vi4_channel_write(chan, vnc_id, CROP_X, width);
563 vi4_channel_write(chan, vnc_id, OUT_X, width);
564 vi4_channel_write(chan, vnc_id, SKIP_Y, 0x0);
565 vi4_channel_write(chan, vnc_id, CROP_Y, height);
566 vi4_channel_write(chan, vnc_id, OUT_Y, height);
567 vi4_channel_write(chan, vnc_id, PIXFMT_ENABLE, PIXFMT_EN);
568 vi4_channel_write(chan, vnc_id, PIXFMT_WIDE, 0x0);
569 vi4_channel_write(chan, vnc_id, PIXFMT_FORMAT, format);
570 vi4_channel_write(chan, vnc_id, DPCM_STRIP, 0x0);
571 vi4_channel_write(chan, vnc_id, ATOMP_DPCM_CHUNK, 0x0);
572 vi4_channel_write(chan, vnc_id, ISPBUFA, 0x0);
573 vi4_channel_write(chan, vnc_id, LINE_TIMER, 0x1000000);
574 vi4_channel_write(chan, vnc_id, EMBED_X, 0x0);
575 vi4_channel_write(chan, vnc_id, EMBED_Y, 0x0);
576 /*
577 * Set ATOMP_RESERVE to 0 so rctpu won't increment syncpt
578 * for captureInfo. This is copied from nvvi driver.
579 *
580 * If we don't set this register to 0, ATOMP_FE syncpt
581 * will be increment by 2 for each frame
582 */
583 vi4_channel_write(chan, vnc_id, ATOMP_RESERVE, 0x0);
584 dev_dbg(chan->vi->dev,
585 "Create Surface with imgW=%d, imgH=%d, memFmt=%d\n",
586 width, height, format);
587
588 return 0;
589}
590
591static int tegra_channel_capture_frame(struct tegra_channel *chan,
592 struct tegra_channel_buffer *buf)
593{
594 struct vb2_v4l2_buffer *vb = &buf->buf;
595 struct timespec ts;
596 int state = VB2_BUF_STATE_DONE;
597 unsigned long flags;
598 int err = false;
599 int i;
600
601 for (i = 0; i < chan->valid_ports; i++)
602 tegra_channel_surface_setup(chan, buf, i);
603
604 if (!chan->bfirst_fstart) {
605 err = tegra_channel_set_stream(chan, true);
606 if (err < 0)
607 return err;
608 }
609
610 for (i = 0; i < chan->valid_ports; i++) {
611 vi4_channel_write(chan, chan->vnc_id[i], CHANNEL_COMMAND, LOAD);
612 vi4_channel_write(chan, chan->vnc_id[i],
613 CONTROL, SINGLESHOT | MATCH_STATE_EN);
614 }
615
616 /* wait for vi notifier events */
617 vi_notify_wait(chan, &ts);
618
619 vi4_check_status(chan);
620
621 spin_lock_irqsave(&chan->capture_state_lock, flags);
622 if (chan->capture_state != CAPTURE_ERROR)
623 chan->capture_state = CAPTURE_GOOD;
624 spin_unlock_irqrestore(&chan->capture_state_lock, flags);
625
626 tegra_channel_ring_buffer(chan, vb, &ts, state);
627
628 return 0;
629}
630
631static int tegra_channel_stop_increments(struct tegra_channel *chan)
632{
633 int i;
634 struct tegra_vi4_syncpts_req req = {
635 .syncpt_ids = {
636 0xffffffff,
637 0xffffffff,
638 0xffffffff,
639 },
640 .stream = chan->port[0],
641 .vc = 0,
642 };
643
644 /* No need to check errors. There's nothing we could do. */
645 for (i = 0; i < chan->valid_ports; i++)
646 vi_notify_channel_reset(chan->vnc_id[i], chan->vnc[i], &req);
647
648 return 0;
649}
650
651static void tegra_channel_capture_done(struct tegra_channel *chan)
652{
653 struct timespec ts;
654 struct tegra_channel_buffer *buf;
655 int state = VB2_BUF_STATE_DONE;
656 u32 thresh[TEGRA_CSI_BLOCKS];
657 int i, err;
658
659 /* dequeue buffer and return if no buffer exists */
660 buf = dequeue_buffer(chan);
661 if (!buf)
662 return;
663
664 /* make sure to read the last frame out before exit */
665 for (i = 0; i < chan->valid_ports; i++) {
666 tegra_channel_surface_setup(chan, buf, i);
667 vi4_channel_write(chan, chan->vnc_id[i], CHANNEL_COMMAND, LOAD);
668 vi4_channel_write(chan, chan->vnc_id[i],
669 CONTROL, SINGLESHOT | MATCH_STATE_EN);
670 }
671
672 for (i = 0; i < chan->valid_ports; i++) {
673 err = nvhost_syncpt_read_ext_check(chan->vi->ndev,
674 chan->syncpt[i][FE_SYNCPT_IDX], &thresh[i]);
675 /* Get current ATOMP_FE syncpt min value */
676 if (!err) {
677 struct vi_capture_status status;
678 u32 index = thresh[i] + 1;
679 /* Wait for ATOMP_FE syncpt
680 *
681 * This is to make sure we don't exit the capture thread
682 * before the last frame is done writing to memory
683 */
684 err = nvhost_syncpt_wait_timeout_ext(chan->vi->ndev,
685 chan->syncpt[i][FE_SYNCPT_IDX],
686 index,
687 250, NULL, NULL);
688 if (unlikely(err))
689 dev_err(chan->vi->dev,
690 "ATOMP_FE syncpt timeout!\n");
691 else {
692 err = vi_notify_get_capture_status(chan->vnc[i],
693 chan->vnc_id[i],
694 index, &status);
695 if (unlikely(err))
696 dev_err(chan->vi->dev,
697 "no capture status! err = %d\n",
698 err);
699 else
700 ts = ns_to_timespec((s64)status.eof_ts);
701 }
702 }
703 }
704
705 /* Mark capture state to IDLE as capture is finished */
706 chan->capture_state = CAPTURE_IDLE;
707
708 tegra_channel_ring_buffer(chan, &buf->buf, &ts, state);
709}
710
711static int tegra_channel_kthread_capture_start(void *data)
712{
713 struct tegra_channel *chan = data;
714 struct tegra_channel_buffer *buf;
715 int err = 0;
716
717 set_freezable();
718
719 while (1) {
720
721 try_to_freeze();
722
723 wait_event_interruptible(chan->start_wait,
724 !list_empty(&chan->capture) ||
725 kthread_should_stop());
726
727 if (kthread_should_stop())
728 break;
729
730 /* source is not streaming if error is non-zero */
731 /* wait till kthread stop and dont DeQ buffers */
732 if (err)
733 continue;
734
735 buf = dequeue_buffer(chan);
736 if (!buf)
737 continue;
738
739 err = tegra_channel_capture_frame(chan, buf);
740 }
741
742 return 0;
743}
744
745static void tegra_channel_stop_kthreads(struct tegra_channel *chan)
746{
747 mutex_lock(&chan->stop_kthread_lock);
748 /* Stop the kthread for capture */
749 if (chan->kthread_capture_start) {
750 kthread_stop(chan->kthread_capture_start);
751 chan->kthread_capture_start = NULL;
752 }
753 mutex_unlock(&chan->stop_kthread_lock);
754}
755
756static int tegra_channel_update_clknbw(struct tegra_channel *chan, u8 on)
757{
758 int ret = 0;
759 unsigned long request_pixelrate;
760 struct v4l2_subdev_frame_interval fie;
761 unsigned long csi_freq = 0;
762
763 fie.interval.denominator = DEFAULT_FRAMERATE;
764 fie.interval.numerator = 1;
765
766 if (v4l2_subdev_has_op(chan->subdev_on_csi,
767 video, g_frame_interval))
768 v4l2_subdev_call(chan->subdev_on_csi, video,
769 g_frame_interval, &fie);
770 if (on) {
771 /* for PG, using default frequence */
772 if (chan->pg_mode) {
773 csi_freq = DEFAULT_CSI_FREQ;
774 request_pixelrate = csi_freq * NUM_PPC;
775 } else {
776 /**
777 * TODO: use real sensor pixelrate
778 * See PowerService code
779 */
780 request_pixelrate = (long long)(chan->format.width
781 * chan->format.height
782 * fie.interval.denominator / 100)
783 * VI_CSI_CLK_SCALE;
784 csi_freq = ((long long)chan->format.width
785 * chan->format.height
786 * fie.interval.denominator) / NUM_PPC;
787 }
788
789 /* VI clk should be slightly faster than CSI clk*/
790 ret = nvhost_module_set_rate(chan->vi->ndev, &chan->video,
791 request_pixelrate, 0, NVHOST_PIXELRATE);
792 if (ret) {
793 dev_err(chan->vi->dev, "Fail to update vi clk\n");
794 return ret;
795 }
796 } else {
797 csi_freq = DEFAULT_CSI_FREQ;
798 ret = nvhost_module_set_rate(chan->vi->ndev, &chan->video, 0, 0,
799 NVHOST_PIXELRATE);
800 if (ret) {
801 dev_err(chan->vi->dev, "Fail to update vi clk\n");
802 return ret;
803 }
804 }
805 if (chan->pg_mode)
806 chan->requested_kbyteps = (on > 0 ? 1 : -1) *
807 ((long long)csi_freq * BPP_MEM * 110 / 100) / 1000;
808 else
809 chan->requested_kbyteps = (on > 0 ? 1 : -1) *
810 (((long long) chan->format.width * chan->format.height
811 * fie.interval.denominator * BPP_MEM) * 115 / 100) / 1000;
812
813 mutex_lock(&chan->vi->bw_update_lock);
814 chan->vi->aggregated_kbyteps += chan->requested_kbyteps;
815 ret = vi_v4l2_update_isobw(chan->vi->aggregated_kbyteps, 0);
816 mutex_unlock(&chan->vi->bw_update_lock);
817 if (ret)
818 dev_info(chan->vi->dev,
819 "WAR:Calculation not precise.Ignore BW request failure\n");
820 ret = vi4_v4l2_set_la(chan->vi->ndev, 0, 0);
821 if (ret)
822 dev_info(chan->vi->dev,
823 "WAR:Calculation not precise.Ignore LA failure\n");
824 return 0;
825}
826
827int vi4_channel_start_streaming(struct vb2_queue *vq, u32 count)
828{
829 struct tegra_channel *chan = vb2_get_drv_priv(vq);
830 struct media_pipeline *pipe = chan->video.entity.pipe;
831 int ret = 0, i;
832 unsigned long flags;
833 struct v4l2_ctrl *override_ctrl;
834
835 vi4_init(chan);
836 ret = media_entity_pipeline_start(&chan->video.entity, pipe);
837 if (ret < 0)
838 goto error_pipeline_start;
839
840 if (chan->bypass) {
841 ret = tegra_channel_set_stream(chan, true);
842 if (ret < 0)
843 goto error_set_stream;
844 return ret;
845 }
846
847 spin_lock_irqsave(&chan->capture_state_lock, flags);
848 chan->capture_state = CAPTURE_IDLE;
849 spin_unlock_irqrestore(&chan->capture_state_lock, flags);
850
851 for (i = 0; i < chan->valid_ports; i++) {
852 ret = tegra_channel_capture_setup(chan, i);
853 if (ret < 0)
854 goto error_capture_setup;
855 }
856
857 chan->sequence = 0;
858 tegra_channel_init_ring_buffer(chan);
859
860 /* disable override for vi mode */
861 override_ctrl = v4l2_ctrl_find(
862 &chan->ctrl_handler, V4L2_CID_OVERRIDE_ENABLE);
863 if (!chan->pg_mode) {
864 if (override_ctrl) {
865 ret = v4l2_ctrl_s_ctrl(override_ctrl, false);
866 if (ret < 0)
867 dev_err(&chan->video.dev,
868 "failed to disable override control\n");
869 } else
870 dev_err(&chan->video.dev,
871 "No override control\n");
872 }
873
874 /* Update clock and bandwidth based on the format */
875 ret = tegra_channel_update_clknbw(chan, 1);
876 if (ret)
877 goto error_capture_setup;
878
879 INIT_WORK(&chan->error_work, tegra_channel_error_worker);
880 INIT_WORK(&chan->status_work, tegra_channel_status_worker);
881
882 /* Start kthread to capture data to buffer */
883 chan->kthread_capture_start = kthread_run(
884 tegra_channel_kthread_capture_start,
885 chan, chan->video.name);
886 if (IS_ERR(chan->kthread_capture_start)) {
887 dev_err(&chan->video.dev,
888 "failed to run kthread for capture start\n");
889 ret = PTR_ERR(chan->kthread_capture_start);
890 goto error_capture_setup;
891 }
892
893 return 0;
894
895error_capture_setup:
896 if (!chan->pg_mode)
897 tegra_channel_set_stream(chan, false);
898error_set_stream:
899 media_entity_pipeline_stop(&chan->video.entity);
900error_pipeline_start:
901 vq->start_streaming_called = 0;
902 tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_QUEUED);
903
904 return ret;
905}
906
907int vi4_channel_stop_streaming(struct vb2_queue *vq)
908{
909 struct tegra_channel *chan = vb2_get_drv_priv(vq);
910 bool is_streaming = atomic_read(&chan->is_streaming);
911 int i;
912
913 for (i = 0; i < chan->valid_ports; i++) {
914 if (chan->vnc_id[i] == -1)
915 return 0;
916 }
917
918 cancel_work_sync(&chan->status_work);
919 cancel_work_sync(&chan->error_work);
920
921 if (!chan->bypass) {
922 tegra_channel_stop_kthreads(chan);
923 /* wait for last frame memory write ack */
924 if (is_streaming)
925 tegra_channel_capture_done(chan);
926 for (i = 0; i < chan->valid_ports; i++)
927 tegra_channel_notify_disable(chan, i);
928 /* free all the ring buffers */
929 free_ring_buffers(chan, chan->num_buffers);
930 /* dequeue buffers back to app which are in capture queue */
931 tegra_channel_queued_buf_done(chan, VB2_BUF_STATE_ERROR);
932 }
933
934 tegra_channel_set_stream(chan, false);
935 media_entity_pipeline_stop(&chan->video.entity);
936
937 if (!chan->bypass)
938 tegra_channel_update_clknbw(chan, 0);
939
940 return 0;
941}
942
943int tegra_vi4_power_on(struct tegra_mc_vi *vi)
944{
945 int ret;
946
947 ret = nvhost_module_busy(vi->ndev);
948 if (ret) {
949 dev_err(vi->dev, "%s:nvhost module is busy\n", __func__);
950 return ret;
951 }
952
953 ret = tegra_camera_emc_clk_enable();
954 if (ret)
955 goto err_emc_enable;
956
957 return 0;
958
959err_emc_enable:
960 nvhost_module_idle(vi->ndev);
961
962 return ret;
963}
964
965void tegra_vi4_power_off(struct tegra_mc_vi *vi)
966{
967 tegra_channel_ec_close(vi);
968 tegra_camera_emc_clk_disable();
969 nvhost_module_idle(vi->ndev);
970}
971
972int vi4_power_on(struct tegra_channel *chan)
973{
974 int ret = 0;
975 struct tegra_mc_vi *vi;
976 struct tegra_csi_device *csi;
977
978 vi = chan->vi;
979 csi = vi->csi;
980
981 /* Use chan->video as identifier of vi4 nvhost_module client
982 * since they are unique per channel
983 */
984 ret = nvhost_module_add_client(vi->ndev, &chan->video);
985 if (ret < 0)
986 return ret;
987
988 ret = tegra_vi4_power_on(vi);
989 if (ret < 0)
990 return ret;
991
992 if (atomic_add_return(1, &chan->power_on_refcnt) == 1) {
993 ret = tegra_channel_set_power(chan, 1);
994 if (ret < 0) {
995 dev_err(vi->dev, "Failed to power on subdevices\n");
996 return ret;
997 }
998 }
999
1000#if defined(CONFIG_TEGRA_CAMERA_RTCPU)
1001 ret = vi_capture_init(chan);
1002 if (ret < 0)
1003 return ret;
1004#endif
1005
1006 return 0;
1007}
1008
1009void vi4_power_off(struct tegra_channel *chan)
1010{
1011 int ret = 0;
1012 struct tegra_mc_vi *vi;
1013 struct tegra_csi_device *csi;
1014
1015 vi = chan->vi;
1016 csi = vi->csi;
1017
1018#if defined(CONFIG_TEGRA_CAMERA_RTCPU)
1019 vi_capture_shutdown(chan);
1020#endif
1021
1022 if (atomic_dec_and_test(&chan->power_on_refcnt)) {
1023 ret = tegra_channel_set_power(chan, 0);
1024 if (ret < 0)
1025 dev_err(vi->dev, "Failed to power off subdevices\n");
1026 }
1027
1028 tegra_vi4_power_off(vi);
1029 nvhost_module_remove_client(vi->ndev, &chan->video);
1030}
1031
1032static void tegra_channel_error_worker(struct work_struct *error_work)
1033{
1034 struct tegra_channel *chan;
1035
1036 chan = container_of(error_work, struct tegra_channel, error_work);
1037
1038 vi4_power_off(chan);
1039 tegra_channel_handle_error(chan);
1040}
1041
1042static void tegra_channel_notify_error_callback(void *client_data)
1043{
1044 struct tegra_channel *chan = (struct tegra_channel *)client_data;
1045
1046 spin_lock(&chan->capture_state_lock);
1047 if (chan->capture_state == CAPTURE_GOOD)
1048 chan->capture_state = CAPTURE_ERROR;
1049 else {
1050 spin_unlock(&chan->capture_state_lock);
1051 return;
1052 }
1053 spin_unlock(&chan->capture_state_lock);
1054
1055 schedule_work(&chan->error_work);
1056}
diff --git a/drivers/media/platform/tegra/camera/vi/vi4_fops.h b/drivers/media/platform/tegra/camera/vi/vi4_fops.h
new file mode 100644
index 000000000..4f48aca8d
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi4_fops.h
@@ -0,0 +1,37 @@
1/*
2 * Tegra Video Input 4 device common APIs
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
7 *
8 * Author: Frank Chen <frankc@nvidia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef __T186_VI_H__
16#define __T186_VI_H__
17
18int vi4_power_on(struct tegra_channel *chan);
19void vi4_power_off(struct tegra_channel *chan);
20int vi4_channel_start_streaming(struct vb2_queue *vq, u32 count);
21int vi4_channel_stop_streaming(struct vb2_queue *vq);
22int vi4_add_ctrls(struct tegra_channel *chan);
23void vi4_init_video_formats(struct tegra_channel *chan);
24long vi4_default_ioctl(struct file *file, void *fh,
25 bool use_prio, unsigned int cmd, void *arg);
26
27struct tegra_vi_fops vi4_fops = {
28 .vi_power_on = vi4_power_on,
29 .vi_power_off = vi4_power_off,
30 .vi_start_streaming = vi4_channel_start_streaming,
31 .vi_stop_streaming = vi4_channel_stop_streaming,
32 .vi_add_ctrls = vi4_add_ctrls,
33 .vi_init_video_formats = vi4_init_video_formats,
34 .vi_default_ioctl = vi4_default_ioctl,
35};
36
37#endif
diff --git a/drivers/media/platform/tegra/camera/vi/vi4_formats.h b/drivers/media/platform/tegra/camera/vi/vi4_formats.h
new file mode 100644
index 000000000..bbdbbab71
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi4_formats.h
@@ -0,0 +1,140 @@
1/*
2 * NVIDIA Tegra Video Input Device Driver VI4 formats
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Bhanu Murthy V <bmurthyv@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __VI4_FORMATS_H_
14#define __VI4_FORMATS_H_
15
16#include "camera/vi/core.h"
17
18/*
19 * These go into the VI_CHn_PIXFMT_FORMAT register bits 7:0
20 * Output pixel memory format for the VI channel.
21 */
22enum tegra_image_format {
23 TEGRA_IMAGE_FORMAT_T_L8 = 16,
24
25 TEGRA_IMAGE_FORMAT_T_R16_I = 32,
26 TEGRA_IMAGE_FORMAT_T_B5G6R5,
27 TEGRA_IMAGE_FORMAT_T_R5G6B5,
28 TEGRA_IMAGE_FORMAT_T_A1B5G5R5,
29 TEGRA_IMAGE_FORMAT_T_A1R5G5B5,
30 TEGRA_IMAGE_FORMAT_T_B5G5R5A1,
31 TEGRA_IMAGE_FORMAT_T_R5G5B5A1,
32 TEGRA_IMAGE_FORMAT_T_A4B4G4R4,
33 TEGRA_IMAGE_FORMAT_T_A4R4G4B4,
34 TEGRA_IMAGE_FORMAT_T_B4G4R4A4,
35 TEGRA_IMAGE_FORMAT_T_R4G4B4A4,
36
37 TEGRA_IMAGE_FORMAT_T_A8B8G8R8 = 64,
38 TEGRA_IMAGE_FORMAT_T_A8R8G8B8,
39 TEGRA_IMAGE_FORMAT_T_B8G8R8A8,
40 TEGRA_IMAGE_FORMAT_T_R8G8B8A8,
41 TEGRA_IMAGE_FORMAT_T_A2B10G10R10,
42 TEGRA_IMAGE_FORMAT_T_A2R10G10B10,
43 TEGRA_IMAGE_FORMAT_T_B10G10R10A2,
44 TEGRA_IMAGE_FORMAT_T_R10G10B10A2,
45
46 TEGRA_IMAGE_FORMAT_T_A8Y8U8V8 = 193,
47 TEGRA_IMAGE_FORMAT_T_V8U8Y8A8,
48
49 TEGRA_IMAGE_FORMAT_T_A2Y10U10V10 = 197,
50 TEGRA_IMAGE_FORMAT_T_V10U10Y10A2,
51
52 TEGRA_IMAGE_FORMAT_T_Y8_U8__Y8_V8 = 200,
53 TEGRA_IMAGE_FORMAT_T_Y8_V8__Y8_U8,
54
55 TEGRA_IMAGE_FORMAT_T_U8_Y8__V8_Y8 = 203,
56
57 TEGRA_IMAGE_FORMAT_T_T_V8_Y8__U8_Y8 = 223,
58 TEGRA_IMAGE_FORMAT_T_T_Y8__U8__V8_N444,
59 TEGRA_IMAGE_FORMAT_T_Y8__U8V8_N444,
60 TEGRA_IMAGE_FORMAT_T_Y8__V8U8_N444,
61 TEGRA_IMAGE_FORMAT_T_Y8__U8__V8_N422,
62 TEGRA_IMAGE_FORMAT_T_Y8__U8V8_N422,
63 TEGRA_IMAGE_FORMAT_T_Y8__V8U8_N422,
64 TEGRA_IMAGE_FORMAT_T_Y8__U8__V8_N420,
65 TEGRA_IMAGE_FORMAT_T_Y8__U8V8_N420,
66 TEGRA_IMAGE_FORMAT_T_Y8__V8U8_N420,
67
68 TEGRA_IMAGE_FORMAT_T_Y10__U10__V10_N422 = 240,
69 TEGRA_IMAGE_FORMAT_T_Y10__U10V10_N422,
70 TEGRA_IMAGE_FORMAT_T_Y10__V10U10_N422,
71 TEGRA_IMAGE_FORMAT_T_Y10__U10__V10_N420,
72 TEGRA_IMAGE_FORMAT_T_Y10__U10V10_N420,
73 TEGRA_IMAGE_FORMAT_T_Y10__V10U10_N420,
74
75 TEGRA_IMAGE_FORMAT_T_R16 = 248,
76 TEGRA_IMAGE_FORMAT_T_R32,
77 TEGRA_IMAGE_FORMAT_T_L16_F,
78 TEGRA_IMAGE_FORMAT_T_L32_F,
79
80 TEGRA_IMAGE_FORMAT_T_DPCM_RAW10 = 254,
81 TEGRA_IMAGE_FORMAT_T_DPCM_RAW12,
82};
83
84static const struct tegra_video_format vi4_video_formats[] = {
85 /* RAW 6: TODO */
86
87 /* RAW 7: TODO */
88
89 /* RAW 8 */
90 TEGRA_VIDEO_FORMAT(RAW8, 8, SRGGB8_1X8, 1, 1, T_L8,
91 RAW8, SRGGB8, "RGRG.. GBGB.."),
92 TEGRA_VIDEO_FORMAT(RAW8, 8, SGRBG8_1X8, 1, 1, T_L8,
93 RAW8, SGRBG8, "GRGR.. BGBG.."),
94 TEGRA_VIDEO_FORMAT(RAW8, 8, SGBRG8_1X8, 1, 1, T_L8,
95 RAW8, SGBRG8, "GBGB.. RGRG.."),
96 TEGRA_VIDEO_FORMAT(RAW8, 8, SBGGR8_1X8, 1, 1, T_L8,
97 RAW8, SBGGR8, "BGBG.. GRGR.."),
98
99 /* RAW 10 */
100 TEGRA_VIDEO_FORMAT(RAW10, 10, SRGGB10_1X10, 2, 1, T_R16_I,
101 RAW10, SRGGB10, "RGRG.. GBGB.."),
102 TEGRA_VIDEO_FORMAT(RAW10, 10, SGRBG10_1X10, 2, 1, T_R16_I,
103 RAW10, SGRBG10, "GRGR.. BGBG.."),
104 TEGRA_VIDEO_FORMAT(RAW10, 10, SGBRG10_1X10, 2, 1, T_R16_I,
105 RAW10, SGBRG10, "GBGB.. RGRG.."),
106 TEGRA_VIDEO_FORMAT(RAW10, 10, SBGGR10_1X10, 2, 1, T_R16_I,
107 RAW10, SBGGR10, "BGBG.. GRGR.."),
108
109 /* RAW 12 */
110 TEGRA_VIDEO_FORMAT(RAW12, 12, SRGGB12_1X12, 2, 1, T_R16_I,
111 RAW12, SRGGB12, "RGRG.. GBGB.."),
112 TEGRA_VIDEO_FORMAT(RAW12, 12, SGRBG12_1X12, 2, 1, T_R16_I,
113 RAW12, SGRBG12, "GRGR.. BGBG.."),
114 TEGRA_VIDEO_FORMAT(RAW12, 12, SGBRG12_1X12, 2, 1, T_R16_I,
115 RAW12, SGBRG12, "GBGB.. RGRG.."),
116 TEGRA_VIDEO_FORMAT(RAW12, 12, SBGGR12_1X12, 2, 1, T_R16_I,
117 RAW12, SBGGR12, "BGBG.. GRGR.."),
118
119 /* RGB888 */
120 TEGRA_VIDEO_FORMAT(RGB888, 24, RGB888_1X24, 4, 1, T_A8R8G8B8,
121 RGB888, ABGR32, "BGRA-8-8-8-8"),
122 TEGRA_VIDEO_FORMAT(RGB888, 24, RGB888_1X32_PADHI, 4, 1, T_A8B8G8R8,
123 RGB888, RGB32, "RGB-8-8-8-8"),
124
125 /* YUV422 */
126 TEGRA_VIDEO_FORMAT(YUV422, 16, UYVY8_1X16, 2, 1, T_U8_Y8__V8_Y8,
127 YUV422_8, UYVY, "YUV 4:2:2"),
128 TEGRA_VIDEO_FORMAT(YUV422, 16, UYVY8_1X16, 1, 1, T_Y8__V8U8_N422,
129 YUV422_8, NV16, "NV16"),
130 TEGRA_VIDEO_FORMAT(YUV422, 16, UYVY8_2X8, 2, 1, T_U8_Y8__V8_Y8,
131 YUV422_8, UYVY, "YUV 4:2:2 UYVY"),
132 TEGRA_VIDEO_FORMAT(YUV422, 16, VYUY8_2X8, 2, 1, T_T_V8_Y8__U8_Y8,
133 YUV422_8, VYUY, "YUV 4:2:2 VYUY"),
134 TEGRA_VIDEO_FORMAT(YUV422, 16, YUYV8_2X8, 2, 1, T_Y8_U8__Y8_V8,
135 YUV422_8, YUYV, "YUV 4:2:2 YUYV"),
136 TEGRA_VIDEO_FORMAT(YUV422, 16, YVYU8_2X8, 2, 1, T_Y8_V8__Y8_U8,
137 YUV422_8, YVYU, "YUV 4:2:2 YVYU"),
138};
139
140#endif
diff --git a/drivers/media/platform/tegra/camera/vi/vi4_registers.h b/drivers/media/platform/tegra/camera/vi/vi4_registers.h
new file mode 100644
index 000000000..588ebb324
--- /dev/null
+++ b/drivers/media/platform/tegra/camera/vi/vi4_registers.h
@@ -0,0 +1,272 @@
1/*
2 * drivers/media/platform/tegra/camera/vi/vi4_registers.h
3 *
4 * Tegra 18x VI register offsets
5 *
6 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __VI4_REGISTERS_H__
22#define __VI4_REGISTERS_H__
23
24/* VI registers. Start from 0x0 */
25#define VI_STREAMS (6)
26#define VIRTUAL_CHANNELS (4)
27#define VI4_CHANNEL_OFFSET 0x10000
28
29#define CFG_INTERRUPT_STATUS 0x44
30#define CFG_INTERRUPT_MASK 0x48
31#define VGP6_INT_MASK (0x1 << 29)
32#define VGP5_INT_MASK (0x1 << 28)
33#define VGP4_INT_MASK (0x1 << 27)
34#define VGP3_INT_MASK (0x1 << 26)
35#define VGP2_INT_MASK (0x1 << 25)
36#define VGP1_INT_MASK (0x1 << 24)
37#define HOST_PKTINJECT_STALL_ERR_MASK (0x1 << 7)
38#define CSIMUX_FIFO_OVFL_ERR_MASK (0x1 << 6)
39#define ATOMP_PACKER_OVFL_ERR_MASK (0x1 << 5)
40#define FMLITE_BUF_OVFL_ERR_MASK (0x1 << 4)
41#define NOTIFY_FIFO_OVFL_ERR_MASK (0x1 << 3)
42#define ISPBUFA_ERR_MASK (0x1 << 0)
43
44#define CFG_PWM_HIGH_PULSE 0x50
45#define PWM_HIGH_PULSE (0xffffffff << 0)
46
47#define CSIMUX_CONFIG_STREAM_0 0x424
48#define CSIMUX_CONFIG_STREAM_1 0x428
49#define CSIMUX_CONFIG_STREAM_2 0x42C
50#define CSIMUX_CONFIG_STREAM_3 0x430
51#define CSIMUX_CONFIG_STREAM_4 0x434
52#define CSIMUX_CONFIG_STREAM_5 0x438
53#define FRAMEIDGEN (0xf << 26)
54#define STICKYFAULT (0x1 << 25)
55#define VPR (0x1 << 24)
56#define SRESET (0x1 << 23)
57#define QBLOCK (0x1 << 22)
58#define FEINJECT (0x1 << 21)
59#define FESHORTTIMER (0x1 << 20)
60#define FEMAXTIME (0xffff << 4)
61#define WT (0xf << 0)
62
63#define NOTIFY_FIFO_TAG_0 0x4000
64#define NOTIFY_FRAME_ID (0xffff << 16)
65#define NOTIFY_CHANNEL (0xff << 8)
66#define NOTIFY_CHANNEL_SHIFT (8)
67#define NOTIFY_TAG (0x1f << 1)
68#define NOTIFY_TAG_SHIFT (1)
69#define NOTIFY_VALID (0x1 << 0)
70
71#define TAG_FS 0
72#define TAG_FE 1
73#define TAG_CSIMUX_FRAME 2
74#define TAG_CSIMUX_STREAM 3
75#define TAG_CHANSEL_PXL_SOF 4
76#define TAG_CHANSEL_PXL_EOF 5
77#define TAG_CHANSEL_EMBED_SOF 6
78#define TAG_CHANSEL_EMBED_EOF 7
79#define TAG_CHANSEL_NLINES 8
80#define TAG_CHANSEL_FAULT 9
81#define TAG_CHANSEL_FAULT_FE 10
82#define TAG_CHANSEL_NOMATCH 11
83#define TAG_CHANSEL_COLLISION 12
84#define TAG_CHANSEL_SHORT_FRAME 13
85#define TAG_CHANSEL_LOAD_FRAMED 14
86#define TAG_ATOMP_PACKER_OVERFLOW 15
87#define TAG_ATOMP_FS 16
88#define TAG_ATOMP_FE 17
89#define TAG_ATOMP_FRAME_DONE 18
90#define TAG_ATOMP_EMB_DATA_DONE 19
91#define TAG_ATOMP_FRAME_NLINES_DONE 20
92#define TAG_ATOMP_FRAME_TRUNCATED 21
93#define TAG_ATOMP_FRAME_TOSSED 22
94#define TAG_ATOMP_PDAF_DATA_DONE 23
95#define TAG_ISPBUF_FIFO_OVERFLOW 26
96#define TAG_ISPBUF_FS 27
97#define TAG_ISPBUF_FE 28
98#define TAG_VGP0_DONE 29
99#define TAG_VGP1_DONE 30
100#define TAG_FMLITE_DONE 31
101
102#define NOTIFY_FIFO_TIMESTAMP_0 0x4004
103#define NOTIFY_TIMESTAMP (0xffffffff << 0)
104
105#define NOTIFY_FIFO_DATA_0 0x4008
106#define NOTIFY_DATA (0xffffffff << 0)
107
108#define NOTIFY_TAG_CLASSIFY_0 0x6000
109#define NOTIFY_TAG_CLASSIFY_1 0x6004
110#define NOTIFY_TAG_CLASSIFY_2 0x6008
111#define NOTIFY_TAG_CLASSIFY_3 0x600c
112#define NOTIFY_TAG_CLASSIFY_4 0x6010
113#define STREAM5_FEINJECT_VC (0xf << 20)
114#define STREAM4_FEINJECT_VC (0xf << 16)
115#define STREAM3_FEINJECT_VC (0xf << 12)
116#define STREAM2_FEINJECT_VC (0xf << 8)
117#define STREAM1_FEINJECT_VC (0xf << 4)
118#define STREAM0_FEINJECT_VC (0xf << 0)
119
120#define NOTIFY_FIFO_OCCUPANCY_0 0x6014
121#define NOTIFY_MAX (0x3ff << 20)
122#define NOTIFY_CURRENT (0x3ff << 10)
123#define NOTIFY_CURRENT_SHIFT 10
124#define NOTIFY_SIZE (0x3ff << 0)
125
126/* VI_CH registers. Start from 0x10000, offset 0x10000 */
127#define CHANNEL_COMMAND 0x004
128#define WR_ACT_SEL (0x1 << 5)
129#define RD_MUX_SEL (0x1 << 4)
130#define AUTOLOAD (0x1 << 1)
131#define LOAD (0x1 << 0)
132
133#define CONTROL 0x01c
134#define SPARE (0xffff << 16)
135#define POST_RUNAWAY_EMBED (0x1 << 4)
136#define POST_RUNAWAY_PIXEL (0x1 << 3)
137#define EARLY_ABORT (0x1 << 2)
138#define SINGLESHOT (0x1 << 1)
139#define MATCH_STATE_EN (0x1 << 0)
140
141#define MATCH 0x020
142#define STREAM (0x3f << 14)
143#define STREAM_SHIFT (14)
144#define STREAM_MASK (0x3f << 8)
145#define VIRTUAL_CHANNEL (0xf << 4)
146#define VIRTUAL_CHANNEL_SHIFT (4)
147#define VIRTUAL_CHANNEL_MASK (0xf << 0)
148
149#define MATCH_DATATYPE 0x024
150#define DATATYPE (0x3f << 6)
151#define DATATYPE_SHIFT (6)
152#define DATATYPE_MASK (0x3f << 0)
153#define DATATYPE_MASK_SHIFT (0)
154
155#define MATCH_FRAMEID 0x028
156#define FRAMEID (0xffff << 16)
157#define FRAMEID_SHIFT (16)
158#define FRAMEID_MASK (0xffff << 0)
159
160#define DT_OVERRIDE 0x02c
161#define OVRD_DT (0x3f << 1)
162#define DT_OVRD_EN (0x1 << 0)
163
164#define FRAME_X 0x030
165#define CROP_X 0x04c
166#define OUT_X 0x058
167#define WIDTH (0xffff < 0)
168
169#define FRAME_Y 0x034
170#define CROP_Y 0x054
171#define OUT_Y 0x05c
172#define HEIGHT (0xffff < 0)
173
174#define EMBED_X 0x038
175#define MAX_BYTES (0x3ffff < 0)
176
177#define EMBED_Y 0x03c
178#define SKIP_Y 0x050
179#define LINES (0xffff < 0)
180/* for EMBED_Y only */
181#define EXPECT (0x1 << 24)
182
183#define LINE_TIMER 0x044
184#define LINE_TIMER_EN (0x1 << 25)
185#define PERIODIC (0x1 << 24)
186#define TRIPLINE (0xffff << 0)
187
188#define SKIP_X 0x048
189#define PACKETS (0x1fff << 0)
190
191#define NOTIFY_MASK 0x060
192#define MASK_DTYPE_MISMATCH (0x1 << 31)
193#define MASK_EMBED_INFRINGE (0x1 << 22)
194#define MASK_EMBED_LONG_LINE (0x1 << 21)
195#define MASK_EMBED_SPURIOUS (0x1 << 20)
196#define MASK_EMBED_RUNAWAY (0x1 << 19)
197#define MASK_EMBED_MISSING_LE (0x1 << 18)
198#define MASK_EMBED_EOF (0x1 << 17)
199#define MASK_EMBED_SOF (0x1 << 16)
200#define MASK_PIXEL_LINE_TIMER (0x1 << 7)
201#define MASK_PIXEL_SHORT_LINE (0x1 << 6)
202#define MASK_PIXEL_LONG_LINE (0x1 << 5)
203#define MASK_PIXEL_SPURIOUS (0x1 << 4)
204#define MASK_PIXEL_RUNAWAY (0x1 << 3)
205#define MASK_PIXEL_MISSING_LE (0x1 << 2)
206#define MASK_PIXEL_EOF (0x1 << 1)
207#define MASK_PIXEL_SOF (0x1 << 0)
208
209#define NOTIFY_MASK_XCPT 0x064
210#define MASK_NOMATCH (0x1 << 9)
211#define MASK_EMBED_OPEN_LINE (0x1 << 8)
212#define MASK_PIXEL_OPEN_LINE (0x1 << 7)
213#define MASK_FORCE_FE (0x1 << 6)
214#define MASK_STALE_FRAME (0x1 << 5)
215#define MASK_COLLISION (0x1 << 4)
216#define MASK_EMPTY_FRAME (0x1 << 3)
217#define MASK_EMBED_SHORT_FRAME (0x1 << 2)
218#define MASK_PIXEL_SHORT_FRAME (0x1 << 1)
219#define MASK_LOAD_FRAMED (0x1 << 0)
220
221#define FRAME_COUNT 0x06c
222
223#define PIXFMT_ENABLE 0x080
224#define PDAF_EN (0x1 << 2)
225#define COMPAND_EN (0x1 << 1)
226#define PIXFMT_EN (0x1 << 0)
227
228#define PIXFMT_FORMAT 0x084
229#define FORMAT (0xff << 0)
230/* refer to enum tegra_image_format in core.h */
231
232#define PIXFMT_WIDE 0x088
233#define ENDIAN_BIG (0x0 << 1)
234#define ENDIAN_LITTLE (0x1 << 1)
235#define PIXFMT_WIDE_EN (0x1 << 0)
236
237#define DPCM_STRIP 0x0b8
238#define OVERFETCH (0x1fff < 16)
239#define STRIP_WIDTH (0x1fff < 0)
240
241#define ATOMP_DPCM_CHUNK 0x0ec
242#define CHUNK_OFFSET (0x3ffff << 0)
243
244#define ATOMP_SURFACE_OFFSET0 0x0e0
245#define ATOMP_SURFACE_OFFSET1 0x0f0
246#define ATOMP_SURFACE_OFFSET2 0x0fc
247#define ATOMP_EMB_SURFACE_OFFSET0 0x108
248#define SURFACE_OFFSET (0xffffffff << 0)
249
250#define ATOMP_SURFACE_OFFSET0_H 0x0e4
251#define ATOMP_SURFACE_OFFSET1_H 0x0f4
252#define ATOMP_SURFACE_OFFSET2_H 0x100
253#define ATOMP_EMB_SURFACE_OFFSET0_H 0x10c
254#define SURFACE_OFFSET_HI (0xff << 0)
255
256#define ATOMP_SURFACE_STRIDE0 0x0e8
257#define ATOMP_SURFACE_STRIDE1 0x0f8
258#define ATOMP_SURFACE_STRIDE2 0x104
259#define ATOMP_EMB_SURFACE_STRIDE0 0x110
260#define SURFACE_STRIDE (0x3ffff << 0)
261#define ATOMP_RESERVE 0x120
262
263#define ISPBUFA 0x134
264#define ISPBUFA_EN (0x1 << 0)
265
266#define ISPBUFA_ERROR 0x1000
267#define FIFO_OVERFLOW (0x1 << 0)
268
269#define FMLITE_ERROR 0x313c
270#define NOTIFY_ERROR 0x6020
271
272#endif /* __VI4_REGISTERS_H__ */
diff --git a/drivers/media/platform/tegra/mipical/Kconfig b/drivers/media/platform/tegra/mipical/Kconfig
new file mode 100644
index 000000000..e00659b2b
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/Kconfig
@@ -0,0 +1,11 @@
1config TEGRA_MIPI_CAL
2 depends on TEGRA_DC || TEGRA_CAMERA_PLATFORM
3 bool "Enable MIPI Cal driver"
4 default y
5 select REGMAP
6 select REGMAP_MMIO
7 help
8 Provides an interfaces to do MIPI calibration for both DSI and CSI blocks.
9 You will always want this enabled if you are using either Camera or Display.
10 Disabling this can cause issues for drivers that depend on it being present.
11 Leaving this on is harmless even if no drivers that need it are enabled.
diff --git a/drivers/media/platform/tegra/mipical/Makefile b/drivers/media/platform/tegra/mipical/Makefile
new file mode 100644
index 000000000..ffd996e09
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/Makefile
@@ -0,0 +1,6 @@
1GCOV_PROFILE := y
2#
3# Makefile for Mipical driver
4#
5obj-$(CONFIG_TEGRA_MIPI_CAL) += mipi_cal.o
6obj-$(CONFIG_TEGRA_MIPI_CAL) += vmipi/vmipi.o
diff --git a/drivers/media/platform/tegra/mipical/mipi_cal.c b/drivers/media/platform/tegra/mipical/mipi_cal.c
new file mode 100644
index 000000000..d53af8ae3
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/mipi_cal.c
@@ -0,0 +1,1096 @@
1/*
2 * mipi_cal.c
3 *
4 * Copyright (c) 2016-2017, NVIDIA CORPORATION, All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16#include <linux/device.h>
17#include <linux/clk.h>
18#include <linux/delay.h>
19#include <linux/of_platform.h>
20#include <linux/regmap.h>
21#include <linux/io.h>
22#include <linux/slab.h>
23#include <linux/platform_device.h>
24#include <linux/module.h>
25#include <linux/export.h>
26#include <linux/reset.h>
27#include <linux/string.h>
28#include <linux/debugfs.h>
29#include <linux/clk/tegra.h>
30#include <linux/pm.h>
31#include <linux/miscdevice.h>
32#include <linux/fs.h>
33#include <linux/uaccess.h>
34
35#include <soc/tegra/fuse.h>
36#include <soc/tegra/tegra_powergate.h>
37#include <linux/tegra_prod.h>
38#include <uapi/misc/tegra_mipi_ioctl.h>
39
40#include "registers.h"
41#include "mipi_cal.h"
42#include "vmipi/vmipi.h"
43
44#define DRV_NAME "tegra_mipi_cal"
45#define MIPI_CAL_TIMEOUT_MSEC 500
46
47struct tegra_mipi_bias {
48 /* BIAS_PAD_CFG0 */
49 u8 pad_pdvclamp;
50 u8 e_vclamp_ref;
51 /* BIAS_PAD_CFG1 */
52 u8 pad_driv_up_ref;
53 u8 pad_driv_dn_ref;
54 /* BIAS_PAD_CFG2 */
55 u8 pad_vclamp_level;
56 u8 pad_vauxp_level;
57};
58
59struct tegra_mipi_prod_csi {
60 struct tegra_mipi_bias bias_csi;
61 u8 overide_x;
62 u8 termos_x;
63 u8 termos_x_clk;
64};
65
66struct tegra_mipi_prod_dsi {
67 struct tegra_mipi_bias bias_dsi;
68 u8 overide_x;
69 u8 hspdos_x;
70 u8 hspuos_x;
71 u8 termos_x;
72 u8 clk_overide_x;
73 u8 clk_hspdos_x;
74 u8 clk_hspuos_x;
75 u8 clk_hstermos_x;
76};
77
78struct tegra_mipi;
79struct tegra_mipi {
80 struct device *dev;
81 struct clk *mipi_cal_clk;
82 struct clk *mipi_cal_fixed;
83 struct reset_control *rst;
84 struct regmap *regmap;
85 struct mutex lock;
86 /* Legacy way of storing mipical reg config */
87 struct tegra_mipi_prod_csi *prod_csi;
88 struct tegra_mipi_prod_dsi *prod_dsi;
89 /* If use tegra_prod framework */
90 struct tegra_prod *prod_gr_csi;
91 struct tegra_prod *prod_gr_dsi;
92 const struct tegra_mipi_soc *soc;
93 void __iomem *io;
94 atomic_t refcount;
95 struct miscdevice misc_dev;
96};
97
98static struct tegra_mipi *mipi;
99static const struct regmap_config t210_mipi_cal_regmap_config = {
100 .reg_bits = 32,
101 .reg_stride = 4,
102 .val_bits = 32,
103 .cache_type = REGCACHE_NONE,
104 .fast_io = 1,
105};
106
107#define ADDR(x) (x + mipi->soc->addr_offset)
108#define dump_register(nm) \
109{ \
110 .name = #nm, \
111 .offset = nm, \
112}
113struct tegra_mipi_soc {
114 int powergate_id;
115 unsigned int total_dsilanes;
116 unsigned int total_cillanes;
117 char addr_offset;
118 char ppsb_war;
119 int (*pad_enable)(struct tegra_mipi *mipi);
120 int (*pad_disable)(struct tegra_mipi *mipi);
121 int (*calibrate)(struct tegra_mipi *mipi, int lanes);
122 int (*parse_cfg)(struct platform_device *pdev, struct tegra_mipi *mipi);
123 u8 virtual_dev;
124};
125
126static int mipical_write(struct regmap *map,
127 unsigned int reg, unsigned int val)
128{
129 int ret, rb_val;
130
131 ret = regmap_write(map, reg, val);
132 if (mipi->soc->ppsb_war)
133 /* Read back register to make sure that register writes completed */
134 regmap_read(map, reg, &rb_val);
135
136 return ret;
137}
138
139static int mipical_update_bits(struct regmap *map, unsigned int reg,
140 unsigned int mask, unsigned int val)
141{
142 int ret, rb_val;
143
144 ret = regmap_update_bits(map, reg, mask, val);
145 if (mipi->soc->ppsb_war)
146 /* Read back register to make sure that register writes completed */
147 regmap_read(map, reg, &rb_val);
148
149 return ret;
150}
151static int tegra_mipi_clk_enable(struct tegra_mipi *mipi)
152{
153 int err;
154
155 err = tegra_unpowergate_partition(mipi->soc->powergate_id);
156 if (err) {
157 dev_err(mipi->dev, "Fail to unpowergate SOR\n");
158 return err;
159 }
160
161 err = clk_prepare_enable(mipi->mipi_cal_fixed);
162 if (err) {
163 dev_err(mipi->dev, "Fail to enable uart_mipi_cal clk\n");
164 goto err_fixed_clk;
165 }
166 mdelay(1);
167 err = clk_prepare_enable(mipi->mipi_cal_clk);
168 if (err) {
169 dev_err(mipi->dev, "Fail to enable mipi_cal clk\n");
170 goto err_mipi_cal_clk;
171 }
172 return 0;
173
174err_mipi_cal_clk:
175 clk_disable_unprepare(mipi->mipi_cal_fixed);
176err_fixed_clk:
177 tegra_powergate_partition(mipi->soc->powergate_id);
178
179 return err;
180}
181
182static void tegra_mipi_clk_disable(struct tegra_mipi *mipi)
183{
184 clk_disable_unprepare(mipi->mipi_cal_clk);
185 clk_disable_unprepare(mipi->mipi_cal_fixed);
186 tegra_powergate_partition(mipi->soc->powergate_id);
187}
188
189static void tegra_mipi_print(struct tegra_mipi *mipi) __maybe_unused;
190static void tegra_mipi_print(struct tegra_mipi *mipi)
191{
192 int val;
193 unsigned long rate;
194#define pr_reg(a) \
195 do { \
196 regmap_read(mipi->regmap, ADDR(a), &val); \
197 dev_info(mipi->dev, "%-30s %#04x %#010x\n", \
198 #a, a + mipi->soc->addr_offset, val); \
199 } while (0)
200
201 rate = clk_get_rate(mipi->mipi_cal_fixed);
202 dev_dbg(mipi->dev, "Fixed clk %luMHz\n", rate/1000000);
203
204 pr_reg(MIPI_CAL_CTRL);
205 pr_reg(CIL_MIPI_CAL_STATUS);
206 pr_reg(CIL_MIPI_CAL_STATUS_2);
207 pr_reg(CILA_MIPI_CAL_CONFIG);
208 pr_reg(CILB_MIPI_CAL_CONFIG);
209 pr_reg(CILC_MIPI_CAL_CONFIG);
210 pr_reg(CILD_MIPI_CAL_CONFIG);
211 pr_reg(CILE_MIPI_CAL_CONFIG);
212 pr_reg(CILF_MIPI_CAL_CONFIG);
213 pr_reg(DSIA_MIPI_CAL_CONFIG);
214 pr_reg(DSIB_MIPI_CAL_CONFIG);
215 pr_reg(DSIC_MIPI_CAL_CONFIG);
216 pr_reg(DSID_MIPI_CAL_CONFIG);
217 pr_reg(MIPI_BIAS_PAD_CFG0);
218 pr_reg(MIPI_BIAS_PAD_CFG1);
219 pr_reg(MIPI_BIAS_PAD_CFG2);
220 pr_reg(DSIA_MIPI_CAL_CONFIG_2);
221 pr_reg(DSIB_MIPI_CAL_CONFIG_2);
222 pr_reg(DSIC_MIPI_CAL_CONFIG_2);
223 pr_reg(DSID_MIPI_CAL_CONFIG_2);
224#undef pr_reg
225}
226static int tegra_mipi_wait(struct tegra_mipi *mipi, int lanes)
227{
228 unsigned long timeout;
229 int val;
230
231 mipical_write(mipi->regmap, ADDR(CIL_MIPI_CAL_STATUS), 0xffffffff);
232 mipical_write(mipi->regmap, ADDR(CIL_MIPI_CAL_STATUS_2), 0xffffffff);
233 mipical_update_bits(mipi->regmap, ADDR(MIPI_CAL_CTRL), STARTCAL, 0x1);
234
235 timeout = jiffies + msecs_to_jiffies(MIPI_CAL_TIMEOUT_MSEC);
236 while (time_before(jiffies, timeout)) {
237 regmap_read(mipi->regmap, ADDR(CIL_MIPI_CAL_STATUS), &val);
238 if (((val & lanes) == lanes) && ((val & CAL_ACTIVE) == 0))
239 return 0;
240 usleep_range(10, 50);
241 }
242 /* Sometimes there is false timeout. Sleep past the timeout and did
243 * not check the status again.
244 * Later status register dump shows no timeout.
245 * Add another check here in case sleep past the timeout.
246 */
247 regmap_read(mipi->regmap, ADDR(CIL_MIPI_CAL_STATUS), &val);
248 if (((val & lanes) == lanes) && ((val & CAL_ACTIVE) == 0))
249 return 0;
250 dev_err(mipi->dev, "Mipi cal timeout,val:%x, lanes:%x\n", val, lanes);
251 tegra_mipi_print(mipi);
252 return -ETIMEDOUT;
253
254}
255
256static int tegra_mipi_apply_bias_prod(struct regmap *reg,
257 struct tegra_mipi_bias *bias)
258{
259 int ret;
260 unsigned int val;
261
262 val = (bias->pad_pdvclamp << PDVCLAMP_SHIFT) |
263 (bias->e_vclamp_ref << E_VCLAMP_REF_SHIFT);
264 ret = mipical_write(reg, ADDR(MIPI_BIAS_PAD_CFG0), val);
265 if (ret)
266 return ret;
267 val = (bias->pad_driv_up_ref << PAD_DRIV_UP_REF_SHIFT) |
268 (bias->pad_driv_dn_ref << PAD_DRIV_DN_REF_SHIFT);
269 ret = mipical_write(reg, ADDR(MIPI_BIAS_PAD_CFG1), val);
270 if (ret)
271 return ret;
272 val = (bias->pad_vclamp_level << PAD_VCLAMP_LEVEL_SHIFT) |
273 (bias->pad_vauxp_level << PAD_VAUXP_LEVEL_SHIFT);
274 ret = mipical_write(reg, ADDR(MIPI_BIAS_PAD_CFG2), val);
275
276 return ret;
277}
278static void tegra_mipi_apply_csi_prod(struct regmap *reg,
279 struct tegra_mipi_prod_csi *prod_csi,
280 int lanes)
281{
282 int val;
283
284 tegra_mipi_apply_bias_prod(reg, &prod_csi->bias_csi);
285 val = (prod_csi->termos_x << TERMOSA_SHIFT) |
286 (prod_csi->termos_x_clk << TERMOSA_CLK_SHIFT);
287
288 if (lanes & CSIA)
289 mipical_write(reg, ADDR(CILA_MIPI_CAL_CONFIG), val);
290 if (lanes & CSIB)
291 mipical_write(reg, ADDR(CILB_MIPI_CAL_CONFIG), val);
292 if (lanes & CSIC)
293 mipical_write(reg, ADDR(CILC_MIPI_CAL_CONFIG), val);
294 if (lanes & CSID)
295 mipical_write(reg, ADDR(CILD_MIPI_CAL_CONFIG), val);
296 if (lanes & CSIE)
297 mipical_write(reg, ADDR(CILE_MIPI_CAL_CONFIG), val);
298 if (lanes & CSIF)
299 mipical_write(reg, ADDR(CILF_MIPI_CAL_CONFIG), val);
300}
301
302static void tegra_mipi_apply_dsi_prod(struct regmap *reg,
303 struct tegra_mipi_prod_dsi *prod_dsi,
304 int lanes)
305{
306 int val, clk_val;
307
308 tegra_mipi_apply_bias_prod(reg, &prod_dsi->bias_dsi);
309 val = (prod_dsi->hspuos_x << HSPUOSDSIA_SHIFT) |
310 (prod_dsi->termos_x << TERMOSDSIA_SHIFT);
311 clk_val = (prod_dsi->clk_hspuos_x << HSCLKPUOSDSIA_SHIFT) |
312 (prod_dsi->clk_hstermos_x << HSCLKTERMOSDSIA_SHIFT);
313 if (lanes & DSIA) {
314 mipical_write(reg, ADDR(DSIA_MIPI_CAL_CONFIG), val);
315 mipical_write(reg, ADDR(DSIA_MIPI_CAL_CONFIG_2), clk_val);
316 }
317 if (lanes & DSIB) {
318 mipical_write(reg, ADDR(DSIB_MIPI_CAL_CONFIG), val);
319 mipical_write(reg, ADDR(DSIB_MIPI_CAL_CONFIG_2), clk_val);
320 }
321 if (lanes & DSIC) {
322 mipical_write(reg, ADDR(DSIC_MIPI_CAL_CONFIG), val);
323 mipical_write(reg, ADDR(DSIC_MIPI_CAL_CONFIG_2), clk_val);
324 }
325 if (lanes & DSID) {
326 mipical_write(reg, ADDR(DSID_MIPI_CAL_CONFIG), val);
327 mipical_write(reg, ADDR(DSID_MIPI_CAL_CONFIG_2), clk_val);
328 }
329
330}
331
332static int _t18x_tegra_mipi_bias_pad_enable(struct tegra_mipi *mipi)
333{
334 if (atomic_read(&mipi->refcount) < 0) {
335 WARN_ON(1);
336 return -EINVAL;
337 }
338 if (atomic_inc_return(&mipi->refcount) == 1) {
339 tegra_mipi_clk_enable(mipi);
340 mipical_update_bits(mipi->regmap, ADDR(MIPI_BIAS_PAD_CFG0),
341 PDVCLAMP, 0 << PDVCLAMP_SHIFT);
342 mipical_update_bits(mipi->regmap, ADDR(MIPI_BIAS_PAD_CFG2),
343 PDVREG, 0 << PDVREG_SHIFT);
344 }
345 return 0;
346}
347
348static int _t18x_tegra_mipi_bias_pad_disable(struct tegra_mipi *mipi)
349{
350 if (atomic_read(&mipi->refcount) < 1) {
351 WARN_ON(1);
352 return -EINVAL;
353 }
354 if (atomic_dec_return(&mipi->refcount) == 0) {
355 mipical_update_bits(mipi->regmap, ADDR(MIPI_BIAS_PAD_CFG0),
356 PDVCLAMP, 1 << PDVCLAMP_SHIFT);
357 mipical_update_bits(mipi->regmap, ADDR(MIPI_BIAS_PAD_CFG2),
358 PDVREG, 1 << PDVREG_SHIFT);
359 tegra_mipi_clk_disable(mipi);
360 }
361 return 0;
362}
363
364static int _t21x_tegra_mipi_bias_pad_enable(struct tegra_mipi *mipi)
365{
366 if (atomic_read(&mipi->refcount) < 0) {
367 WARN_ON(1);
368 return -EINVAL;
369 }
370 if (atomic_inc_return(&mipi->refcount) == 1) {
371 tegra_mipi_clk_enable(mipi);
372 return mipical_update_bits(mipi->regmap,
373 ADDR(MIPI_BIAS_PAD_CFG2), PDVREG, 0);
374 }
375 return 0;
376}
377
378int tegra_mipi_bias_pad_enable(void)
379{
380 if (!mipi)
381 return -EPROBE_DEFER;
382 dev_dbg(mipi->dev, "%s", __func__);
383
384 if (mipi->soc->pad_enable)
385 return mipi->soc->pad_enable(mipi);
386 else
387 return 0;
388}
389EXPORT_SYMBOL(tegra_mipi_bias_pad_enable);
390
391static int _t21x_tegra_mipi_bias_pad_disable(struct tegra_mipi *mipi)
392{
393 if (atomic_read(&mipi->refcount) < 1) {
394 WARN_ON(1);
395 return -EINVAL;
396 }
397 if (atomic_dec_return(&mipi->refcount) == 0) {
398 mipical_update_bits(mipi->regmap,
399 ADDR(MIPI_BIAS_PAD_CFG2), PDVREG, PDVREG);
400 tegra_mipi_clk_disable(mipi);
401 }
402 return 0;
403}
404
405int tegra_mipi_bias_pad_disable(void)
406{
407 if (!mipi)
408 return -ENODEV;
409 dev_dbg(mipi->dev, "%s", __func__);
410
411 if (mipi->soc->pad_disable)
412 return mipi->soc->pad_disable(mipi);
413 else
414 return 0;
415}
416EXPORT_SYMBOL(tegra_mipi_bias_pad_disable);
417
418static void select_lanes(struct tegra_mipi *mipi, int lanes)
419{
420 mipical_update_bits(mipi->regmap, ADDR(CILA_MIPI_CAL_CONFIG), SELA,
421 ((lanes & CSIA) != 0 ? SELA : 0));
422 mipical_update_bits(mipi->regmap, ADDR(CILB_MIPI_CAL_CONFIG), SELA,
423 ((lanes & CSIB) != 0 ? SELA : 0));
424 mipical_update_bits(mipi->regmap, ADDR(CILC_MIPI_CAL_CONFIG), SELA,
425 ((lanes & CSIC) != 0 ? SELA : 0));
426 mipical_update_bits(mipi->regmap, ADDR(CILD_MIPI_CAL_CONFIG), SELA,
427 ((lanes & CSID) != 0 ? SELA : 0));
428 mipical_update_bits(mipi->regmap, ADDR(CILE_MIPI_CAL_CONFIG), SELA,
429 ((lanes & CSIE) != 0 ? SELA : 0));
430 mipical_update_bits(mipi->regmap, ADDR(CILF_MIPI_CAL_CONFIG), SELA,
431 ((lanes & CSIF) != 0 ? SELA : 0));
432
433 mipical_update_bits(mipi->regmap, ADDR(DSIA_MIPI_CAL_CONFIG), SELDSIA,
434 ((lanes & DSIA) != 0 ? SELDSIA : 0));
435 mipical_update_bits(mipi->regmap, ADDR(DSIB_MIPI_CAL_CONFIG), SELDSIA,
436 ((lanes & DSIB) != 0 ? SELDSIA : 0));
437 mipical_update_bits(mipi->regmap, ADDR(DSIC_MIPI_CAL_CONFIG), SELDSIA,
438 ((lanes & DSIC) != 0 ? SELDSIA : 0));
439 mipical_update_bits(mipi->regmap, ADDR(DSID_MIPI_CAL_CONFIG), SELDSIA,
440 ((lanes & DSID) != 0 ? SELDSIA : 0));
441 mipical_update_bits(mipi->regmap, ADDR(DSIA_MIPI_CAL_CONFIG_2),
442 CLKSELDSIA, ((lanes & DSIA) != 0 ? CLKSELDSIA : 0));
443 mipical_update_bits(mipi->regmap, ADDR(DSIB_MIPI_CAL_CONFIG_2),
444 CLKSELDSIA, ((lanes & DSIB) != 0 ? CLKSELDSIA : 0));
445 mipical_update_bits(mipi->regmap, ADDR(DSIC_MIPI_CAL_CONFIG_2),
446 CLKSELDSIA, ((lanes & DSIC) != 0 ? CLKSELDSIA : 0));
447 mipical_update_bits(mipi->regmap, ADDR(DSID_MIPI_CAL_CONFIG_2),
448 CLKSELDSIA, ((lanes & DSID) != 0 ? CLKSELDSIA : 0));
449}
450
451static void clear_all(struct tegra_mipi *mipi)
452{
453 mipical_write(mipi->regmap, ADDR(CILA_MIPI_CAL_CONFIG), 0);
454 mipical_write(mipi->regmap, ADDR(CILB_MIPI_CAL_CONFIG), 0);
455 mipical_write(mipi->regmap, ADDR(CILC_MIPI_CAL_CONFIG), 0);
456 mipical_write(mipi->regmap, ADDR(CILD_MIPI_CAL_CONFIG), 0);
457 mipical_write(mipi->regmap, ADDR(CILE_MIPI_CAL_CONFIG), 0);
458 mipical_write(mipi->regmap, ADDR(CILF_MIPI_CAL_CONFIG), 0);
459
460 mipical_write(mipi->regmap, ADDR(DSIA_MIPI_CAL_CONFIG), 0);
461 mipical_write(mipi->regmap, ADDR(DSIB_MIPI_CAL_CONFIG), 0);
462 mipical_write(mipi->regmap, ADDR(DSIC_MIPI_CAL_CONFIG), 0);
463 mipical_write(mipi->regmap, ADDR(DSID_MIPI_CAL_CONFIG), 0);
464 mipical_write(mipi->regmap, ADDR(DSIA_MIPI_CAL_CONFIG_2), 0);
465 mipical_write(mipi->regmap, ADDR(DSIB_MIPI_CAL_CONFIG_2), 0);
466 mipical_write(mipi->regmap, ADDR(DSIC_MIPI_CAL_CONFIG_2), 0);
467 mipical_write(mipi->regmap, ADDR(DSID_MIPI_CAL_CONFIG_2), 0);
468}
469
470#ifdef CONFIG_DEBUG_FS
471static struct debugfs_reg32 mipical_regs[] = {
472 dump_register(MIPI_CAL_CTRL),
473 dump_register(MIPI_CAL_AUTOCAL_CTRL0),
474 dump_register(CIL_MIPI_CAL_STATUS),
475 dump_register(CIL_MIPI_CAL_STATUS_2),
476 dump_register(CILA_MIPI_CAL_CONFIG),
477 dump_register(CILB_MIPI_CAL_CONFIG),
478 dump_register(CILC_MIPI_CAL_CONFIG),
479 dump_register(CILD_MIPI_CAL_CONFIG),
480 dump_register(CILE_MIPI_CAL_CONFIG),
481 dump_register(CILF_MIPI_CAL_CONFIG),
482 dump_register(DSIA_MIPI_CAL_CONFIG),
483 dump_register(DSIB_MIPI_CAL_CONFIG),
484 dump_register(DSIC_MIPI_CAL_CONFIG),
485 dump_register(DSID_MIPI_CAL_CONFIG),
486 dump_register(MIPI_BIAS_PAD_CFG0),
487 dump_register(MIPI_BIAS_PAD_CFG1),
488 dump_register(MIPI_BIAS_PAD_CFG2),
489 dump_register(DSIA_MIPI_CAL_CONFIG_2),
490 dump_register(DSIB_MIPI_CAL_CONFIG_2),
491 dump_register(DSIC_MIPI_CAL_CONFIG_2),
492 dump_register(DSID_MIPI_CAL_CONFIG_2),
493};
494
495static u32 mipical_status;
496static u32 timeout_ct;
497static u32 counts;
498
499static int dbgfs_show_regs(struct seq_file *s, void *data)
500{
501 struct tegra_mipi *mipi = s->private;
502 int err;
503
504 err = tegra_unpowergate_partition(mipi->soc->powergate_id);
505 if (err) {
506 dev_err(mipi->dev, "Fail to unpowergate SOR\n");
507 return err;
508 }
509
510 err = tegra_mipi_clk_enable(mipi);
511 if (err) {
512 dev_err(mipi->dev, "Fail to enable mipi clk\n");
513 goto clk_err;
514 }
515 debugfs_print_regs32(s, mipical_regs, ARRAY_SIZE(mipical_regs),
516 mipi->io, "");
517 tegra_mipi_clk_disable(mipi);
518 err = 0;
519
520clk_err:
521 tegra_powergate_partition(mipi->soc->powergate_id);
522 return err;
523}
524
525static int dbgfs_open(struct inode *inode, struct file *file)
526{
527 return single_open(file, dbgfs_show_regs, inode->i_private);
528}
529
530static const struct file_operations dbgfs_ops = {
531 .open = dbgfs_open,
532 .read = seq_read,
533 .llseek = seq_lseek,
534 .release = single_release
535};
536
537static int dbgfs_mipi_init(struct tegra_mipi *mipi)
538{
539 struct dentry *dir;
540 struct dentry *val;
541 int i;
542
543 dir = debugfs_create_dir(DRV_NAME, NULL);
544 if (!dir)
545 return -ENOMEM;
546
547 val = debugfs_create_x32("LAST_STATUS", S_IRUGO, dir, &mipical_status);
548 if (!val)
549 goto err;
550 val = debugfs_create_u32("COUNT", S_IRUGO | S_IWUGO, dir, &counts);
551 if (!val)
552 goto err;
553 val = debugfs_create_u32("TIMEOUTS", S_IRUGO | S_IWUGO, dir,
554 &timeout_ct);
555 if (!val)
556 goto err;
557
558 val = debugfs_create_file("regs", S_IRUGO, dir, mipi, &dbgfs_ops);
559 if (!val)
560 goto err;
561
562 /* Assign register address with adjusted offset */
563 for (i = 0; i < ARRAY_SIZE(mipical_regs); ++i)
564 mipical_regs[i].offset += mipi->soc->addr_offset;
565 return 0;
566err:
567 dev_err(mipi->dev, "%s:Fail to create debugfs\n", __func__);
568 debugfs_remove_recursive(dir);
569 return -ENODEV;
570}
571#endif
572static int _tegra_mipi_calibration(struct tegra_mipi *mipi, int lanes)
573{
574 int err;
575
576 mutex_lock(&mipi->lock);
577 /* clean up lanes */
578 clear_all(mipi);
579
580 /* Apply MIPI_CAL PROD_Set */
581 if (lanes & (CSIA|CSIB|CSIC|CSID|CSIE|CSIF))
582 tegra_mipi_apply_csi_prod(mipi->regmap, mipi->prod_csi,
583 lanes);
584 else
585 tegra_mipi_apply_dsi_prod(mipi->regmap, mipi->prod_dsi,
586 lanes);
587
588 /*Select lanes */
589 select_lanes(mipi, lanes);
590 /* Start calibration */
591 err = tegra_mipi_wait(mipi, lanes);
592
593#ifdef CONFIG_DEBUG_FS
594 regmap_read(mipi->regmap, ADDR(CIL_MIPI_CAL_STATUS), &mipical_status);
595 counts++;
596 if (err)
597 timeout_ct++;
598#endif
599 mutex_unlock(&mipi->lock);
600 return err;
601}
602static int tegra_mipical_using_prod(struct tegra_mipi *mipi, int lanes)
603{
604 int err = 0;
605
606 mutex_lock(&mipi->lock);
607
608 /* clean up lanes */
609 clear_all(mipi);
610
611 /* Apply MIPI_CAL PROD_Set */
612 if (lanes & (CSIA|CSIB|CSIC|CSID|CSIE|CSIF)) {
613 if (!IS_ERR(mipi->prod_gr_csi))
614 err = tegra_prod_set_by_name(&mipi->io, "prod",
615 mipi->prod_gr_csi);
616 } else {
617 if (!IS_ERR(mipi->prod_gr_dsi))
618 err = tegra_prod_set_by_name(&mipi->io,
619 "prod", mipi->prod_gr_dsi);
620 }
621 if (err) {
622 dev_err(mipi->dev, "tegra_prod set failed\n");
623 goto err_unlock;
624 }
625 /*Select lanes */
626 select_lanes(mipi, lanes);
627 /* Start calibration */
628 err = tegra_mipi_wait(mipi, lanes);
629
630#ifdef CONFIG_DEBUG_FS
631 regmap_read(mipi->regmap, ADDR(CIL_MIPI_CAL_STATUS), &mipical_status);
632 counts++;
633 if (err)
634 timeout_ct++;
635#endif
636err_unlock:
637 mutex_unlock(&mipi->lock);
638 return err;
639
640}
641int tegra_mipi_calibration(int lanes)
642{
643 if (!mipi)
644 return -ENODEV;
645 dev_dbg(mipi->dev, "%s", __func__);
646 if (mipi->soc->calibrate)
647 return mipi->soc->calibrate(mipi, lanes);
648 else
649 return 0;
650
651}
652EXPORT_SYMBOL(tegra_mipi_calibration);
653
654static void parse_bias_prod(struct device_node *np,
655 struct tegra_mipi_bias *bias)
656{
657 int ret;
658 unsigned int v;
659
660 ret = of_property_read_u32(np, "bias-pad-cfg0", &v);
661 if (!ret) {
662 bias->pad_pdvclamp = (v & PDVCLAMP) >> PDVCLAMP_SHIFT;
663 bias->e_vclamp_ref = (v & E_VCLAMP_REF) >> E_VCLAMP_REF_SHIFT;
664 }
665
666 ret = of_property_read_u32(np, "bias-pad-cfg1", &v);
667 if (!ret) {
668 bias->pad_driv_up_ref =
669 (v & PAD_DRIV_UP_REF) >> PAD_DRIV_UP_REF_SHIFT;
670 bias->pad_driv_dn_ref =
671 (v & PAD_DRIV_DN_REF) >> PAD_DRIV_DN_REF_SHIFT;
672 }
673
674 ret = of_property_read_u32(np, "bias-pad-cfg2", &v);
675 if (!ret) {
676 bias->pad_vclamp_level =
677 (v & PAD_VCLAMP_LEVEL) >> PAD_VCLAMP_LEVEL_SHIFT;
678 bias->pad_vauxp_level =
679 (v & PAD_VAUXP_LEVEL) >> PAD_VAUXP_LEVEL_SHIFT;
680 }
681}
682
683static void parse_dsi_prod(struct device_node *np,
684 struct tegra_mipi_prod_dsi *dsi)
685{
686 int ret;
687 unsigned int v;
688
689 if (!np)
690 return;
691 ret = of_property_read_u32(np, "dsix-cfg", &v);
692 if (!ret) {
693 dsi->overide_x = (v & OVERIDEDSIA) >> OVERIDEDSIA_SHIFT;
694 dsi->hspdos_x = (v & HSPDOSDSIA) >> HSPDOSDSIA_SHIFT;
695 dsi->hspuos_x = (v & HSPUOSDSIA) >> HSPUOSDSIA_SHIFT;
696 dsi->termos_x = (v & TERMOSDSIA) >> TERMOSDSIA_SHIFT;
697 }
698 ret = of_property_read_u32(np, "dsix-cfg2", &v);
699 if (!ret) {
700 dsi->clk_overide_x =
701 (v & CLKOVERIDEDSIA) >> CLKOVERIDEDSIA_SHIFT;
702 dsi->clk_hspdos_x = (v & HSCLKPDOSDSIA) >> HSCLKPDOSDSIA_SHIFT;
703 dsi->clk_hspuos_x = (v & HSCLKPUOSDSIA) >> HSCLKPUOSDSIA_SHIFT;
704 dsi->clk_hstermos_x =
705 (v & HSCLKTERMOSDSIA) >> HSCLKTERMOSDSIA_SHIFT;
706 }
707 parse_bias_prod(np, &dsi->bias_dsi);
708}
709static void parse_csi_prod(struct device_node *np,
710 struct tegra_mipi_prod_csi *csi)
711{
712 int ret;
713 unsigned int v;
714
715 if (!np)
716 return;
717 ret = of_property_read_u32(np, "cilx-cfg", &v);
718 if (!ret) {
719 csi->overide_x = (v & OVERIDEA) >> OVERIDEA_SHIFT;
720 csi->termos_x = (v & TERMOSA) >> TERMOSA_SHIFT;
721 csi->termos_x_clk = (v & TERMOSA_CLK) >> TERMOSA_CLK_SHIFT;
722 }
723 parse_bias_prod(np, &csi->bias_csi);
724
725}
726static void parse_prod(struct device_node *np, struct tegra_mipi *mipi)
727{
728 struct device_node *next;
729
730 if (!np)
731 return;
732 next = of_get_child_by_name(np, "dsi");
733 parse_dsi_prod(next, mipi->prod_dsi);
734 next = of_get_child_by_name(np, "csi");
735 parse_csi_prod(next, mipi->prod_csi);
736}
737
738static void print_config(struct tegra_mipi *mipi)
739{
740 struct tegra_mipi_prod_csi *csi = mipi->prod_csi;
741 struct tegra_mipi_prod_dsi *dsi = mipi->prod_dsi;
742#define pr_val(x) dev_dbg(mipi->dev, "%s:%x", #x, x)
743
744 pr_val(csi->overide_x);
745 pr_val(csi->termos_x);
746 pr_val(csi->termos_x_clk);
747 pr_val(dsi->overide_x);
748 pr_val(dsi->hspdos_x);
749 pr_val(dsi->hspuos_x);
750 pr_val(dsi->termos_x);
751 pr_val(dsi->clk_overide_x);
752 pr_val(dsi->clk_hspdos_x);
753 pr_val(dsi->clk_hspuos_x);
754 pr_val(dsi->clk_hstermos_x);
755#undef pr_val
756}
757
758static int tegra_prod_get_config(struct platform_device *pdev,
759 struct tegra_mipi *mipi)
760{
761 struct device_node *np;
762
763 if (mipi->prod_gr_dsi != NULL && mipi->prod_gr_csi != NULL)
764 return 0;
765
766 np = of_find_node_by_name(NULL, "mipical");
767 if (!np) {
768 pr_err("%s: Can not find dsi prod node\n", __func__);
769 } else {
770 mipi->prod_gr_dsi =
771 devm_tegra_prod_get_from_node(mipi->dev, np);
772 if (IS_ERR(mipi->prod_gr_dsi))
773 dev_err(mipi->dev, "Fail to get DSI PROD settings\n");
774 }
775
776 np = of_find_node_by_name(NULL, "csi_mipical");
777 if (!np) {
778 pr_err("%s: Can not find csi_mipical node\n", __func__);
779 } else {
780 mipi->prod_gr_csi =
781 devm_tegra_prod_get_from_node(mipi->dev, np);
782 if (IS_ERR(mipi->prod_gr_csi))
783 dev_err(mipi->dev, "Fail to get CSI PROD settings\n");
784 }
785
786 return 0;
787}
788
789static int tegra_mipi_parse_config(struct platform_device *pdev,
790 struct tegra_mipi *mipi)
791{
792 struct device_node *np = pdev->dev.of_node;
793 struct device_node *next;
794
795 if (!np)
796 return -ENODEV;
797
798 if (of_device_is_compatible(np, "nvidia,tegra210-mipical"))
799 parse_prod(np, mipi);
800
801 if (of_device_is_compatible(np, "nvidia, tegra186-mipical")) {
802 if (tegra_chip_get_revision() == TEGRA186_REVISION_A01) {
803 dev_dbg(mipi->dev, "T186-A01\n");
804 next = of_get_child_by_name(np, "a01");
805 parse_prod(next, mipi);
806 } else {
807 dev_dbg(mipi->dev, "T186-A02\n");
808 next = of_get_child_by_name(np, "a02");
809 parse_prod(next, mipi);
810 }
811 }
812 print_config(mipi);
813 return 0;
814}
815static const struct tegra_mipi_soc tegra21x_mipi_soc = {
816 .total_dsilanes = 4,
817 .total_cillanes = 6,
818 .addr_offset = 0,
819 .ppsb_war = 1,
820 .pad_enable = &_t21x_tegra_mipi_bias_pad_enable,
821 .pad_disable = &_t21x_tegra_mipi_bias_pad_disable,
822 .calibrate = &_tegra_mipi_calibration,
823 .parse_cfg = &tegra_mipi_parse_config,
824 .powergate_id = TEGRA210_POWER_DOMAIN_SOR,
825};
826
827static const struct tegra_mipi_soc tegra18x_mipi_soc = {
828 .total_dsilanes = 4,
829 .total_cillanes = 6,
830 .addr_offset = 4,
831 .ppsb_war = 0,
832 .pad_enable = &_t18x_tegra_mipi_bias_pad_enable,
833 .pad_disable = &_t18x_tegra_mipi_bias_pad_disable,
834 .calibrate = &tegra_mipical_using_prod,
835 .parse_cfg = &tegra_prod_get_config,
836 .powergate_id = TEGRA186_POWER_DOMAIN_DISP,
837};
838
839static const struct tegra_mipi_soc tegra_vmipi_soc = {
840 .pad_enable = &tegra_vmipi_bias_pad_enable,
841 .pad_disable = &tegra_vmipi_bias_pad_disable,
842 .calibrate = &tegra_vmipi_calibration,
843 .virtual_dev = 1,
844};
845
846static const struct of_device_id tegra_mipi_of_match[] = {
847 {
848 .compatible = "nvidia,tegra210-mipical",
849 .data = &tegra21x_mipi_soc,
850 }, {
851 .compatible = "nvidia, tegra186-mipical",
852 .data = &tegra18x_mipi_soc,
853 }, {
854 .compatible = "nvidia, tegra186-mipical-shared-multi-os",
855 .data = &tegra18x_mipi_soc,
856 }, {
857 .compatible = "nvidia,tegra-mipical-hv",
858 .data = &tegra_vmipi_soc,
859 }, {
860 }
861};
862MODULE_DEVICE_TABLE(of, tegra_mipi_of_match);
863
864static int tegra_mipi_open(struct inode *inode, struct file *file)
865{
866 return 0;
867}
868static int tegra_mipi_release(struct inode *inode, struct file *file)
869{
870 return 0;
871}
872static long mipi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
873{
874 struct tegra_mipi *mipi = container_of(file->private_data,
875 struct tegra_mipi, misc_dev);
876 if (_IOC_TYPE(cmd) != TEGRA_MIPI_IOCTL_MAGIC)
877 return -EINVAL;
878
879 switch (_IOC_NR(cmd)) {
880 case _IOC_NR(TEGRA_MIPI_IOCTL_BIAS_PAD_CTRL): {
881 unsigned int enable = 0;
882 int err;
883
884 if (copy_from_user(&enable, (const void __user *)arg,
885 sizeof(unsigned int))) {
886 dev_err(mipi->dev, "Fail to get user data\n");
887 return -EFAULT;
888 }
889 if (enable)
890 err = tegra_mipi_bias_pad_enable();
891 else
892 err = tegra_mipi_bias_pad_disable();
893 return err;
894 }
895 case _IOC_NR(TEGRA_MIPI_IOCTL_CAL): {
896 int lanes = 0;
897
898 if (copy_from_user(&lanes, (const void __user *)arg,
899 sizeof(int))) {
900 dev_err(mipi->dev, "Fail to get user data\n");
901 return -EFAULT;
902 }
903 if (lanes)
904 return tegra_mipi_calibration(lanes);
905
906 dev_err(mipi->dev, "Selected lane %x, skip mipical\n", lanes);
907 return 0;
908 }
909 default:
910 dev_err(mipi->dev, "Unknown ioctl\n");
911 return -EINVAL;
912 }
913 return 0;
914}
915
916static const struct file_operations tegra_mipi_miscdev_fops = {
917 .owner = THIS_MODULE,
918 .open = tegra_mipi_open,
919 .release = tegra_mipi_release,
920 .unlocked_ioctl = mipi_ioctl,
921#ifdef CONFIG_COMPAT
922 .compat_ioctl = mipi_ioctl,
923#endif
924};
925
926static int tegra_mipi_misc_register(struct tegra_mipi *mipi)
927{
928 int err;
929
930 if (!mipi)
931 return -EINVAL;
932
933 mipi->misc_dev.minor = MISC_DYNAMIC_MINOR;
934 mipi->misc_dev.name = DRV_NAME;
935 mipi->misc_dev.fops = &tegra_mipi_miscdev_fops;
936 err = misc_register(&mipi->misc_dev);
937 if (err)
938 dev_err(mipi->dev, "Fail to register misc dev\n");
939
940 return err;
941}
942
943int tegra_vmipi_probe(struct platform_device *pdev)
944{
945 int err;
946
947 err = tegra_vmipi_init(pdev);
948 if (err) {
949 dev_err(&pdev->dev, "Mipi cal virtual dev probe failed\n");
950 return err;
951 }
952
953 err = tegra_mipi_misc_register(mipi);
954 if (err)
955 tegra_vmipi_deinit();
956
957 return err;
958}
959
960static int tegra_mipi_probe(struct platform_device *pdev)
961{
962 const struct of_device_id *match;
963 struct resource *mem, *memregion;
964 void __iomem *regs;
965 int err = 0;
966 struct device_node *np;
967 const struct tegra_mipi_soc *cdata = NULL;
968
969 np = pdev->dev.of_node;
970 match = of_match_device(tegra_mipi_of_match, &pdev->dev);
971 if (!match) {
972 dev_err(&pdev->dev, "No device match found\n");
973 return -ENODEV;
974 }
975 cdata = match->data;
976 mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
977 if (!mipi)
978 return -ENOMEM;
979
980 mipi->dev = &pdev->dev;
981 mipi->soc = cdata;
982 platform_set_drvdata(pdev, mipi);
983
984 if (mipi->soc->virtual_dev)
985 return tegra_vmipi_probe(pdev);
986
987 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
988 if (!mem) {
989 dev_err(&pdev->dev, "No memory resource\n");
990 return -EINVAL;
991 }
992 memregion = devm_request_mem_region(&pdev->dev, mem->start,
993 resource_size(mem), pdev->name);
994 if (!memregion) {
995 dev_err(&pdev->dev, "Cannot request mem region\n");
996 return -EBUSY;
997 }
998 regs = devm_ioremap_nocache(&pdev->dev, mem->start, resource_size(mem));
999 if (!regs) {
1000 dev_err(&pdev->dev, "ioremap failed\n");
1001 return -ENOMEM;
1002 }
1003
1004 mipi->io = regs;
1005 mipi->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
1006 &t210_mipi_cal_regmap_config);
1007 if (IS_ERR(mipi->regmap)) {
1008 dev_err(&pdev->dev, "Fai to initialize regmap\n");
1009 return PTR_ERR(mipi->regmap);
1010 }
1011
1012 mipi->mipi_cal_clk = devm_clk_get(&pdev->dev, "mipi_cal");
1013 if (IS_ERR(mipi->mipi_cal_clk))
1014 return PTR_ERR(mipi->mipi_cal_clk);
1015
1016 if (of_device_is_compatible(np, "nvidia,tegra210-mipical")) {
1017 mipi->mipi_cal_fixed = devm_clk_get(&pdev->dev,
1018 "uart_mipi_cal");
1019 if (IS_ERR(mipi->mipi_cal_fixed))
1020 return PTR_ERR(mipi->mipi_cal_fixed);
1021 mipi->prod_csi = devm_kzalloc(&pdev->dev,
1022 sizeof(*mipi->prod_csi), GFP_KERNEL);
1023 mipi->prod_dsi = devm_kzalloc(&pdev->dev,
1024 sizeof(*mipi->prod_dsi), GFP_KERNEL);
1025 } else if (of_device_is_compatible(np, "nvidia, tegra186-mipical")) {
1026 mipi->mipi_cal_fixed = devm_clk_get(&pdev->dev,
1027 "uart_fs_mipi_cal");
1028 if (IS_ERR(mipi->mipi_cal_fixed))
1029 return PTR_ERR(mipi->mipi_cal_fixed);
1030 mipi->rst = devm_reset_control_get(mipi->dev, "mipi_cal");
1031 reset_control_deassert(mipi->rst);
1032 /* Bug 200224083 requires both register fields set to 1
1033 * after de-asserted
1034 */
1035 tegra_mipi_clk_enable(mipi);
1036 mipical_update_bits(mipi->regmap, ADDR(MIPI_BIAS_PAD_CFG0),
1037 PDVCLAMP, 1 << PDVCLAMP_SHIFT);
1038 mipical_update_bits(mipi->regmap, ADDR(MIPI_BIAS_PAD_CFG2),
1039 PDVREG, 1 << PDVREG_SHIFT);
1040 tegra_mipi_clk_disable(mipi);
1041 } else if (of_device_is_compatible(np, "nvidia, tegra186-mipical-shared-multi-os")) {
1042 mipi->mipi_cal_fixed = devm_clk_get(&pdev->dev,
1043 "uart_fs_mipi_cal");
1044 if (IS_ERR(mipi->mipi_cal_fixed))
1045 return PTR_ERR(mipi->mipi_cal_fixed);
1046 mipi->rst = devm_reset_control_get(mipi->dev, "mipi_cal");
1047 reset_control_deassert(mipi->rst);
1048 }
1049
1050 if (mipi->soc->parse_cfg)
1051 err = mipi->soc->parse_cfg(pdev, mipi);
1052 if (err)
1053 return err;
1054
1055 mutex_init(&mipi->lock);
1056 atomic_set(&mipi->refcount, 0);
1057
1058 err = tegra_mipi_misc_register(mipi);
1059 if (err)
1060 return err;
1061
1062#ifdef CONFIG_DEBUG_FS
1063 err = dbgfs_mipi_init(mipi);
1064 if (err)
1065 dev_err(&pdev->dev, "Fail to create debugfs\n");
1066#endif
1067
1068 dev_dbg(&pdev->dev, "Mipi cal done probing...\n");
1069 return err;
1070}
1071
1072static struct platform_driver tegra_mipi_cal_platform_driver = {
1073 .driver = {
1074 .name = DRV_NAME,
1075 .owner = THIS_MODULE,
1076 .of_match_table = tegra_mipi_of_match,
1077 },
1078 .probe = tegra_mipi_probe,
1079};
1080
1081static int __init tegra_mipi_module_init(void)
1082{
1083 return platform_driver_register(&tegra_mipi_cal_platform_driver);
1084}
1085
1086static void __exit tegra_mipi_module_exit(void)
1087{
1088 platform_driver_unregister(&tegra_mipi_cal_platform_driver);
1089}
1090subsys_initcall(tegra_mipi_module_init);
1091module_exit(tegra_mipi_module_exit);
1092
1093MODULE_AUTHOR("Wenjia Zhou <wenjiaz@nvidia.com>");
1094MODULE_DESCRIPTION("Common MIPI calibration driver for CSI and DSI");
1095MODULE_LICENSE("GPL v2");
1096MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/media/platform/tegra/mipical/mipi_cal.h b/drivers/media/platform/tegra/mipical/mipi_cal.h
new file mode 100644
index 000000000..0fd5171fb
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/mipi_cal.h
@@ -0,0 +1,50 @@
1/*
2 * mipi_cal.h
3 *
4 * Copyright (c) 2016-2017, NVIDIA CORPORATION, All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef MIPI_CAL_H
18#define MIPI_CAL_H
19
20#define DSID (1 << 31)
21#define DSIC (1 << 30)
22#define DSIB (1 << 29)
23#define DSIA (1 << 28)
24#define CSIF (1 << 25)
25#define CSIE (1 << 24)
26#define CSID (1 << 23)
27#define CSIC (1 << 22)
28#define CSIB (1 << 21)
29#define CSIA (1 << 20)
30#define MIPI_CPHY 1
31
32#ifdef CONFIG_TEGRA_MIPI_CAL
33int tegra_mipi_bias_pad_enable(void);
34int tegra_mipi_bias_pad_disable(void);
35int tegra_mipi_calibration(int lanes);
36#else
37static inline int tegra_mipi_bias_pad_enable(void)
38{
39 return 0;
40}
41static inline int tegra_mipi_bias_pad_disable(void)
42{
43 return 0;
44}
45static inline int tegra_mipi_calibration(int lanes)
46{
47 return 0;
48}
49#endif
50#endif
diff --git a/drivers/media/platform/tegra/mipical/registers.h b/drivers/media/platform/tegra/mipical/registers.h
new file mode 100644
index 000000000..5f209790b
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/registers.h
@@ -0,0 +1,99 @@
1 /*
2 * registers.h
3 *
4 * Copyright (c) 2016-2017, NVIDIA CORPORATION, All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17/* New register on T186 that starts
18 * at offset 0
19 */
20#define MIPI_CAL_MODE 0x00
21
22/* T210 register offset*/
23#define MIPI_CAL_CTRL 0x00
24#define NOISE_FLT (0xf << 26)
25#define PRESCALE (0x3 << 24)
26#define CLKEN_OVR (1 << 4)
27#define AUTOCAL_EN (1 << 1)
28#define STARTCAL (1 << 0)
29#define MIPI_CAL_AUTOCAL_CTRL0 0x04
30#define CIL_MIPI_CAL_STATUS 0x08
31#define CAL_DONE_DSID (1 << 31)
32#define CAL_DONE_DSIC (1 << 30)
33#define CAL_DONE_DSIB (1 << 29)
34#define CAL_DONE_DSIA (1 << 28)
35#define CAL_DONE_CSIF (1 << 25)
36#define CAL_DONE_CSIE (1 << 24)
37#define CAL_DONE_CSID (1 << 23)
38#define CAL_DONE_CSIC (1 << 22)
39#define CAL_DONE_CSIB (1 << 21)
40#define CAL_DONE_CSIA (1 << 20)
41#define CAL_DONE (1 << 16)
42#define CAL_ACTIVE (1 << 0)
43#define CIL_MIPI_CAL_STATUS_2 0x0c
44#define CILA_MIPI_CAL_CONFIG 0x14
45#define OVERIDEA (1 << 30)
46#define OVERIDEA_SHIFT 30
47#define SELA (1 << 21)
48#define TERMOSA_CLK (0x1f << 11)
49#define TERMOSA_CLK_SHIFT 11
50#define TERMOSA 0x1f
51#define TERMOSA_SHIFT 0
52#define CILB_MIPI_CAL_CONFIG 0x18
53#define CILC_MIPI_CAL_CONFIG 0x1c
54#define CILD_MIPI_CAL_CONFIG 0x20
55#define CILE_MIPI_CAL_CONFIG 0x24
56#define CILF_MIPI_CAL_CONFIG 0x28
57#define DSIA_MIPI_CAL_CONFIG 0x38
58#define OVERIDEDSIA (1 << 30)
59#define OVERIDEDSIA_SHIFT 30
60#define SELDSIA (1 << 21)
61#define HSPDOSDSIA (0x1f << 16)
62#define HSPDOSDSIA_SHIFT 16
63#define HSPUOSDSIA (0x1f << 8)
64#define HSPUOSDSIA_SHIFT 8
65#define TERMOSDSIA 0x1f
66#define TERMOSDSIA_SHIFT 0
67#define DSIB_MIPI_CAL_CONFIG 0x3c
68#define DSIC_MIPI_CAL_CONFIG 0x40
69#define DSID_MIPI_CAL_CONFIG 0x44
70#define MIPI_BIAS_PAD_CFG0 0x58
71#define E_VCLAMP_REF (1 << 0)
72#define E_VCLAMP_REF_SHIFT 0
73#define PDVCLAMP (1 << 1)
74#define PDVCLAMP_SHIFT 1
75#define MIPI_BIAS_PAD_CFG1 0x5c
76#define PAD_DRIV_UP_REF (0x7 << 8)
77#define PAD_DRIV_UP_REF_SHIFT 8
78#define PAD_DRIV_DN_REF (0x7 << 16)
79#define PAD_DRIV_DN_REF_SHIFT 16
80#define MIPI_BIAS_PAD_CFG2 0x60
81#define PDVREG (1 << 1)
82#define PDVREG_SHIFT 1
83#define PAD_VAUXP_LEVEL (0x7 << 4)
84#define PAD_VAUXP_LEVEL_SHIFT 4
85#define PAD_VCLAMP_LEVEL (0x7 << 16)
86#define PAD_VCLAMP_LEVEL_SHIFT 16
87#define DSIA_MIPI_CAL_CONFIG_2 0x64
88#define CLKOVERIDEDSIA (1 << 30)
89#define CLKOVERIDEDSIA_SHIFT 30
90#define CLKSELDSIA (1 << 21)
91#define HSCLKTERMOSDSIA (0x1f << 16)
92#define HSCLKTERMOSDSIA_SHIFT 16
93#define HSCLKPDOSDSIA (0x1f << 8)
94#define HSCLKPDOSDSIA_SHIFT 8
95#define HSCLKPUOSDSIA 0x1f
96#define HSCLKPUOSDSIA_SHIFT 0
97#define DSIB_MIPI_CAL_CONFIG_2 0x68
98#define DSIC_MIPI_CAL_CONFIG_2 0x70
99#define DSID_MIPI_CAL_CONFIG_2 0x74
diff --git a/drivers/media/platform/tegra/mipical/vmipi/vmipi.c b/drivers/media/platform/tegra/mipical/vmipi/vmipi.c
new file mode 100644
index 000000000..ea441c53e
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/vmipi/vmipi.c
@@ -0,0 +1,246 @@
1/*
2 * vmipi.c
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION, All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16#include <linux/device.h>
17#include <linux/of_platform.h>
18#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/delay.h>
21#include <linux/interrupt.h>
22#include <linux/mutex.h>
23#include <linux/semaphore.h>
24#include <linux/wait.h>
25#include <linux/tegra-ivc.h>
26
27#include "mipi_cal.h"
28#include "vmipi.h"
29
30const char *tegra_vmipi_cmd[] = {
31 "TEGRA_VMIPI_CMD_CALIBRATE",
32 "TEGRA_VMIPI_CMD_BIAS_PAD_ENABLE",
33 "TEGRA_VMIPI_CMD_BIAS_PAD_DISABLE",
34};
35
36struct tegra_vmipi_ivc_context {
37 struct device *dev;
38 struct tegra_hv_ivc_cookie *cookie;
39 wait_queue_head_t tx_wq;
40 wait_queue_head_t rx_wq;
41 struct mutex lock;
42};
43static struct tegra_vmipi_ivc_context *ctx;
44
45static int tegra_vmipi_ivc_send(struct tegra_vmipi_cmd_msg *msg, int size)
46{
47 int ret = 0;
48
49 if (!tegra_hv_ivc_can_write(ctx->cookie)) {
50 ret = wait_event_timeout(ctx->tx_wq,
51 tegra_hv_ivc_can_write(ctx->cookie),
52 msecs_to_jiffies(500));
53 if (!ret) {
54 dev_err(ctx->dev,
55 "%s timeout waiting for tx buffer for cmd %s\n",
56 __func__, tegra_vmipi_cmd[msg->cmd]);
57 return -ETIMEDOUT;
58 }
59 }
60
61 ret = tegra_hv_ivc_write(ctx->cookie, msg, size);
62 if (ret != size) {
63 dev_err(ctx->dev,
64 "%s: ivc send incorrect msg size %d for cmd %s\n",
65 __func__, ret, tegra_vmipi_cmd[msg->cmd]);
66 return -EIO;
67 }
68
69 return 0;
70}
71
72static int tegra_vmipi_ivc_rcv(struct tegra_vmipi_cmd_msg *msg, int size)
73{
74 int ret = 0, len;
75
76 if (!tegra_hv_ivc_can_read(ctx->cookie)) {
77 ret = wait_event_timeout(ctx->rx_wq,
78 tegra_hv_ivc_can_read(ctx->cookie),
79 msecs_to_jiffies(500));
80 if (!ret) {
81 dev_err(ctx->dev,
82 "%s timeout waiting for rx buffer for cmd %s\n",
83 __func__, tegra_vmipi_cmd[msg->cmd]);
84 ret = -ETIMEDOUT;
85 goto out;
86 }
87 ret = 0;
88 }
89
90 len = tegra_hv_ivc_read(ctx->cookie, msg, size);
91 if (len != size) {
92 dev_err(ctx->dev,
93 "%s: ivc read incorrect msg size %d for cmd %s\n",
94 __func__, len, tegra_vmipi_cmd[msg->cmd]);
95 ret = -EIO;
96 }
97
98out:
99 if (tegra_hv_ivc_can_write(ctx->cookie))
100 wake_up(&ctx->tx_wq);
101
102 return ret ? ret : msg->ret;
103}
104
105static irqreturn_t tegra_vmipi_ivc_isr(int irq, void *data)
106{
107 struct tegra_vmipi_ivc_context *ictx =
108 (struct tegra_vmipi_ivc_context *)data;
109
110 if (tegra_hv_ivc_channel_notified(ictx->cookie))
111 return IRQ_HANDLED;
112
113 wake_up(&ictx->rx_wq);
114 return IRQ_HANDLED;
115}
116
117static int tegra_vmipi_ivc_send_rcv(struct tegra_vmipi_cmd_msg *msg, int size)
118{
119 int err;
120
121 if (!msg || !size)
122 return -EINVAL;
123
124 mutex_lock(&ctx->lock);
125
126 err = tegra_vmipi_ivc_send(msg, size);
127 if (err)
128 goto out;
129
130 err = tegra_vmipi_ivc_rcv(msg, size);
131
132out:
133 mutex_unlock(&ctx->lock);
134
135 return err;
136}
137
138int tegra_vmipi_calibration(struct tegra_mipi *mipi, int lanes)
139{
140 struct tegra_vmipi_cmd_msg msg;
141 int size = sizeof(msg);
142 struct tegra_vmipi_calibrate_params *p;
143
144 if (!ctx)
145 return -EINVAL;
146
147 msg.cmd = TEGRA_VMIPI_CMD_CALIBRATE;
148 p = &msg.params.calibrate;
149 p->lanes = lanes;
150 return tegra_vmipi_ivc_send_rcv(&msg, size);
151}
152
153int tegra_vmipi_bias_pad_enable(struct tegra_mipi *mipi)
154{
155 struct tegra_vmipi_cmd_msg msg;
156 int size = sizeof(msg);
157
158 if (!ctx)
159 return -EINVAL;
160
161 msg.cmd = TEGRA_VMIPI_CMD_BIAS_PAD_ENABLE;
162 return tegra_vmipi_ivc_send_rcv(&msg, size);
163}
164
165int tegra_vmipi_bias_pad_disable(struct tegra_mipi *mipi)
166{
167 struct tegra_vmipi_cmd_msg msg;
168 int size = sizeof(msg);
169
170 if (!ctx)
171 return -EINVAL;
172
173 msg.cmd = TEGRA_VMIPI_CMD_BIAS_PAD_DISABLE;
174 return tegra_vmipi_ivc_send_rcv(&msg, size);
175}
176
177int tegra_vmipi_init(struct platform_device *pdev)
178{
179 static struct tegra_vmipi_ivc_context *context;
180 struct device_node *np, *ivcq_np;
181 struct tegra_hv_ivc_cookie *cookie;
182 int err, ivcq;
183
184 if (!pdev)
185 return -ENODEV;
186
187 context = devm_kzalloc(&pdev->dev, sizeof(*context), GFP_KERNEL);
188 if (!context)
189 return -ENOMEM;
190
191 context->dev = &pdev->dev;
192
193 np = pdev->dev.of_node;
194 ivcq_np = of_parse_phandle(np, "ivc_queue", 0);
195 if (!ivcq_np) {
196 dev_err(&pdev->dev, "Fail to find vmipi ivc queue\n");
197 return -ENOMEM;
198 }
199
200 err = of_property_read_u32_index(np, "ivc_queue", 1, &ivcq);
201 if (err) {
202 dev_err(&pdev->dev, "Fail to read vmipi ivc queue value\n");
203 of_node_put(ivcq_np);
204 return -EINVAL;
205 }
206 of_node_put(ivcq_np);
207
208 cookie = tegra_hv_ivc_reserve(ivcq_np, ivcq, NULL);
209 if (IS_ERR_OR_NULL(cookie)) {
210 if (cookie == ERR_PTR(-EPROBE_DEFER))
211 return -EPROBE_DEFER;
212
213 dev_err(&pdev->dev,
214 "Fail to reserve vmipi ivc queue %d\n", ivcq);
215 return PTR_ERR(cookie);
216 }
217 context->cookie = cookie;
218
219 init_waitqueue_head(&context->tx_wq);
220 init_waitqueue_head(&context->rx_wq);
221
222 mutex_init(&context->lock);
223
224 tegra_hv_ivc_channel_reset(context->cookie);
225
226 err = devm_request_irq(&pdev->dev, cookie->irq, tegra_vmipi_ivc_isr, 0,
227 "mipi-virt", context);
228 if (err) {
229 dev_err(&pdev->dev, "Fail to request vmipi ivc irq %d\n",
230 cookie->irq);
231 goto fail;
232 }
233
234 ctx = context;
235 return 0;
236
237fail:
238 tegra_hv_ivc_unreserve(context->cookie);
239 return err;
240}
241
242void tegra_vmipi_deinit(void)
243{
244 if (ctx)
245 tegra_hv_ivc_unreserve(ctx->cookie);
246}
diff --git a/drivers/media/platform/tegra/mipical/vmipi/vmipi.h b/drivers/media/platform/tegra/mipical/vmipi/vmipi.h
new file mode 100644
index 000000000..694f1ac21
--- /dev/null
+++ b/drivers/media/platform/tegra/mipical/vmipi/vmipi.h
@@ -0,0 +1,66 @@
1/*
2 * vmipi.h
3 *
4 * Copyright (c) 2017, NVIDIA CORPORATION, All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef VMIPI_H
18#define VMIPI_H
19
20struct tegra_mipi;
21
22enum {
23 TEGRA_VMIPI_CMD_CALIBRATE = 0,
24 TEGRA_VMIPI_CMD_BIAS_PAD_ENABLE = 1,
25 TEGRA_VMIPI_CMD_BIAS_PAD_DISABLE = 2,
26};
27
28struct tegra_vmipi_calibrate_params {
29 u32 lanes;
30};
31
32struct tegra_vmipi_cmd_msg {
33 u32 cmd;
34 int ret;
35 union {
36 struct tegra_vmipi_calibrate_params calibrate;
37 } params;
38};
39
40#ifdef CONFIG_TEGRA_MIPI_CAL
41int tegra_vmipi_init(struct platform_device *pdev);
42void tegra_vmipi_deinit(void);
43int tegra_vmipi_bias_pad_enable(struct tegra_mipi *mipi);
44int tegra_vmipi_bias_pad_disable(struct tegra_mipi *mipi);
45int tegra_vmipi_calibration(struct tegra_mipi *mipi, int lanes);
46#else
47static inline int tegra_vmipi_init(struct platform_device *pdev)
48{
49 return 0;
50}
51static inline void tegra_vmipi_init(void) {}
52static inline int tegra_vmipi_bias_pad_enable(struct tegra_mipi *mipi)
53{
54 return 0;
55}
56static inline int tegra_vmipi_bias_pad_disable(struct tegra_mipi *mipi)
57{
58 return 0;
59}
60static inline int tegra_vmipi_calibration(struct tegra_mipi *mipi,
61 int lanes)
62{
63 return 0;
64}
65#endif
66#endif
diff --git a/drivers/media/platform/tegra/regmap_util.c b/drivers/media/platform/tegra/regmap_util.c
new file mode 100644
index 000000000..c21dcac78
--- /dev/null
+++ b/drivers/media/platform/tegra/regmap_util.c
@@ -0,0 +1,173 @@
1/*
2 * regmap_util.c - utilities for writing regmap tables
3 *
4 * Copyright (c) 2013-2016, NVIDIA Corporation. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/regmap.h>
20#include <media/camera_common.h>
21
22int
23regmap_util_write_table_8(struct regmap *regmap,
24 const struct reg_8 table[],
25 const struct reg_8 override_list[],
26 int num_override_regs, u16 wait_ms_addr, u16 end_addr)
27{
28 int err;
29 const struct reg_8 *next;
30 int i;
31 u8 val;
32
33 int range_start = -1;
34 int range_count = 0;
35 /* bug 200048392 -
36 * the vi i2c cannot take a FIFO buffer bigger than 16 bytes
37 */
38 u8 range_vals[16];
39 int max_range_vals = ARRAY_SIZE(range_vals);
40
41 for (next = table;; next++) {
42 /* If we have a range open and */
43 /* either the address doesn't match */
44 /* or the temporary storage is full, flush */
45 if ((next->addr != range_start + range_count) ||
46 (next->addr == end_addr) ||
47 (next->addr == wait_ms_addr) ||
48 (range_count == max_range_vals)) {
49
50 if (range_count == 1) {
51 err =
52 regmap_write(regmap, range_start,
53 range_vals[0]);
54 } else if (range_count > 1) {
55 err =
56 regmap_bulk_write(regmap, range_start,
57 &range_vals[0],
58 range_count);
59 }
60
61 if (err) {
62 pr_err("%s:regmap_util_write_table:%d",
63 __func__, err);
64 return err;
65 }
66
67 range_start = -1;
68 range_count = 0;
69
70 /* Handle special address values */
71 if (next->addr == end_addr)
72 break;
73
74 if (next->addr == wait_ms_addr) {
75 msleep_range(next->val);
76 continue;
77 }
78 }
79
80 val = next->val;
81
82 /* When an override list is passed in, replace the reg */
83 /* value to write if the reg is in the list */
84 if (override_list) {
85 for (i = 0; i < num_override_regs; i++) {
86 if (next->addr == override_list[i].addr) {
87 val = override_list[i].val;
88 break;
89 }
90 }
91 }
92
93 if (range_start == -1)
94 range_start = next->addr;
95
96 range_vals[range_count++] = val;
97 }
98 return 0;
99}
100
101int
102regmap_util_write_table_16_as_8(struct regmap *regmap,
103 const struct reg_16 table[],
104 const struct reg_16 override_list[],
105 int num_override_regs,
106 u16 wait_ms_addr, u16 end_addr)
107{
108 int err;
109 const struct reg_16 *next;
110 int i;
111 u16 val;
112
113 int range_start = -1;
114 int range_count = 0;
115 u8 range_vals[256];
116 int max_range_vals = ARRAY_SIZE(range_vals);
117
118 for (next = table;; next++) {
119 /* If we have a range open and */
120 /* either the address doesn't match */
121 /* or the temporary storage is full, flush*/
122 if ((next->addr != range_start + range_count) ||
123 (next->addr == end_addr) ||
124 (next->addr == wait_ms_addr) ||
125 (range_count == max_range_vals)) {
126
127 if (range_count > 1) {
128 err =
129 regmap_bulk_write(regmap, range_start,
130 &range_vals[0],
131 range_count);
132 }
133
134 if (err) {
135 pr_err("%s:regmap_util_write_table:%d",
136 __func__, err);
137 return err;
138 }
139
140 range_start = -1;
141 range_count = 0;
142
143 /* Handle special address values */
144 if (next->addr == end_addr)
145 break;
146
147 if (next->addr == wait_ms_addr) {
148 msleep_range(next->val);
149 continue;
150 }
151 }
152
153 val = next->val;
154
155 /* When an override list is passed in, replace the reg */
156 /* value to write if the reg is in the list */
157 if (override_list) {
158 for (i = 0; i < num_override_regs; i++) {
159 if (next->addr == override_list[i].addr) {
160 val = override_list[i].val;
161 break;
162 }
163 }
164 }
165
166 if (range_start == -1)
167 range_start = next->addr;
168
169 range_vals[range_count++] = (u8) (val >> 8);
170 range_vals[range_count++] = (u8) (val & 0xFF);
171 }
172 return 0;
173}
diff --git a/drivers/media/platform/tegra/tpg/Makefile b/drivers/media/platform/tegra/tpg/Makefile
new file mode 100644
index 000000000..135473166
--- /dev/null
+++ b/drivers/media/platform/tegra/tpg/Makefile
@@ -0,0 +1,14 @@
1GCOV_PROFILE := y
2ccflags-y += -I../nvhost/drivers/video/tegra/host
3ccflags-y += -Idrivers/media/platform/tegra
4ccflags-y += -Werror
5
6ifeq ($(CONFIG_ARCH_TEGRA_18x_SOC),y)
7ccflags-y += -I../t18x/drivers/video/tegra/host
8nvhost-vi-tpg-objs += tpg_t18x.o
9else
10nvhost-vi-tpg-objs += tpg_t21x.o
11endif
12
13
14obj-$(CONFIG_VIDEO_TEGRA_VI_TPG) += nvhost-vi-tpg.o
diff --git a/drivers/media/platform/tegra/tpg/tpg_t18x.c b/drivers/media/platform/tegra/tpg/tpg_t18x.c
new file mode 100644
index 000000000..539d9b4de
--- /dev/null
+++ b/drivers/media/platform/tegra/tpg/tpg_t18x.c
@@ -0,0 +1,199 @@
1/*
2 * drivers/video/tegra/host/tpg/tpg.c
3 *
4 * Tegra VI test pattern generator driver
5 *
6 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include <linux/init.h>
21#include <linux/export.h>
22#include <linux/module.h>
23#include <linux/debugfs.h>
24
25#include "camera/vi/mc_common.h"
26#include "camera/csi/csi.h"
27#include "vi/vi4.h"
28#include "nvcsi/nvcsi.h"
29#include "host1x/host1x.h"
30
31/* PG generate 1 pixel per nvcsi_clk:
32 * ((width + hblank) * height + vblank) * fps = nvcsi_clk_freq
33 *
34 */
35const struct tpg_frmfmt tegra18x_csi_tpg_frmfmt[] = {
36 {{1280, 720}, V4L2_PIX_FMT_SRGGB10, 120, 750, 0xffff},
37 {{1920, 1080}, V4L2_PIX_FMT_SRGGB10, 60, 930, 0xffff},
38 {{3840, 2160}, V4L2_PIX_FMT_SRGGB10, 20, 900, 0xffff},
39 {{1280, 720}, V4L2_PIX_FMT_RGB32, 60, 3351, 0xffff},
40 {{1920, 1080}, V4L2_PIX_FMT_RGB32, 30, 4315, 0xffff},
41 {{3840, 2160}, V4L2_PIX_FMT_RGB32, 20, 851, 0xffff},
42};
43
44#define TPG_PORT_IDX 0
45
46static int tpg_debugfs_height_show(void *data, u64 *val)
47{
48 struct tegra_csi_channel *chan = data;
49 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
50
51 mutex_lock(&chan->format_lock);
52 *val = port->format.height;
53 mutex_unlock(&chan->format_lock);
54
55 return 0;
56}
57
58static int tpg_debugfs_height_write(void *data, u64 val)
59{
60 struct tegra_csi_channel *chan = data;
61 struct tegra_csi_device *csi = chan->csi;
62 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
63
64 mutex_lock(&chan->format_lock);
65 port->format.height = val;
66 mutex_unlock(&chan->format_lock);
67
68 if (csi->fops->csi_override_format)
69 csi->fops->csi_override_format(chan, TPG_PORT_IDX);
70
71 return 0;
72}
73
74DEFINE_SIMPLE_ATTRIBUTE(tpg_debugfs_height_fops,
75 tpg_debugfs_height_show,
76 tpg_debugfs_height_write,
77 "%lld\n");
78
79static int tpg_debugfs_width_show(void *data, u64 *val)
80{
81 struct tegra_csi_channel *chan = data;
82 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
83
84 mutex_lock(&chan->format_lock);
85 *val = port->format.width;
86 mutex_unlock(&chan->format_lock);
87
88 return 0;
89}
90
91static int tpg_debugfs_width_write(void *data, u64 val)
92{
93 struct tegra_csi_channel *chan = data;
94 struct tegra_csi_device *csi = chan->csi;
95 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
96
97 mutex_lock(&chan->format_lock);
98 port->format.width = val;
99 mutex_unlock(&chan->format_lock);
100
101 if (csi->fops->csi_override_format)
102 csi->fops->csi_override_format(chan, TPG_PORT_IDX);
103
104 return 0;
105}
106
107DEFINE_SIMPLE_ATTRIBUTE(tpg_debugfs_width_fops,
108 tpg_debugfs_width_show,
109 tpg_debugfs_width_write,
110 "%lld\n");
111
112
113static void tpg_remove_debugfs(struct tegra_csi_device *csi)
114{
115 debugfs_remove_recursive(csi->debugdir);
116 csi->debugdir = NULL;
117}
118
119static int tpg_create_debugfs(struct tegra_csi_device *csi)
120{
121 struct dentry *dir;
122 struct tegra_csi_channel *chan;
123
124 csi->debugdir = dir = debugfs_create_dir("tpg", NULL);
125 if (dir == NULL)
126 return -ENOMEM;
127
128 list_for_each_entry(chan, &csi->csi_chans, list) {
129 const struct tegra_channel *vi_chan =
130 v4l2_get_subdev_hostdata(&chan->subdev);
131 if (vi_chan->pg_mode) {
132 const char *name = vi_chan->video.name;
133
134 dev_dbg(csi->dev, "debugfs node installed %s\n", name);
135 dir = debugfs_create_dir(name, csi->debugdir);
136 if (!dir)
137 goto error;
138
139 if (!debugfs_create_file("height", S_IRUGO | S_IWUSR,
140 dir, chan,
141 &tpg_debugfs_height_fops))
142 goto error;
143 if (!debugfs_create_file("width", S_IRUGO | S_IWUSR,
144 dir, chan,
145 &tpg_debugfs_width_fops))
146 goto error;
147 }
148 }
149
150 return 0;
151error:
152 tpg_remove_debugfs(csi);
153 return -ENOMEM;
154}
155
156static int __init tpg_probe_t18x(void)
157{
158 struct tegra_csi_device *mc_csi = tegra_get_mc_csi();
159 struct tegra_mc_vi *mc_vi = tegra_get_mc_vi();
160 int err;
161
162 dev_info(mc_csi->dev, "%s\n", __func__);
163 mc_vi->csi = mc_csi;
164 /* Init CSI related media controller interface */
165 mc_csi->tpg_frmfmt_table = tegra18x_csi_tpg_frmfmt;
166 mc_csi->tpg_frmfmt_table_size = ARRAY_SIZE(tegra18x_csi_tpg_frmfmt);
167 err = tpg_csi_media_controller_init(mc_csi, TEGRA_VI_PG_PATCH);
168 if (err)
169 return -EINVAL;
170 err = tpg_vi_media_controller_init(mc_vi, TEGRA_VI_PG_PATCH);
171 if (err)
172 goto vi_init_err;
173
174 err = tpg_create_debugfs(mc_csi);
175 if (err)
176 goto debugfs_init_err;
177
178 return err;
179debugfs_init_err:
180 tpg_remove_debugfs(mc_csi);
181vi_init_err:
182 tpg_csi_media_controller_cleanup(mc_csi);
183 dev_err(mc_csi->dev, "%s error\n", __func__);
184 return err;
185}
186static void __exit tpg_remove_t18x(void)
187{
188 struct tegra_csi_device *mc_csi = tegra_get_mc_csi();
189 struct tegra_mc_vi *mc_vi = tegra_get_mc_vi();
190
191 dev_info(mc_csi->dev, "%s\n", __func__);
192 tpg_remove_debugfs(mc_csi);
193 tpg_csi_media_controller_cleanup(mc_csi);
194 tpg_vi_media_controller_cleanup(mc_vi);
195}
196
197module_init(tpg_probe_t18x);
198module_exit(tpg_remove_t18x);
199MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/tegra/tpg/tpg_t21x.c b/drivers/media/platform/tegra/tpg/tpg_t21x.c
new file mode 100644
index 000000000..6291d0209
--- /dev/null
+++ b/drivers/media/platform/tegra/tpg/tpg_t21x.c
@@ -0,0 +1,210 @@
1/*
2 * drivers/video/tegra/host/tpg/tpg.c
3 *
4 * Tegra VI test pattern generator driver
5 *
6 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include <linux/init.h>
21#include <linux/export.h>
22#include <linux/module.h>
23#include <linux/debugfs.h>
24
25#include "camera/vi/mc_common.h"
26#include "camera/csi/csi.h"
27#include "vi/vi.h"
28#include "host1x/host1x.h"
29
30/*
31 * total_cycles_per_lane for one second = pll_d freq / 8
32 * width_in_bytes = ((width * bpp) / 8)
33 * cycles_per_line = width_in_bytes + hblank
34 * cycles_per_image = (cycles_per_line * height) + vblank
35 * image_cycles_per_lane = cycles_per_image / numlanes
36 * framerate = total_cycles_per_lane / image_cycles_per_lane
37 * As per IAS maximum overhead of ~15% can occur
38 * hblank and vblank are tuned to consider overhead during capture
39 * e.g. for 1920x1080, RAW 10 and two lane TPG
40 * cycles_per_lane = (((((1920 * 10)/8) + 512) * 1080) + 8) / 2 ~ 1572480
41 * framerate = ((927000000 / 8) / 1572480) ~ 73fps
42 * Max overhead of 15% results in minimum of 62fps (max can be 73fps)
43 * Note: with changing resolution, bpp and hblank overhead % varies.
44 */
45
46static struct tpg_frmfmt tegra21x_csi_tpg_frmfmt[] = {
47 {{1280, 720}, V4L2_PIX_FMT_SRGGB10, 120, 512, 8},
48 {{1920, 1080}, V4L2_PIX_FMT_SRGGB10, 60, 512, 8},
49 {{3840, 2160}, V4L2_PIX_FMT_SRGGB10, 20, 8, 8},
50 {{1280, 720}, V4L2_PIX_FMT_RGB32, 60, 512, 8},
51 {{1920, 1080}, V4L2_PIX_FMT_RGB32, 30, 512, 8},
52 {{3840, 2160}, V4L2_PIX_FMT_RGB32, 8, 8, 8},
53};
54
55#define TPG_PORT_IDX 0
56
57static int tpg_debugfs_height_show(void *data, u64 *val)
58{
59 struct tegra_csi_channel *chan = data;
60 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
61
62 mutex_lock(&chan->format_lock);
63 *val = port->format.height;
64 mutex_unlock(&chan->format_lock);
65
66 return 0;
67}
68
69static int tpg_debugfs_height_write(void *data, u64 val)
70{
71 struct tegra_csi_channel *chan = data;
72 struct tegra_csi_device *csi = chan->csi;
73 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
74
75 mutex_lock(&chan->format_lock);
76 port->format.height = val;
77 mutex_unlock(&chan->format_lock);
78
79 if (csi->fops->csi_override_format)
80 csi->fops->csi_override_format(chan, TPG_PORT_IDX);
81
82 return 0;
83}
84
85DEFINE_SIMPLE_ATTRIBUTE(tpg_debugfs_height_fops,
86 tpg_debugfs_height_show,
87 tpg_debugfs_height_write,
88 "%lld\n");
89
90static int tpg_debugfs_width_show(void *data, u64 *val)
91{
92 struct tegra_csi_channel *chan = data;
93 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
94
95 mutex_lock(&chan->format_lock);
96 *val = port->format.width;
97 mutex_unlock(&chan->format_lock);
98
99 return 0;
100}
101
102static int tpg_debugfs_width_write(void *data, u64 val)
103{
104 struct tegra_csi_channel *chan = data;
105 struct tegra_csi_device *csi = chan->csi;
106 struct tegra_csi_port *port = &chan->ports[TPG_PORT_IDX];
107
108 mutex_lock(&chan->format_lock);
109 port->format.width = val;
110 mutex_unlock(&chan->format_lock);
111
112 if (csi->fops->csi_override_format)
113 csi->fops->csi_override_format(chan, TPG_PORT_IDX);
114
115 return 0;
116}
117
118DEFINE_SIMPLE_ATTRIBUTE(tpg_debugfs_width_fops,
119 tpg_debugfs_width_show,
120 tpg_debugfs_width_write,
121 "%lld\n");
122
123
124static void tpg_remove_debugfs(struct tegra_csi_device *csi)
125{
126 debugfs_remove_recursive(csi->debugdir);
127 csi->debugdir = NULL;
128}
129
130static int tpg_create_debugfs(struct tegra_csi_device *csi)
131{
132 struct dentry *dir;
133 struct tegra_csi_channel *chan;
134
135 csi->debugdir = dir = debugfs_create_dir("tpg", NULL);
136 if (dir == NULL)
137 return -ENOMEM;
138
139 list_for_each_entry(chan, &csi->csi_chans, list) {
140 const struct tegra_channel *vi_chan =
141 v4l2_get_subdev_hostdata(&chan->subdev);
142 if (vi_chan->pg_mode) {
143 const char *name = vi_chan->video.name;
144
145 dev_dbg(csi->dev, "debugfs node installed %s\n", name);
146 dir = debugfs_create_dir(name, csi->debugdir);
147 if (!dir)
148 goto error;
149
150 if (!debugfs_create_file("height", S_IRUGO | S_IWUSR,
151 dir, chan,
152 &tpg_debugfs_height_fops))
153 goto error;
154 if (!debugfs_create_file("width", S_IRUGO | S_IWUSR,
155 dir, chan,
156 &tpg_debugfs_width_fops))
157 goto error;
158 }
159 }
160
161 return 0;
162error:
163 tpg_remove_debugfs(csi);
164 return -ENOMEM;
165}
166
167static int __init tpg_probe_t21x(void)
168{
169 struct tegra_csi_device *mc_csi = &(tegra_vi_get()->csi);
170 struct tegra_mc_vi *mc_vi = &(tegra_vi_get()->mc_vi);
171 int err;
172
173 dev_info(mc_csi->dev, "%s\n", __func__);
174 mc_vi->csi = mc_csi;
175 /* Init CSI related media controller interface */
176 mc_csi->tpg_frmfmt_table = tegra21x_csi_tpg_frmfmt;
177 mc_csi->tpg_frmfmt_table_size = ARRAY_SIZE(tegra21x_csi_tpg_frmfmt);
178 err = tpg_csi_media_controller_init(mc_csi, TEGRA_VI_PG_PATCH);
179 if (err)
180 return -EINVAL;
181 err = tpg_vi_media_controller_init(mc_vi, TEGRA_VI_PG_PATCH);
182 if (err)
183 goto vi_init_err;
184
185 err = tpg_create_debugfs(mc_csi);
186 if (err)
187 goto debugfs_init_err;
188
189 return err;
190debugfs_init_err:
191 tpg_remove_debugfs(mc_csi);
192vi_init_err:
193 tpg_csi_media_controller_cleanup(mc_csi);
194 dev_err(mc_csi->dev, "%s error\n", __func__);
195 return err;
196}
197static void __exit tpg_remove_t21x(void)
198{
199 struct tegra_csi_device *mc_csi = &(tegra_vi_get()->csi);
200 struct tegra_mc_vi *mc_vi = &(tegra_vi_get()->mc_vi);
201
202 dev_info(mc_csi->dev, "%s\n", __func__);
203 tpg_remove_debugfs(mc_csi);
204 tpg_csi_media_controller_cleanup(mc_csi);
205 tpg_vi_media_controller_cleanup(mc_vi);
206}
207
208module_init(tpg_probe_t21x);
209module_exit(tpg_remove_t21x);
210MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/tegra/vi/Makefile b/drivers/media/platform/tegra/vi/Makefile
new file mode 100644
index 000000000..6cd9767ea
--- /dev/null
+++ b/drivers/media/platform/tegra/vi/Makefile
@@ -0,0 +1,17 @@
1GCOV_PROFILE := y
2ccflags-y += -I../nvhost/drivers/video/tegra/host
3ccflags-y += -Idrivers/video/tegra/camera
4ccflags-y += -Idrivers/media/platform/tegra/
5ccflags-y += -Werror
6
7ifeq ($(CONFIG_ARCH_TEGRA_18x_SOC),y)
8ccflags-y += -I../t18x/drivers/video/tegra/host/
9endif
10
11ifneq (,$(filter $(CONFIG_VIDEO_TEGRA_VI),y m))
12obj-y += vi_irq.o
13obj-y += tegra_vi.o
14endif
15
16nvhost-vi-objs += vi.o
17obj-$(CONFIG_VIDEO_TEGRA_VI) += nvhost-vi.o
diff --git a/drivers/media/platform/tegra/vi/tegra_vi.c b/drivers/media/platform/tegra/vi/tegra_vi.c
new file mode 100644
index 000000000..4d2e3b714
--- /dev/null
+++ b/drivers/media/platform/tegra/vi/tegra_vi.c
@@ -0,0 +1,515 @@
1/*
2 * Copyright (c) 2013-2016, 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/fs.h>
18#include <linux/file.h>
19#include <linux/delay.h>
20#include <linux/module.h>
21#include <linux/nvhost.h>
22#include <linux/nvhost_vi_ioctl.h>
23#include <linux/platform_device.h>
24#include <linux/regulator/consumer.h>
25#include <linux/uaccess.h>
26#include <linux/clk.h>
27
28#include <linux/platform/tegra/latency_allowance.h>
29
30#include "bus_client.h"
31#include "nvhost_acm.h"
32#include "chip_support.h"
33#include "host1x/host1x.h"
34#include "vi/vi.h"
35#include "vi/vi_irq.h"
36
37#define T12_VI_CFG_CG_CTRL 0xb8
38#define T12_CG_2ND_LEVEL_EN 1
39#define T12_VI_CSI_0_SW_RESET 0x100
40#define T12_CSI_CSI_SW_SENSOR_A_RESET 0x858
41#define T12_CSI_CSICIL_SW_SENSOR_A_RESET 0x94c
42#define T12_VI_CSI_0_CSI_IMAGE_DT 0x120
43
44#define T12_VI_CSI_1_SW_RESET 0x200
45#define T12_CSI_CSI_SW_SENSOR_B_RESET 0x88c
46#define T12_CSI_CSICIL_SW_SENSOR_B_RESET 0x980
47#define T12_VI_CSI_1_CSI_IMAGE_DT 0x220
48
49#define T21_CSI_CILA_PAD_CONFIG0 0x92c
50#define T21_CSI1_CILA_PAD_CONFIG0 0x112c
51#define T21_CSI2_CILA_PAD_CONFIG0 0x192c
52
53#define VI_MAX_BPP 2
54
55int nvhost_vi_finalize_poweron(struct platform_device *dev)
56{
57 struct vi *tegra_vi = nvhost_get_private_data(dev);
58 int ret = 0;
59
60 if (!tegra_vi)
61 return -EINVAL;
62
63 if (tegra_vi->reg) {
64 ret = regulator_enable(tegra_vi->reg);
65 if (ret) {
66 dev_err(&dev->dev,
67 "%s: enable csi regulator failed.\n",
68 __func__);
69 return ret;
70 }
71 }
72
73#ifdef CONFIG_ARCH_TEGRA_12x_SOC
74 /* Only do this for vi.0 not for slave device vi.1 */
75 if (dev->id == 0)
76 host1x_writel(dev, T12_VI_CFG_CG_CTRL, T12_CG_2ND_LEVEL_EN);
77#endif
78
79 ret = vi_enable_irq(tegra_vi);
80 if (ret)
81 dev_err(&tegra_vi->ndev->dev, "%s: vi_enable_irq failed\n",
82 __func__);
83
84 return ret;
85}
86
87int nvhost_vi_prepare_poweroff(struct platform_device *dev)
88{
89 int ret = 0;
90 struct vi *tegra_vi = nvhost_get_private_data(dev);
91
92 if (!tegra_vi)
93 return -EINVAL;
94
95 ret = vi_disable_irq(tegra_vi);
96 if (ret) {
97 dev_err(&tegra_vi->ndev->dev, "%s: vi_disable_irq failed\n",
98 __func__);
99 return ret;
100 }
101
102 if (tegra_vi->reg) {
103 ret = regulator_disable(tegra_vi->reg);
104 if (ret)
105 dev_err(&dev->dev,
106 "%s: disable csi regulator failed.\n",
107 __func__);
108 }
109
110 return ret;
111}
112
113#if defined(CONFIG_TEGRA_ISOMGR)
114static int vi_isomgr_register(struct vi *tegra_vi)
115{
116 int iso_client_id = TEGRA_ISO_CLIENT_VI_0;
117 struct clk *vi_clk;
118 struct nvhost_device_data *pdata =
119 platform_get_drvdata(tegra_vi->ndev);
120
121 dev_dbg(&tegra_vi->ndev->dev, "%s++\n", __func__);
122
123 if (WARN_ONCE(pdata == NULL, "pdata not found, %s failed\n", __func__))
124 return -ENODEV;
125
126 /* Get max VI BW */
127 vi_clk = pdata->clk[0];
128 tegra_vi->max_bw =
129 (clk_round_rate(vi_clk, UINT_MAX) / 1000) * VI_MAX_BPP;
130
131 /* Register with max possible BW in VI usecases.*/
132 tegra_vi->isomgr_handle = tegra_isomgr_register(iso_client_id,
133 tegra_vi->max_bw,
134 NULL, /* tegra_isomgr_renegotiate */
135 NULL); /* *priv */
136
137 if (!tegra_vi->isomgr_handle) {
138 dev_err(&tegra_vi->ndev->dev, "%s: unable to register isomgr\n",
139 __func__);
140 return -ENOMEM;
141 }
142
143 return 0;
144}
145
146static int vi_set_isomgr_request(struct vi *tegra_vi, uint vi_bw, uint lt)
147{
148 int ret = 0;
149
150 dev_dbg(&tegra_vi->ndev->dev,
151 "%s++ bw=%u, lt=%u\n", __func__, vi_bw, lt);
152
153 /* return value of tegra_isomgr_reserve is dvfs latency in usec */
154 ret = tegra_isomgr_reserve(tegra_vi->isomgr_handle,
155 vi_bw, /* KB/sec */
156 lt); /* usec */
157 if (!ret) {
158 dev_err(&tegra_vi->ndev->dev,
159 "%s: failed to reserve %u KBps\n", __func__, vi_bw);
160 return -ENOMEM;
161 }
162
163 /* return value of tegra_isomgr_realize is dvfs latency in usec */
164 ret = tegra_isomgr_realize(tegra_vi->isomgr_handle);
165 if (ret)
166 dev_dbg(&tegra_vi->ndev->dev,
167 "%s: tegra_vi isomgr latency is %d usec",
168 __func__, ret);
169 else {
170 dev_err(&tegra_vi->ndev->dev,
171 "%s: failed to realize %u KBps\n", __func__, vi_bw);
172 return -ENOMEM;
173 }
174 return 0;
175}
176
177static int vi_isomgr_release(struct vi *tegra_vi)
178{
179 int ret = 0;
180
181 dev_dbg(&tegra_vi->ndev->dev, "%s++\n", __func__);
182
183 /* deallocate isomgr bw */
184 ret = vi_set_isomgr_request(tegra_vi, 0, 0);
185 if (ret) {
186 dev_err(&tegra_vi->ndev->dev,
187 "%s: failed to deallocate memory in isomgr\n",
188 __func__);
189 return -ENOMEM;
190 }
191
192 return 0;
193}
194#endif
195
196static int vi_set_la(u32 vi_bw)
197{
198 int ret = 0;
199
200#ifdef CONFIG_TEGRA_MC
201 ret = tegra_set_camera_ptsa(TEGRA_LA_VI_W, vi_bw, 1);
202
203 if (!ret) {
204 ret = tegra_set_latency_allowance(TEGRA_LA_VI_W,
205 vi_bw);
206
207 if (ret)
208 pr_err("%s: set latency failed: %d\n",
209 __func__, ret);
210 } else {
211 pr_err("%s: set ptsa failed: %d\n", __func__, ret);
212 }
213#endif
214
215 return ret;
216}
217
218int vi_v4l2_set_la(struct vi *tegra_vi, u32 vi_bypass_bw, bool is_ioctl)
219{
220 int ret = 0;
221 unsigned long total_bw;
222
223 mutex_lock(&tegra_vi->update_la_lock);
224 if (is_ioctl)
225 tegra_vi->vi_bypass_bw = vi_bypass_bw;
226 total_bw = tegra_vi->mc_vi.aggregated_kbyteps + tegra_vi->vi_bypass_bw;
227 ret = vi_set_la(total_bw);
228 mutex_unlock(&tegra_vi->update_la_lock);
229 return ret;
230}
231EXPORT_SYMBOL(vi_v4l2_set_la);
232
233static long vi_ioctl(struct file *file,
234 unsigned int cmd, unsigned long arg)
235{
236 struct vi *tegra_vi = file->private_data;
237
238 if (_IOC_TYPE(cmd) != NVHOST_VI_IOCTL_MAGIC)
239 return -EFAULT;
240
241 switch (_IOC_NR(cmd)) {
242 case _IOC_NR(NVHOST_VI_IOCTL_ENABLE_TPG): {
243 uint enable;
244 int ret;
245 struct clk *clk;
246
247 if (copy_from_user(&enable,
248 (const void __user *)arg, sizeof(uint))) {
249 dev_err(&tegra_vi->ndev->dev,
250 "%s: Failed to copy arg from user\n", __func__);
251 return -EFAULT;
252 }
253
254 clk = clk_get(NULL, "pll_d");
255 if (IS_ERR(clk))
256 return -EINVAL;
257
258 if (enable)
259 ret = tegra_clk_cfg_ex(clk,
260 TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
261 else
262 ret = tegra_clk_cfg_ex(clk,
263 TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
264 clk_put(clk);
265
266 return ret;
267 }
268 case _IOC_NR(NVHOST_VI_IOCTL_GET_VI_CLK): {
269 int ret;
270 u64 vi_clk_rate = 0;
271
272 ret = nvhost_module_get_rate(tegra_vi->ndev,
273 (unsigned long *)&vi_clk_rate, 0);
274 if (ret) {
275 dev_err(&tegra_vi->ndev->dev,
276 "%s: failed to get vi clk\n",
277 __func__);
278 return ret;
279 }
280
281 if (copy_to_user((void __user *)arg,
282 &vi_clk_rate, sizeof(vi_clk_rate))) {
283 dev_err(&tegra_vi->ndev->dev,
284 "%s:Failed to copy vi clk rate to user\n",
285 __func__);
286 return -EFAULT;
287 }
288
289 return 0;
290 }
291 case _IOC_NR(NVHOST_VI_IOCTL_SET_VI_LA_BW): {
292 u32 ret = 0;
293 u32 vi_la_bw;
294
295 if (copy_from_user(&vi_la_bw,
296 (const void __user *)arg,
297 sizeof(vi_la_bw))) {
298 dev_err(&tegra_vi->ndev->dev,
299 "%s: Failed to copy arg from user\n", __func__);
300 return -EFAULT;
301 }
302
303 /* Set latency allowance for VI, BW is in MBps */
304 ret = vi_v4l2_set_la(tegra_vi, vi_la_bw, 1);
305 if (ret) {
306 dev_err(&tegra_vi->ndev->dev,
307 "%s: failed to set la vi_bw %u MBps\n",
308 __func__, vi_la_bw);
309 return -ENOMEM;
310 }
311
312 return 0;
313 }
314 case _IOC_NR(NVHOST_VI_IOCTL_SET_EMC_INFO): {
315 uint vi_bw;
316 int ret;
317
318 if (copy_from_user(&vi_bw,
319 (const void __user *)arg, sizeof(uint))) {
320 dev_err(&tegra_vi->ndev->dev,
321 "%s: Failed to copy arg from user\n", __func__);
322 return -EFAULT;
323 }
324
325 ret = vi_set_la(vi_bw/1000);
326 if (ret) {
327 dev_err(&tegra_vi->ndev->dev,
328 "%s: failed to set la for vi_bw %u MBps\n",
329 __func__, vi_bw/1000);
330 return -ENOMEM;
331 }
332
333#if defined(CONFIG_TEGRA_ISOMGR)
334 /*
335 * Register VI as isomgr client.
336 */
337 if (!tegra_vi->isomgr_handle) {
338 ret = vi_isomgr_register(tegra_vi);
339 if (ret) {
340 dev_err(&tegra_vi->ndev->dev,
341 "%s: failed to register VI as isomgr client\n",
342 __func__);
343 return -ENOMEM;
344 }
345 }
346
347 if (vi_bw > tegra_vi->max_bw) {
348 dev_err(&tegra_vi->ndev->dev,
349 "%s: Requested ISO BW %u is more than "
350 "VI's max BW %u possible\n",
351 __func__, vi_bw, tegra_vi->max_bw);
352 return -EINVAL;
353 }
354
355 /*
356 * Set VI ISO BW requirements.
357 * There is no way to figure out what latency
358 * can be tolerated in VI without reading VI
359 * registers for now. 3 usec is minimum time
360 * to switch PLL source. Let's put 4 usec as
361 * latency for now.
362 */
363 ret = vi_set_isomgr_request(tegra_vi, vi_bw, 4);
364 if (ret) {
365 dev_err(&tegra_vi->ndev->dev,
366 "%s: failed to reserve %u KBps\n",
367 __func__, vi_bw);
368 return -ENOMEM;
369 }
370#endif
371 return ret;
372 }
373 case _IOC_NR(NVHOST_VI_IOCTL_SET_VI_CLK): {
374 long vi_clk_rate = 0;
375
376 if (copy_from_user(&vi_clk_rate,
377 (const void __user *)arg, sizeof(long))) {
378 dev_err(&tegra_vi->ndev->dev,
379 "%s: Failed to copy arg from user\n", __func__);
380 return -EFAULT;
381 }
382
383 return nvhost_module_set_rate(tegra_vi->ndev,
384 tegra_vi, vi_clk_rate, 0, NVHOST_CLOCK);
385 }
386 default:
387 dev_err(&tegra_vi->ndev->dev,
388 "%s: Unknown vi ioctl.\n", __func__);
389 return -EINVAL;
390 }
391 return 0;
392}
393
394static int vi_open(struct inode *inode, struct file *file)
395{
396 struct nvhost_device_data *pdata;
397 struct vi *vi;
398 int err = 0;
399
400 pdata = container_of(inode->i_cdev,
401 struct nvhost_device_data, ctrl_cdev);
402 if (WARN_ONCE(pdata == NULL, "pdata not found, %s failed\n", __func__))
403 return -ENODEV;
404
405 vi = (struct vi *)pdata->private_data;
406 if (WARN_ONCE(vi == NULL, "vi not found, %s failed\n", __func__))
407 return -ENODEV;
408
409 file->private_data = vi;
410
411 /* add vi client to acm */
412 if (nvhost_module_add_client(vi->ndev, vi)) {
413 dev_err(&vi->ndev->dev,
414 "%s: failed add vi client\n",
415 __func__);
416 return -ENOMEM;
417 }
418
419 return err;
420}
421
422static int vi_release(struct inode *inode, struct file *file)
423{
424 int ret = 0;
425 struct vi *tegra_vi = file->private_data;
426
427#if defined(CONFIG_TEGRA_ISOMGR)
428 /* nullify isomgr request */
429 if (tegra_vi->isomgr_handle) {
430 ret = vi_isomgr_release(tegra_vi);
431 if (ret) {
432 dev_err(&tegra_vi->ndev->dev,
433 "%s: failed to deallocate memory in isomgr\n",
434 __func__);
435 return -ENOMEM;
436 }
437 }
438#endif
439
440 /* remove vi client from acm */
441 nvhost_module_remove_client(tegra_vi->ndev, tegra_vi);
442
443 return ret;
444}
445
446const struct file_operations tegra_vi_ctrl_ops = {
447 .owner = THIS_MODULE,
448 .open = vi_open,
449 .unlocked_ioctl = vi_ioctl,
450#ifdef CONFIG_COMPAT
451 .compat_ioctl = vi_ioctl,
452#endif
453 .release = vi_release,
454};
455
456/* Reset sensor data if respective clk is ON */
457void nvhost_vi_reset_all(struct platform_device *pdev)
458{
459 void __iomem *reset_reg[4];
460 int err;
461 bool enabled = false;
462 struct nvhost_device_data *pdata = pdev->dev.platform_data;
463 struct clk *clk;
464
465 err = nvhost_clk_get(pdev, "cilab", &clk);
466 if (!err) {
467 reset_reg[0] = pdata->aperture[0] +
468 T12_VI_CSI_0_SW_RESET;
469 reset_reg[1] = pdata->aperture[0] +
470 T12_CSI_CSI_SW_SENSOR_A_RESET;
471 reset_reg[2] = pdata->aperture[0] +
472 T12_CSI_CSICIL_SW_SENSOR_A_RESET;
473 reset_reg[3] = pdata->aperture[0] +
474 T12_VI_CSI_0_CSI_IMAGE_DT;
475
476 writel(0, reset_reg[3]);
477 writel(0x1, reset_reg[2]);
478 writel(0x1, reset_reg[1]);
479 writel(0x1f, reset_reg[0]);
480
481 udelay(10);
482
483 writel(0, reset_reg[2]);
484 writel(0, reset_reg[1]);
485 }
486
487 err = nvhost_clk_get(pdev, "cilcd", &clk);
488 if (!err)
489 enabled = true;
490
491 err = nvhost_clk_get(pdev, "cile", &clk);
492 if (!err)
493 enabled = true;
494
495 if (enabled) {
496 reset_reg[0] = pdata->aperture[0] +
497 T12_VI_CSI_1_SW_RESET;
498 reset_reg[1] = pdata->aperture[0] +
499 T12_CSI_CSI_SW_SENSOR_B_RESET;
500 reset_reg[2] = pdata->aperture[0] +
501 T12_CSI_CSICIL_SW_SENSOR_B_RESET;
502 reset_reg[3] = pdata->aperture[0] +
503 T12_VI_CSI_1_CSI_IMAGE_DT;
504
505 writel(0, reset_reg[3]);
506 writel(0x1, reset_reg[2]);
507 writel(0x1, reset_reg[1]);
508 writel(0x1f, reset_reg[0]);
509
510 udelay(10);
511
512 writel(0, reset_reg[2]);
513 writel(0, reset_reg[1]);
514 }
515}
diff --git a/drivers/media/platform/tegra/vi/vi.c b/drivers/media/platform/tegra/vi/vi.c
new file mode 100644
index 000000000..61f47fd40
--- /dev/null
+++ b/drivers/media/platform/tegra/vi/vi.c
@@ -0,0 +1,611 @@
1/*
2 * drivers/video/tegra/host/vi/vi.c
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2012-2017, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <linux/init.h>
22#include <linux/export.h>
23#include <linux/module.h>
24#include <linux/resource.h>
25#include <linux/pm_runtime.h>
26#include <linux/of.h>
27#include <linux/of_device.h>
28#include <linux/of_platform.h>
29#include <linux/clk/tegra.h>
30#include <linux/tegra-soc.h>
31#include <linux/tegra_pm_domains.h>
32#include <linux/debugfs.h>
33#include <linux/slab.h>
34
35#include <media/tegra_v4l2_camera.h>
36
37#include "dev.h"
38#include "bus_client.h"
39#include "nvhost_acm.h"
40#include "t210/t210.h"
41#include "vi/vi.h"
42#include "vi/vi_irq.h"
43#include "camera/vi/vi2_fops.h"
44#include "camera/csi/csi2_fops.h"
45
46#include "tegra_camera_dev_mfi.h"
47
48#define MAX_DEVID_LENGTH 16
49#define TEGRA_VI_NAME "tegra_vi"
50
51struct vi *tegra_vi;
52
53struct vi *tegra_vi_get(void)
54{
55 return tegra_vi;
56}
57EXPORT_SYMBOL(tegra_vi_get);
58
59static struct tegra_t210_vi_data t21_vi_data = {
60 .info = (struct nvhost_device_data *)&t21_vi_info,
61 .vi_fops = &vi2_fops,
62 .csi_fops = &csi2_fops,
63};
64
65static struct of_device_id tegra_vi_of_match[] = {
66 { .compatible = "nvidia,tegra210-vi",
67 .data = (struct tegra_t210_vi_data *)&t21_vi_data },
68 { },
69};
70
71static struct i2c_camera_ctrl *i2c_ctrl;
72
73static void (*mfi_callback)(void *);
74static struct mfi_cb_arg *mfi_callback_arg;
75static DEFINE_MUTEX(vi_isr_lock);
76
77int tegra_vi_register_mfi_cb(callback cb, void *cb_arg)
78{
79 mutex_lock(&vi_isr_lock);
80 if (mfi_callback || mfi_callback_arg) {
81 pr_err("cb already registered\n");
82 mutex_unlock(&vi_isr_lock);
83 return -1;
84 }
85
86 mfi_callback = cb;
87 mfi_callback_arg = (struct mfi_cb_arg *)cb_arg;
88 mutex_unlock(&vi_isr_lock);
89
90 return 0;
91}
92EXPORT_SYMBOL(tegra_vi_register_mfi_cb);
93
94int tegra_vi_unregister_mfi_cb(void)
95{
96 mutex_lock(&vi_isr_lock);
97 mfi_callback = NULL;
98 mfi_callback_arg = NULL;
99 mutex_unlock(&vi_isr_lock);
100
101 return 0;
102}
103EXPORT_SYMBOL(tegra_vi_unregister_mfi_cb);
104
105struct tegra_mfi_chan {
106 struct work_struct mfi_cb_work;
107 struct rcu_head rcu;
108 u8 channel;
109};
110
111struct tegra_vi_mfi_ctx {
112 u8 num_channels;
113 struct workqueue_struct *mfi_workqueue;
114 struct tegra_mfi_chan __rcu *mfi_chans;
115};
116
117static void vi_mfi_worker(struct work_struct *vi_work)
118{
119 struct tegra_mfi_chan *mfi_chan =
120 container_of(vi_work, struct tegra_mfi_chan, mfi_cb_work);
121
122 mutex_lock(&vi_isr_lock);
123 if (mfi_callback == NULL) {
124 pr_debug("NULL callback\n");
125 mutex_unlock(&vi_isr_lock);
126 return;
127 }
128 if (mfi_callback_arg)
129 mfi_callback_arg->vi_chan = mfi_chan->channel;
130 mfi_callback(mfi_callback_arg);
131 mutex_unlock(&vi_isr_lock);
132}
133
134int tegra_vi_mfi_event_notify(struct tegra_vi_mfi_ctx *mfi_ctx, u8 channel)
135{
136 struct tegra_mfi_chan *chan;
137
138 if (!mfi_ctx) {
139 pr_err("Invalid mfi_ctx\n");
140 return -EINVAL;
141 }
142
143 if (channel > mfi_ctx->num_channels-1) {
144 pr_err("Invalid mfi channel\n");
145 return -EINVAL;
146 }
147
148 rcu_read_lock();
149 chan = rcu_dereference(mfi_ctx->mfi_chans);
150 queue_work(mfi_ctx->mfi_workqueue, &chan[channel].mfi_cb_work);
151 rcu_read_unlock();
152
153 return 0;
154}
155EXPORT_SYMBOL(tegra_vi_mfi_event_notify);
156
157bool tegra_vi_has_mfi_callback(void)
158{
159 bool ret;
160
161 mutex_lock(&vi_isr_lock);
162 ret = mfi_callback ? true : false;
163 mutex_unlock(&vi_isr_lock);
164
165 return ret;
166}
167EXPORT_SYMBOL(tegra_vi_has_mfi_callback);
168
169int tegra_vi_init_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx, u8 num_channels)
170{
171 u8 i;
172 struct tegra_mfi_chan *chan;
173 struct tegra_vi_mfi_ctx *mfi_ctx;
174
175 if (!pmfi_ctx) {
176 pr_err("mfi_ctx is invalid\n");
177 return -EINVAL;
178 }
179
180 mfi_ctx = kzalloc(sizeof(*mfi_ctx), GFP_KERNEL);
181 if (unlikely(mfi_ctx == NULL))
182 return -ENOMEM;
183
184 /* create workqueue for mfi callback */
185 mfi_ctx->mfi_workqueue = alloc_workqueue("mfi_workqueue",
186 WQ_HIGHPRI | WQ_UNBOUND, 1);
187 if (!mfi_ctx->mfi_workqueue) {
188 pr_err("Failed to allocated mfi_workqueue");
189 tegra_vi_deinit_mfi(&mfi_ctx);
190 return -ENOMEM;
191 }
192
193 chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
194 if (unlikely(chan == NULL)) {
195 tegra_vi_deinit_mfi(&mfi_ctx);
196 return -ENOMEM;
197 }
198
199 mfi_ctx->num_channels = num_channels;
200
201 /* Init mfi callback work */
202 for (i = 0; i < num_channels; i++) {
203 INIT_WORK(&chan[i].mfi_cb_work, vi_mfi_worker);
204 chan[i].channel = i;
205 }
206
207 rcu_assign_pointer(mfi_ctx->mfi_chans, chan);
208
209 *pmfi_ctx = mfi_ctx;
210
211 return 0;
212}
213EXPORT_SYMBOL(tegra_vi_init_mfi);
214
215void tegra_vi_deinit_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx)
216{
217 struct tegra_vi_mfi_ctx *mfi_ctx;
218
219 if (!pmfi_ctx || !*pmfi_ctx)
220 return;
221
222 mfi_ctx = *pmfi_ctx;
223
224 flush_workqueue(mfi_ctx->mfi_workqueue);
225 destroy_workqueue(mfi_ctx->mfi_workqueue);
226
227 kfree_rcu(mfi_ctx->mfi_chans, rcu);
228
229 kfree(mfi_ctx);
230 mfi_ctx = NULL;
231}
232EXPORT_SYMBOL(tegra_vi_deinit_mfi);
233
234#if defined(CONFIG_TEGRA_ISOMGR)
235static int vi_isomgr_unregister(struct vi *tegra_vi)
236{
237 tegra_isomgr_unregister(tegra_vi->isomgr_handle);
238 tegra_vi->isomgr_handle = NULL;
239
240 return 0;
241}
242#endif
243
244static int vi_out_show(struct seq_file *s, void *unused)
245{
246 struct vi *vi = s->private;
247
248 seq_printf(s, "vi overflow: %u\n",
249 atomic_read(&(vi->vi_out.overflow)));
250
251 return 0;
252}
253
254static int vi_out_open(struct inode *inode, struct file *file)
255{
256 return single_open(file, vi_out_show, inode->i_private);
257}
258
259static const struct file_operations vi_out_fops = {
260 .open = vi_out_open,
261 .read = seq_read,
262 .llseek = seq_lseek,
263 .release = single_release,
264};
265
266static void vi_remove_debugfs(struct vi *vi)
267{
268 debugfs_remove_recursive(vi->debugdir);
269 vi->debugdir = NULL;
270}
271
272static void vi_create_debugfs(struct vi *vi)
273{
274 struct dentry *ret;
275 char tegra_vi_name[20];
276 char debugfs_file_name[20];
277
278
279 snprintf(tegra_vi_name, sizeof(tegra_vi_name), "%s", TEGRA_VI_NAME);
280
281 vi->debugdir = debugfs_create_dir(tegra_vi_name, NULL);
282 if (!vi->debugdir) {
283 dev_err(&vi->ndev->dev,
284 "%s: failed to create %s directory",
285 __func__, tegra_vi_name);
286 goto create_debugfs_fail;
287 }
288
289 snprintf(debugfs_file_name, sizeof(debugfs_file_name), "%s", "vi_out");
290
291 ret = debugfs_create_file(debugfs_file_name, S_IRUGO,
292 vi->debugdir, vi, &vi_out_fops);
293 if (!ret) {
294 dev_err(&vi->ndev->dev,
295 "%s: failed to create %s", __func__, debugfs_file_name);
296 goto create_debugfs_fail;
297 }
298
299 return;
300
301create_debugfs_fail:
302 dev_err(&vi->ndev->dev, "%s: could not create debugfs", __func__);
303 vi_remove_debugfs(vi);
304}
305
306static int nvhost_vi_slcg_handler(struct notifier_block *nb,
307 unsigned long action, void *data)
308{
309 struct clk *clk;
310 int ret = 0;
311
312 struct nvhost_device_data *pdata =
313 container_of(nb, struct nvhost_device_data,
314 toggle_slcg_notifier);
315 struct vi *tegra_vi = (struct vi *)pdata->private_data;
316
317 if (tegra_vi->mc_vi.pg_mode)
318 return NOTIFY_OK;
319
320 clk = clk_get(NULL, "pll_d");
321 if (IS_ERR(clk))
322 return -EINVAL;
323
324 /* Make CSI sourced from PLL_D */
325 ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
326 if (ret) {
327 dev_err(&pdata->pdev->dev,
328 "%s: failed to select CSI source pll_d: %d\n",
329 __func__, ret);
330 return ret;
331 }
332
333 /* Enable PLL_D */
334 ret = clk_prepare_enable(clk);
335 if (ret) {
336 dev_err(&pdata->pdev->dev, "Can't enable pll_d: %d\n", ret);
337 return ret;
338 }
339
340 udelay(1);
341
342 /* Disable PLL_D */
343 clk_disable_unprepare(clk);
344
345 /* Restore CSI source */
346 ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
347 if (ret) {
348 dev_err(&pdata->pdev->dev,
349 "%s: failed to restore csi source: %d\n",
350 __func__, ret);
351 return ret;
352 }
353
354 clk_put(clk);
355
356 return NOTIFY_OK;
357}
358
359static int vi_probe(struct platform_device *dev)
360{
361 int err = 0;
362 struct nvhost_device_data *pdata = NULL;
363 struct tegra_t210_vi_data *data = NULL;
364 u8 num_channels;
365
366 if (dev->dev.of_node) {
367 const struct of_device_id *match;
368
369 match = of_match_device(tegra_vi_of_match, &dev->dev);
370 if (match) {
371 data = (struct tegra_t210_vi_data *)match->data;
372 pdata = data->info;
373 dev->dev.platform_data = pdata;
374 }
375 /* DT initializes it to -1, use below WAR to set correct value.
376 * TODO: Once proper fix for dev-id goes in, remove it.
377 */
378 dev->id = dev->dev.id;
379 } else
380 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
381
382 WARN_ON(!pdata);
383 if (!pdata) {
384 dev_info(&dev->dev, "no platform data\n");
385 return -ENODATA;
386 }
387
388 err = nvhost_check_bondout(pdata->bond_out_id);
389 if (err) {
390 dev_warn(&dev->dev, "No VI unit present. err:%d", err);
391 return err;
392 }
393
394 pdata->pdev = dev;
395 mutex_init(&pdata->lock);
396 platform_set_drvdata(dev, pdata);
397
398 dev_info(&dev->dev, "%s: ++\n", __func__);
399
400 tegra_vi = devm_kzalloc(&dev->dev, sizeof(struct vi), GFP_KERNEL);
401 if (!tegra_vi)
402 return -ENOMEM;
403
404 tegra_vi->ndev = dev;
405 tegra_vi->dev = &dev->dev;
406 err = nvhost_client_device_get_resources(dev);
407 if (err)
408 goto vi_probe_fail;
409
410 num_channels = 6;
411
412 err = tegra_vi_init_mfi(&tegra_vi->mfi_ctx, num_channels);
413 if (err)
414 goto vi_probe_fail;
415
416 if (!pdata->aperture[0]) {
417 dev_err(&dev->dev, "%s: failed to map register base\n",
418 __func__);
419 return -ENXIO;
420 }
421
422 /* call vi_intr_init and stats_work */
423 INIT_WORK(&tegra_vi->stats_work, vi_stats_worker);
424
425 err = vi_intr_init(tegra_vi);
426 if (err)
427 goto vi_mfi_init_fail;
428
429 vi_create_debugfs(tegra_vi);
430
431 i2c_ctrl = pdata->private_data;
432 pdata->private_data = tegra_vi;
433 mutex_init(&tegra_vi->update_la_lock);
434
435 /* Create I2C Devices according to settings from board file */
436 if (i2c_ctrl && i2c_ctrl->new_devices)
437 i2c_ctrl->new_devices(dev);
438
439 tegra_vi->reg = regulator_get(&tegra_vi->ndev->dev, "avdd_dsi_csi");
440 if (IS_ERR(tegra_vi->reg)) {
441 err = PTR_ERR(tegra_vi->reg);
442 if (err == -ENODEV)
443 dev_info(&tegra_vi->ndev->dev,
444 "%s: no regulator device\n", __func__);
445 else
446 dev_err(&tegra_vi->ndev->dev,
447 "%s: couldn't get regulator\n", __func__);
448 tegra_vi->reg = NULL;
449 if (tegra_platform_is_silicon())
450 goto camera_i2c_unregister;
451 }
452
453#ifdef CONFIG_TEGRA_CAMERA
454 tegra_vi->camera = tegra_camera_register(dev);
455 if (!tegra_vi->camera) {
456 dev_err(&dev->dev, "%s: can't register tegra_camera\n",
457 __func__);
458 goto vi_regulator_put;
459 }
460#endif
461
462 if (pdata->slcg_notifier_enable &&
463 (pdata->powergate_id != -1)) {
464 pdata->toggle_slcg_notifier.notifier_call =
465 &nvhost_vi_slcg_handler;
466
467 slcg_register_notifier(pdata->powergate_id,
468 &pdata->toggle_slcg_notifier);
469 }
470
471 nvhost_module_init(dev);
472
473 err = nvhost_client_device_init(dev);
474 if (err)
475 goto camera_unregister;
476
477 tegra_vi->mc_vi.vi = tegra_vi;
478 tegra_vi->mc_vi.csi = &tegra_vi->csi;
479 tegra_vi->mc_vi.reg = tegra_vi->reg;
480 tegra_vi->mc_vi.fops = data->vi_fops;
481 tegra_vi->csi.fops = data->csi_fops;
482 err = tegra_csi_media_controller_init(&tegra_vi->csi, dev);
483 if (err)
484 goto vi_mc_init_error;
485
486 err = tegra_vi_media_controller_init(&tegra_vi->mc_vi, dev);
487 if (err)
488 goto vi_mc_init_error;
489
490 return 0;
491
492vi_mc_init_error:
493 nvhost_client_device_release(dev);
494camera_unregister:
495#ifdef CONFIG_TEGRA_CAMERA
496 tegra_camera_unregister(tegra_vi->camera);
497vi_regulator_put:
498#endif
499
500 regulator_put(tegra_vi->reg);
501 tegra_vi->reg = NULL;
502
503camera_i2c_unregister:
504 if (i2c_ctrl && i2c_ctrl->remove_devices)
505 i2c_ctrl->remove_devices(dev);
506 pdata->private_data = i2c_ctrl;
507vi_mfi_init_fail:
508 tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
509vi_probe_fail:
510 dev_err(&dev->dev, "%s: failed\n", __func__);
511 return err;
512}
513
514static int __exit vi_remove(struct platform_device *dev)
515{
516#ifdef CONFIG_TEGRA_CAMERA
517 int err = 0;
518#endif
519 struct nvhost_device_data *pdata = platform_get_drvdata(dev);
520 struct vi *tegra_vi = (struct vi *)pdata->private_data;
521
522#ifdef CONFIG_PM
523 if (atomic_read(&dev->dev.power.usage_count) > 0)
524 return -EBUSY;
525#endif
526
527 dev_info(&dev->dev, "%s: ++\n", __func__);
528
529#if defined(CONFIG_TEGRA_ISOMGR)
530 if (tegra_vi->isomgr_handle)
531 vi_isomgr_unregister(tegra_vi);
532#endif
533
534 tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
535
536 vi_remove_debugfs(tegra_vi);
537
538 tegra_vi_media_controller_cleanup(&tegra_vi->mc_vi);
539
540 nvhost_client_device_release(dev);
541
542 if (pdata->slcg_notifier_enable &&
543 (pdata->powergate_id != -1))
544 slcg_unregister_notifier(pdata->powergate_id,
545 &pdata->toggle_slcg_notifier);
546
547 vi_intr_free(tegra_vi);
548
549 pdata->aperture[0] = NULL;
550#ifdef CONFIG_TEGRA_CAMERA
551 err = tegra_camera_unregister(tegra_vi->camera);
552 if (err)
553 return err;
554#endif
555
556#ifdef CONFIG_PM_GENERIC_DOMAINS
557 tegra_pd_remove_device(&dev->dev);
558#endif
559
560 regulator_put(tegra_vi->reg);
561 tegra_vi->reg = NULL;
562
563 /* Remove I2C Devices according to settings from board file */
564 if (i2c_ctrl && i2c_ctrl->remove_devices)
565 i2c_ctrl->remove_devices(dev);
566
567 pdata->private_data = i2c_ctrl;
568
569 return 0;
570}
571
572static struct platform_driver vi_driver = {
573 .probe = vi_probe,
574 .remove = __exit_p(vi_remove),
575 .driver = {
576 .owner = THIS_MODULE,
577 .name = "vi",
578#ifdef CONFIG_PM
579 .pm = &nvhost_module_pm_ops,
580#endif
581#ifdef CONFIG_OF
582 .of_match_table = tegra_vi_of_match,
583#endif
584 }
585};
586
587static struct of_device_id tegra_vi_domain_match[] = {
588 {.compatible = "nvidia,tegra210-ve-pd",
589 .data = (struct nvhost_device_data *)&t21_vi_info},
590 {},
591};
592
593static int __init vi_init(void)
594{
595 int ret;
596
597 ret = nvhost_domain_init(tegra_vi_domain_match);
598 if (ret)
599 return ret;
600
601 return platform_driver_register(&vi_driver);
602}
603
604static void __exit vi_exit(void)
605{
606 platform_driver_unregister(&vi_driver);
607}
608
609late_initcall(vi_init);
610module_exit(vi_exit);
611MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/tegra/vi/vi.h b/drivers/media/platform/tegra/vi/vi.h
new file mode 100644
index 000000000..a03057265
--- /dev/null
+++ b/drivers/media/platform/tegra/vi/vi.h
@@ -0,0 +1,128 @@
1/*
2 * drivers/video/tegra/host/vi/vi.h
3 *
4 * Tegra Graphics Host VI
5 *
6 * Copyright (c) 2012-2016, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef __NVHOST_VI_H__
22#define __NVHOST_VI_H__
23
24#include <linux/platform/tegra/isomgr.h>
25#include <linux/tegra-powergate.h>
26#include <linux/clk/tegra.h>
27
28#include "camera/vi/mc_common.h"
29#include "chip_support.h"
30
31#define VI_CFG_INTERRUPT_MASK_0 0x8c
32#define VI_CFG_INTERRUPT_STATUS_0 0x98
33
34#define CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0 0x850
35#define CSI_CSI_PIXEL_PARSER_A_STATUS_0 0x854
36#define PPA_FIFO_OVRF (1 << 5)
37
38#define CSI_CSI_PIXEL_PARSER_B_INTERRUPT_MASK_0 0x884
39#define CSI_CSI_PIXEL_PARSER_B_STATUS_0 0x888
40#define PPB_FIFO_OVRF (1 << 5)
41
42#define VI_CSI_0_ERROR_STATUS 0x184
43#define VI_CSI_1_ERROR_STATUS 0x284
44#define VI_CSI_0_WD_CTRL 0x18c
45#define VI_CSI_1_WD_CTRL 0x28c
46#define VI_CSI_0_ERROR_INT_MASK_0 0x188
47#define VI_CSI_1_ERROR_INT_MASK_0 0x288
48
49#ifdef TEGRA_21X_OR_HIGHER_CONFIG
50#define VI_CSI_2_ERROR_STATUS 0x384
51#define VI_CSI_3_ERROR_STATUS 0x484
52#define VI_CSI_4_ERROR_STATUS 0x584
53#define VI_CSI_5_ERROR_STATUS 0x684
54
55#define VI_CSI_2_WD_CTRL 0x38c
56#define VI_CSI_3_WD_CTRL 0x48c
57#define VI_CSI_4_WD_CTRL 0x58c
58#define VI_CSI_5_WD_CTRL 0x68c
59
60#define VI_CSI_2_ERROR_INT_MASK_0 0x388
61#define VI_CSI_3_ERROR_INT_MASK_0 0x488
62#define VI_CSI_4_ERROR_INT_MASK_0 0x588
63#define VI_CSI_5_ERROR_INT_MASK_0 0x688
64
65#define CSI1_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0 0x1050
66#define CSI1_CSI_PIXEL_PARSER_A_STATUS_0 0x1054
67#define CSI1_CSI_PIXEL_PARSER_B_INTERRUPT_MASK_0 0x1084
68#define CSI1_CSI_PIXEL_PARSER_B_STATUS_0 0x1088
69#define CSI2_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0 0x1850
70#define CSI2_CSI_PIXEL_PARSER_A_STATUS_0 0x1854
71#define CSI2_CSI_PIXEL_PARSER_B_INTERRUPT_MASK_0 0x1884
72#define CSI2_CSI_PIXEL_PARSER_B_STATUS_0 0x1888
73
74#define NUM_VI_WATCHDOG 6
75#else
76#define NUM_VI_WATCHDOG 2
77#endif
78
79typedef void (*callback)(void *);
80
81struct tegra_vi_stats {
82 atomic_t overflow;
83};
84
85struct tegra_vi_mfi_ctx;
86
87struct vi {
88 struct tegra_camera *camera;
89 struct platform_device *ndev;
90 struct device *dev;
91 struct tegra_vi_data *data;
92 struct tegra_mc_vi mc_vi;
93 struct tegra_csi_device csi;
94
95 struct regulator *reg;
96 struct dentry *debugdir;
97 struct tegra_vi_stats vi_out;
98 struct work_struct stats_work;
99 struct tegra_vi_mfi_ctx *mfi_ctx;
100#if defined(CONFIG_TEGRA_ISOMGR)
101 tegra_isomgr_handle isomgr_handle;
102#endif
103 int vi_irq;
104 uint vi_bypass_bw;
105 uint max_bw;
106 struct mutex update_la_lock;
107 bool master_deinitialized;
108 bool tpg_opened;
109 bool sensor_opened;
110 bool bypass;
111};
112
113extern const struct file_operations tegra_vi_ctrl_ops;
114int nvhost_vi_prepare_poweroff(struct platform_device *);
115int nvhost_vi_finalize_poweron(struct platform_device *);
116
117void nvhost_vi_reset_all(struct platform_device *);
118struct vi *tegra_vi_get(void);
119int vi_v4l2_set_la(struct vi *tegra_vi, u32 vi_bypass_bw, bool is_ioctl);
120
121int tegra_vi_register_mfi_cb(callback cb, void *cb_arg);
122int tegra_vi_unregister_mfi_cb(void);
123
124bool tegra_vi_has_mfi_callback(void);
125int tegra_vi_mfi_event_notify(struct tegra_vi_mfi_ctx *mfi_ctx, u8 channel);
126int tegra_vi_init_mfi(struct tegra_vi_mfi_ctx **mfi_ctx, u8 num_channels);
127void tegra_vi_deinit_mfi(struct tegra_vi_mfi_ctx **mfi_ctx);
128#endif
diff --git a/drivers/media/platform/tegra/vi/vi_irq.c b/drivers/media/platform/tegra/vi/vi_irq.c
new file mode 100644
index 000000000..9f3cc3f3c
--- /dev/null
+++ b/drivers/media/platform/tegra/vi/vi_irq.c
@@ -0,0 +1,244 @@
1/*
2 * drivers/video/tegra/host/vi/vi_irq.c
3 *
4 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/interrupt.h>
18#include <linux/module.h>
19#include <linux/nvhost.h>
20
21#include "nvhost_acm.h"
22#include "vi/vi.h"
23#include "vi/vi_irq.h"
24
25static const int status_reg_table[] = {
26 VI_CFG_INTERRUPT_STATUS_0,
27 CSI_CSI_PIXEL_PARSER_A_STATUS_0,
28 CSI_CSI_PIXEL_PARSER_B_STATUS_0,
29 VI_CSI_0_ERROR_STATUS,
30 VI_CSI_1_ERROR_STATUS,
31#ifdef TEGRA_21X_OR_HIGHER_CONFIG
32 VI_CSI_2_ERROR_STATUS,
33 VI_CSI_3_ERROR_STATUS,
34 VI_CSI_4_ERROR_STATUS,
35 VI_CSI_5_ERROR_STATUS,
36 CSI1_CSI_PIXEL_PARSER_A_STATUS_0,
37 CSI1_CSI_PIXEL_PARSER_B_STATUS_0,
38 CSI2_CSI_PIXEL_PARSER_A_STATUS_0,
39 CSI2_CSI_PIXEL_PARSER_B_STATUS_0,
40#endif
41};
42
43static const int mask_reg_table[] = {
44 VI_CFG_INTERRUPT_MASK_0,
45 CSI_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0,
46 CSI_CSI_PIXEL_PARSER_B_INTERRUPT_MASK_0,
47 VI_CSI_0_ERROR_INT_MASK_0,
48 VI_CSI_1_ERROR_INT_MASK_0,
49 VI_CSI_0_WD_CTRL,
50 VI_CSI_1_WD_CTRL,
51#ifdef TEGRA_21X_OR_HIGHER_CONFIG
52 VI_CSI_2_WD_CTRL,
53 VI_CSI_3_WD_CTRL,
54 VI_CSI_4_WD_CTRL,
55 VI_CSI_5_WD_CTRL,
56 VI_CSI_2_ERROR_INT_MASK_0,
57 VI_CSI_3_ERROR_INT_MASK_0,
58 VI_CSI_4_ERROR_INT_MASK_0,
59 VI_CSI_5_ERROR_INT_MASK_0,
60 CSI1_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0,
61 CSI1_CSI_PIXEL_PARSER_B_INTERRUPT_MASK_0,
62 CSI2_CSI_PIXEL_PARSER_A_INTERRUPT_MASK_0,
63 CSI2_CSI_PIXEL_PARSER_B_INTERRUPT_MASK_0,
64#endif
65};
66
67static inline void clear_state(struct vi *tegra_vi, int addr)
68{
69 int val;
70
71 val = host1x_readl(tegra_vi->ndev, addr);
72 host1x_writel(tegra_vi->ndev, addr, val);
73}
74
75int vi_enable_irq(struct vi *tegra_vi)
76{
77 int i;
78
79 /* Mask all VI interrupt */
80 for (i = 0; i < ARRAY_SIZE(mask_reg_table); i++)
81 host1x_writel(tegra_vi->ndev, mask_reg_table[i], 0);
82
83 /* Clear all VI interrupt state registers */
84 for (i = 0; i < ARRAY_SIZE(status_reg_table); i++)
85 clear_state(tegra_vi, status_reg_table[i]);
86
87 enable_irq(tegra_vi->vi_irq);
88
89 return 0;
90
91}
92EXPORT_SYMBOL(vi_enable_irq);
93
94int vi_disable_irq(struct vi *tegra_vi)
95{
96 int i;
97
98 disable_irq(tegra_vi->vi_irq);
99
100 /* Mask all VI interrupt */
101 for (i = 0; i < ARRAY_SIZE(mask_reg_table); i++)
102 host1x_writel(tegra_vi->ndev, mask_reg_table[i], 0);
103
104 /* Clear all VI interrupt state registers */
105 for (i = 0; i < ARRAY_SIZE(status_reg_table); i++)
106 clear_state(tegra_vi, status_reg_table[i]);
107
108 return 0;
109}
110EXPORT_SYMBOL(vi_disable_irq);
111
112static irqreturn_t vi_checkwd(struct vi *tegra_vi, int stream)
113{
114 int err_addr, wd_addr, val;
115
116 switch (stream) {
117 case 0:
118 err_addr = VI_CSI_0_ERROR_STATUS;
119 wd_addr = VI_CSI_0_WD_CTRL;
120 break;
121 case 1:
122 err_addr = VI_CSI_1_ERROR_STATUS;
123 wd_addr = VI_CSI_1_WD_CTRL;
124 break;
125#ifdef TEGRA_21X_OR_HIGHER_CONFIG
126 case 2:
127 err_addr = VI_CSI_2_ERROR_STATUS;
128 wd_addr = VI_CSI_2_WD_CTRL;
129 break;
130 case 3:
131 err_addr = VI_CSI_3_ERROR_STATUS;
132 wd_addr = VI_CSI_3_WD_CTRL;
133 break;
134 case 4:
135 err_addr = VI_CSI_4_ERROR_STATUS;
136 wd_addr = VI_CSI_4_WD_CTRL;
137 break;
138 case 5:
139 err_addr = VI_CSI_5_ERROR_STATUS;
140 wd_addr = VI_CSI_5_WD_CTRL;
141 break;
142#endif
143 default:
144 return IRQ_NONE;
145 }
146
147 val = host1x_readl(tegra_vi->ndev, err_addr);
148 if (val & 0x20) {
149 host1x_writel(tegra_vi->ndev, wd_addr, 0);
150 host1x_writel(tegra_vi->ndev, err_addr, 0x20);
151 tegra_vi_mfi_event_notify(tegra_vi->mfi_ctx, stream);
152 return IRQ_HANDLED;
153 }
154
155 return IRQ_NONE;
156}
157
158static irqreturn_t vi_isr(int irq, void *dev_id)
159{
160 struct vi *tegra_vi = (struct vi *)dev_id;
161 int i, val;
162 irqreturn_t result;
163
164 for (i = 0; i < NUM_VI_WATCHDOG; i++) {
165 result = vi_checkwd(tegra_vi, i);
166 if (result == IRQ_HANDLED)
167 goto handled;
168 }
169
170 dev_dbg(&tegra_vi->ndev->dev, "%s: ++", __func__);
171
172 val = host1x_readl(tegra_vi->ndev, CSI_CSI_PIXEL_PARSER_A_STATUS_0);
173
174 /* changes required as per t124 register spec */
175 if (val & PPA_FIFO_OVRF)
176 atomic_inc(&(tegra_vi->vi_out.overflow));
177
178 /* Disable IRQ */
179 vi_disable_irq(tegra_vi);
180
181 schedule_work(&tegra_vi->stats_work);
182
183handled:
184 return IRQ_HANDLED;
185}
186EXPORT_SYMBOL(vi_isr);
187
188void vi_stats_worker(struct work_struct *work)
189{
190 struct vi *tegra_vi = container_of(work, struct vi, stats_work);
191
192 dev_dbg(&tegra_vi->ndev->dev,
193 "%s: vi_out dropped data %u times", __func__,
194 atomic_read(&(tegra_vi->vi_out.overflow)));
195
196 /* Enable IRQ's */
197 vi_enable_irq(tegra_vi);
198}
199EXPORT_SYMBOL(vi_stats_worker);
200
201int vi_intr_init(struct vi *tegra_vi)
202{
203 struct platform_device *ndev = tegra_vi->ndev;
204
205 /* Interrupt resources are only associated with
206 * master dev vi.0 so irq must be programmed
207 * with it only.
208 */
209 int ret;
210
211 dev_dbg(&tegra_vi->ndev->dev, "%s: ++", __func__);
212
213 tegra_vi->vi_irq = platform_get_irq(ndev, 0);
214 if (IS_ERR_VALUE(tegra_vi->vi_irq)) {
215 dev_err(&tegra_vi->ndev->dev, "missing camera irq\n");
216 return -ENXIO;
217 }
218
219 ret = request_irq(tegra_vi->vi_irq,
220 vi_isr,
221 IRQF_SHARED,
222 dev_name(&tegra_vi->ndev->dev),
223 tegra_vi);
224 if (ret) {
225 dev_err(&tegra_vi->ndev->dev, "failed to get irq\n");
226 return -EBUSY;
227 }
228
229 disable_irq(tegra_vi->vi_irq);
230
231 return 0;
232}
233EXPORT_SYMBOL(vi_intr_init);
234
235int vi_intr_free(struct vi *tegra_vi)
236{
237 dev_dbg(&tegra_vi->ndev->dev, "%s: ++", __func__);
238
239 free_irq(tegra_vi->vi_irq, tegra_vi);
240
241 return 0;
242}
243EXPORT_SYMBOL(vi_intr_free);
244
diff --git a/drivers/media/platform/tegra/vi/vi_irq.h b/drivers/media/platform/tegra/vi/vi_irq.h
new file mode 100644
index 000000000..26fed8a00
--- /dev/null
+++ b/drivers/media/platform/tegra/vi/vi_irq.h
@@ -0,0 +1,26 @@
1/*
2 * drivers/video/tegra/host/vi/vi_irq.h
3 *
4 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __DRIVERS_VIDEO_VI_IRQ_H
18#define __DRIVERS_VIDEO_VI_IRQ_H
19
20int vi_intr_init(struct vi *vi);
21int vi_intr_free(struct vi *vi);
22void vi_stats_worker(struct work_struct *work);
23int vi_enable_irq(struct vi *vi);
24int vi_disable_irq(struct vi *vi);
25#endif
26