1
2
3
4
5
6#include <linux/bitmap.h>
7#include <linux/clk.h>
8#include <linux/delay.h>
9#include <linux/host1x.h>
10#include <linux/lcm.h>
11#include <linux/list.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/platform_device.h>
16#include <linux/regulator/consumer.h>
17#include <linux/pm_runtime.h>
18#include <linux/slab.h>
19
20#include <media/v4l2-event.h>
21#include <media/v4l2-fh.h>
22#include <media/v4l2-fwnode.h>
23#include <media/v4l2-ioctl.h>
24#include <media/videobuf2-dma-contig.h>
25
26#include <soc/tegra/pmc.h>
27
28#include "vi.h"
29#include "video.h"
30
31#define SURFACE_ALIGN_BYTES 64
32#define MAX_CID_CONTROLS 1
33
34static const struct tegra_video_format tegra_default_format = {
35 .img_dt = TEGRA_IMAGE_DT_RAW10,
36 .bit_width = 10,
37 .code = MEDIA_BUS_FMT_SRGGB10_1X10,
38 .bpp = 2,
39 .img_fmt = TEGRA_IMAGE_FORMAT_DEF,
40 .fourcc = V4L2_PIX_FMT_SRGGB10,
41};
42
43static inline struct tegra_vi *
44host1x_client_to_vi(struct host1x_client *client)
45{
46 return container_of(client, struct tegra_vi, client);
47}
48
49static inline struct tegra_channel_buffer *
50to_tegra_channel_buffer(struct vb2_v4l2_buffer *vb)
51{
52 return container_of(vb, struct tegra_channel_buffer, buf);
53}
54
55static int tegra_get_format_idx_by_code(struct tegra_vi *vi,
56 unsigned int code)
57{
58 unsigned int i;
59
60 for (i = 0; i < vi->soc->nformats; ++i) {
61 if (vi->soc->video_formats[i].code == code)
62 return i;
63 }
64
65 return -1;
66}
67
68static u32 tegra_get_format_fourcc_by_idx(struct tegra_vi *vi,
69 unsigned int index)
70{
71 if (index >= vi->soc->nformats)
72 return -EINVAL;
73
74 return vi->soc->video_formats[index].fourcc;
75}
76
77static const struct tegra_video_format *
78tegra_get_format_by_fourcc(struct tegra_vi *vi, u32 fourcc)
79{
80 unsigned int i;
81
82 for (i = 0; i < vi->soc->nformats; ++i) {
83 if (vi->soc->video_formats[i].fourcc == fourcc)
84 return &vi->soc->video_formats[i];
85 }
86
87 return NULL;
88}
89
90
91
92
93static int tegra_channel_queue_setup(struct vb2_queue *vq,
94 unsigned int *nbuffers,
95 unsigned int *nplanes,
96 unsigned int sizes[],
97 struct device *alloc_devs[])
98{
99 struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
100
101 if (*nplanes)
102 return sizes[0] < chan->format.sizeimage ? -EINVAL : 0;
103
104 *nplanes = 1;
105 sizes[0] = chan->format.sizeimage;
106 alloc_devs[0] = chan->vi->dev;
107
108 return 0;
109}
110
111static int tegra_channel_buffer_prepare(struct vb2_buffer *vb)
112{
113 struct tegra_vi_channel *chan = vb2_get_drv_priv(vb->vb2_queue);
114 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
115 struct tegra_channel_buffer *buf = to_tegra_channel_buffer(vbuf);
116 unsigned long size = chan->format.sizeimage;
117
118 if (vb2_plane_size(vb, 0) < size) {
119 v4l2_err(chan->video.v4l2_dev,
120 "buffer too small (%lu < %lu)\n",
121 vb2_plane_size(vb, 0), size);
122 return -EINVAL;
123 }
124
125 vb2_set_plane_payload(vb, 0, size);
126 buf->chan = chan;
127 buf->addr = vb2_dma_contig_plane_dma_addr(vb, 0);
128
129 return 0;
130}
131
132static void tegra_channel_buffer_queue(struct vb2_buffer *vb)
133{
134 struct tegra_vi_channel *chan = vb2_get_drv_priv(vb->vb2_queue);
135 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
136 struct tegra_channel_buffer *buf = to_tegra_channel_buffer(vbuf);
137
138
139 spin_lock(&chan->start_lock);
140 list_add_tail(&buf->queue, &chan->capture);
141 spin_unlock(&chan->start_lock);
142
143
144 wake_up_interruptible(&chan->start_wait);
145}
146
147struct v4l2_subdev *
148tegra_channel_get_remote_subdev(struct tegra_vi_channel *chan)
149{
150 struct media_pad *pad;
151 struct v4l2_subdev *subdev;
152 struct media_entity *entity;
153
154 pad = media_entity_remote_pad(&chan->pad);
155 entity = pad->entity;
156 subdev = media_entity_to_v4l2_subdev(entity);
157
158 return subdev;
159}
160
161int tegra_channel_set_stream(struct tegra_vi_channel *chan, bool on)
162{
163 struct v4l2_subdev *subdev;
164 int ret;
165
166
167 subdev = tegra_channel_get_remote_subdev(chan);
168 ret = v4l2_subdev_call(subdev, video, s_stream, on);
169 if (on && ret < 0 && ret != -ENOIOCTLCMD)
170 return ret;
171
172 return 0;
173}
174
175void tegra_channel_release_buffers(struct tegra_vi_channel *chan,
176 enum vb2_buffer_state state)
177{
178 struct tegra_channel_buffer *buf, *nbuf;
179
180 spin_lock(&chan->start_lock);
181 list_for_each_entry_safe(buf, nbuf, &chan->capture, queue) {
182 vb2_buffer_done(&buf->buf.vb2_buf, state);
183 list_del(&buf->queue);
184 }
185 spin_unlock(&chan->start_lock);
186
187 spin_lock(&chan->done_lock);
188 list_for_each_entry_safe(buf, nbuf, &chan->done, queue) {
189 vb2_buffer_done(&buf->buf.vb2_buf, state);
190 list_del(&buf->queue);
191 }
192 spin_unlock(&chan->done_lock);
193}
194
195static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
196{
197 struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
198 int ret;
199
200 ret = pm_runtime_get_sync(chan->vi->dev);
201 if (ret < 0) {
202 dev_err(chan->vi->dev, "failed to get runtime PM: %d\n", ret);
203 pm_runtime_put_noidle(chan->vi->dev);
204 return ret;
205 }
206
207 ret = chan->vi->ops->vi_start_streaming(vq, count);
208 if (ret < 0)
209 pm_runtime_put(chan->vi->dev);
210
211 return ret;
212}
213
214static void tegra_channel_stop_streaming(struct vb2_queue *vq)
215{
216 struct tegra_vi_channel *chan = vb2_get_drv_priv(vq);
217
218 chan->vi->ops->vi_stop_streaming(vq);
219 pm_runtime_put(chan->vi->dev);
220}
221
222static const struct vb2_ops tegra_channel_queue_qops = {
223 .queue_setup = tegra_channel_queue_setup,
224 .buf_prepare = tegra_channel_buffer_prepare,
225 .buf_queue = tegra_channel_buffer_queue,
226 .wait_prepare = vb2_ops_wait_prepare,
227 .wait_finish = vb2_ops_wait_finish,
228 .start_streaming = tegra_channel_start_streaming,
229 .stop_streaming = tegra_channel_stop_streaming,
230};
231
232
233
234
235static int tegra_channel_querycap(struct file *file, void *fh,
236 struct v4l2_capability *cap)
237{
238 struct tegra_vi_channel *chan = video_drvdata(file);
239
240 strscpy(cap->driver, "tegra-video", sizeof(cap->driver));
241 strscpy(cap->card, chan->video.name, sizeof(cap->card));
242 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
243 dev_name(chan->vi->dev));
244
245 return 0;
246}
247
248static int tegra_channel_g_parm(struct file *file, void *fh,
249 struct v4l2_streamparm *a)
250{
251 struct tegra_vi_channel *chan = video_drvdata(file);
252 struct v4l2_subdev *subdev;
253
254 subdev = tegra_channel_get_remote_subdev(chan);
255 return v4l2_g_parm_cap(&chan->video, subdev, a);
256}
257
258static int tegra_channel_s_parm(struct file *file, void *fh,
259 struct v4l2_streamparm *a)
260{
261 struct tegra_vi_channel *chan = video_drvdata(file);
262 struct v4l2_subdev *subdev;
263
264 subdev = tegra_channel_get_remote_subdev(chan);
265 return v4l2_s_parm_cap(&chan->video, subdev, a);
266}
267
268static int tegra_channel_enum_framesizes(struct file *file, void *fh,
269 struct v4l2_frmsizeenum *sizes)
270{
271 int ret;
272 struct tegra_vi_channel *chan = video_drvdata(file);
273 struct v4l2_subdev *subdev;
274 const struct tegra_video_format *fmtinfo;
275 struct v4l2_subdev_frame_size_enum fse = {
276 .index = sizes->index,
277 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
278 };
279
280 fmtinfo = tegra_get_format_by_fourcc(chan->vi, sizes->pixel_format);
281 if (!fmtinfo)
282 return -EINVAL;
283
284 fse.code = fmtinfo->code;
285
286 subdev = tegra_channel_get_remote_subdev(chan);
287 ret = v4l2_subdev_call(subdev, pad, enum_frame_size, NULL, &fse);
288 if (ret)
289 return ret;
290
291 sizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
292 sizes->discrete.width = fse.max_width;
293 sizes->discrete.height = fse.max_height;
294
295 return 0;
296}
297
298static int tegra_channel_enum_frameintervals(struct file *file, void *fh,
299 struct v4l2_frmivalenum *ivals)
300{
301 int ret;
302 struct tegra_vi_channel *chan = video_drvdata(file);
303 struct v4l2_subdev *subdev;
304 const struct tegra_video_format *fmtinfo;
305 struct v4l2_subdev_frame_interval_enum fie = {
306 .index = ivals->index,
307 .width = ivals->width,
308 .height = ivals->height,
309 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
310 };
311
312 fmtinfo = tegra_get_format_by_fourcc(chan->vi, ivals->pixel_format);
313 if (!fmtinfo)
314 return -EINVAL;
315
316 fie.code = fmtinfo->code;
317
318 subdev = tegra_channel_get_remote_subdev(chan);
319 ret = v4l2_subdev_call(subdev, pad, enum_frame_interval, NULL, &fie);
320 if (ret)
321 return ret;
322
323 ivals->type = V4L2_FRMIVAL_TYPE_DISCRETE;
324 ivals->discrete.numerator = fie.interval.numerator;
325 ivals->discrete.denominator = fie.interval.denominator;
326
327 return 0;
328}
329
330static int tegra_channel_enum_format(struct file *file, void *fh,
331 struct v4l2_fmtdesc *f)
332{
333 struct tegra_vi_channel *chan = video_drvdata(file);
334 unsigned int index = 0, i;
335 unsigned long *fmts_bitmap = chan->tpg_fmts_bitmap;
336
337 if (f->index >= bitmap_weight(fmts_bitmap, MAX_FORMAT_NUM))
338 return -EINVAL;
339
340 for (i = 0; i < f->index + 1; i++, index++)
341 index = find_next_bit(fmts_bitmap, MAX_FORMAT_NUM, index);
342
343 f->pixelformat = tegra_get_format_fourcc_by_idx(chan->vi, index - 1);
344
345 return 0;
346}
347
348static int tegra_channel_get_format(struct file *file, void *fh,
349 struct v4l2_format *format)
350{
351 struct tegra_vi_channel *chan = video_drvdata(file);
352
353 format->fmt.pix = chan->format;
354
355 return 0;
356}
357
358static void tegra_channel_fmt_align(struct tegra_vi_channel *chan,
359 struct v4l2_pix_format *pix,
360 unsigned int bpp)
361{
362 unsigned int align;
363 unsigned int min_width;
364 unsigned int max_width;
365 unsigned int width;
366 unsigned int min_bpl;
367 unsigned int max_bpl;
368 unsigned int bpl;
369
370
371
372
373
374
375 align = lcm(SURFACE_ALIGN_BYTES, bpp);
376 min_width = roundup(TEGRA_MIN_WIDTH, align);
377 max_width = rounddown(TEGRA_MAX_WIDTH, align);
378 width = roundup(pix->width * bpp, align);
379
380 pix->width = clamp(width, min_width, max_width) / bpp;
381 pix->height = clamp(pix->height, TEGRA_MIN_HEIGHT, TEGRA_MAX_HEIGHT);
382
383
384
385
386
387
388 min_bpl = pix->width * bpp;
389 max_bpl = rounddown(TEGRA_MAX_WIDTH, SURFACE_ALIGN_BYTES);
390 bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES);
391
392 pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
393 pix->sizeimage = pix->bytesperline * pix->height;
394}
395
396static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
397 struct v4l2_pix_format *pix)
398{
399 const struct tegra_video_format *fmtinfo;
400 struct v4l2_subdev *subdev;
401 struct v4l2_subdev_format fmt;
402 struct v4l2_subdev_pad_config *pad_cfg;
403
404 subdev = tegra_channel_get_remote_subdev(chan);
405 pad_cfg = v4l2_subdev_alloc_pad_config(subdev);
406 if (!pad_cfg)
407 return -ENOMEM;
408
409
410
411
412 fmtinfo = tegra_get_format_by_fourcc(chan->vi, pix->pixelformat);
413 if (!fmtinfo) {
414 pix->pixelformat = chan->format.pixelformat;
415 pix->colorspace = chan->format.colorspace;
416 fmtinfo = tegra_get_format_by_fourcc(chan->vi,
417 pix->pixelformat);
418 }
419
420 pix->field = V4L2_FIELD_NONE;
421 fmt.which = V4L2_SUBDEV_FORMAT_TRY;
422 fmt.pad = 0;
423 v4l2_fill_mbus_format(&fmt.format, pix, fmtinfo->code);
424 v4l2_subdev_call(subdev, pad, set_fmt, pad_cfg, &fmt);
425 v4l2_fill_pix_format(pix, &fmt.format);
426 tegra_channel_fmt_align(chan, pix, fmtinfo->bpp);
427
428 v4l2_subdev_free_pad_config(pad_cfg);
429
430 return 0;
431}
432
433static int tegra_channel_try_format(struct file *file, void *fh,
434 struct v4l2_format *format)
435{
436 struct tegra_vi_channel *chan = video_drvdata(file);
437
438 return __tegra_channel_try_format(chan, &format->fmt.pix);
439}
440
441static int tegra_channel_set_format(struct file *file, void *fh,
442 struct v4l2_format *format)
443{
444 struct tegra_vi_channel *chan = video_drvdata(file);
445 const struct tegra_video_format *fmtinfo;
446 struct v4l2_subdev_format fmt;
447 struct v4l2_subdev *subdev;
448 struct v4l2_pix_format *pix = &format->fmt.pix;
449 int ret;
450
451 if (vb2_is_busy(&chan->queue))
452 return -EBUSY;
453
454
455 ret = __tegra_channel_try_format(chan, pix);
456 if (ret)
457 return ret;
458
459 fmtinfo = tegra_get_format_by_fourcc(chan->vi, pix->pixelformat);
460
461 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
462 fmt.pad = 0;
463 v4l2_fill_mbus_format(&fmt.format, pix, fmtinfo->code);
464 subdev = tegra_channel_get_remote_subdev(chan);
465 v4l2_subdev_call(subdev, pad, set_fmt, NULL, &fmt);
466 v4l2_fill_pix_format(pix, &fmt.format);
467 tegra_channel_fmt_align(chan, pix, fmtinfo->bpp);
468
469 chan->format = *pix;
470 chan->fmtinfo = fmtinfo;
471
472 return 0;
473}
474
475static int tegra_channel_enum_input(struct file *file, void *fh,
476 struct v4l2_input *inp)
477{
478
479 if (inp->index)
480 return -EINVAL;
481
482 inp->type = V4L2_INPUT_TYPE_CAMERA;
483 strscpy(inp->name, "Tegra TPG", sizeof(inp->name));
484
485 return 0;
486}
487
488static int tegra_channel_g_input(struct file *file, void *priv,
489 unsigned int *i)
490{
491 *i = 0;
492
493 return 0;
494}
495
496static int tegra_channel_s_input(struct file *file, void *priv,
497 unsigned int input)
498{
499 if (input > 0)
500 return -EINVAL;
501
502 return 0;
503}
504
505static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = {
506 .vidioc_querycap = tegra_channel_querycap,
507 .vidioc_g_parm = tegra_channel_g_parm,
508 .vidioc_s_parm = tegra_channel_s_parm,
509 .vidioc_enum_framesizes = tegra_channel_enum_framesizes,
510 .vidioc_enum_frameintervals = tegra_channel_enum_frameintervals,
511 .vidioc_enum_fmt_vid_cap = tegra_channel_enum_format,
512 .vidioc_g_fmt_vid_cap = tegra_channel_get_format,
513 .vidioc_s_fmt_vid_cap = tegra_channel_set_format,
514 .vidioc_try_fmt_vid_cap = tegra_channel_try_format,
515 .vidioc_enum_input = tegra_channel_enum_input,
516 .vidioc_g_input = tegra_channel_g_input,
517 .vidioc_s_input = tegra_channel_s_input,
518 .vidioc_reqbufs = vb2_ioctl_reqbufs,
519 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
520 .vidioc_querybuf = vb2_ioctl_querybuf,
521 .vidioc_qbuf = vb2_ioctl_qbuf,
522 .vidioc_dqbuf = vb2_ioctl_dqbuf,
523 .vidioc_create_bufs = vb2_ioctl_create_bufs,
524 .vidioc_expbuf = vb2_ioctl_expbuf,
525 .vidioc_streamon = vb2_ioctl_streamon,
526 .vidioc_streamoff = vb2_ioctl_streamoff,
527 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
528 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
529};
530
531
532
533
534static const struct v4l2_file_operations tegra_channel_fops = {
535 .owner = THIS_MODULE,
536 .unlocked_ioctl = video_ioctl2,
537 .open = v4l2_fh_open,
538 .release = vb2_fop_release,
539 .read = vb2_fop_read,
540 .poll = vb2_fop_poll,
541 .mmap = vb2_fop_mmap,
542};
543
544
545
546
547static int vi_s_ctrl(struct v4l2_ctrl *ctrl)
548{
549 struct tegra_vi_channel *chan = container_of(ctrl->handler,
550 struct tegra_vi_channel,
551 ctrl_handler);
552
553 switch (ctrl->id) {
554 case V4L2_CID_TEST_PATTERN:
555
556 chan->pg_mode = ctrl->val + 1;
557 break;
558 default:
559 return -EINVAL;
560 }
561
562 return 0;
563}
564
565static const struct v4l2_ctrl_ops vi_ctrl_ops = {
566 .s_ctrl = vi_s_ctrl,
567};
568
569static const char *const vi_pattern_strings[] = {
570 "Black/White Direct Mode",
571 "Color Patch Mode",
572};
573
574static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan)
575{
576 int ret;
577
578
579 v4l2_ctrl_new_std_menu_items(&chan->ctrl_handler, &vi_ctrl_ops,
580 V4L2_CID_TEST_PATTERN,
581 ARRAY_SIZE(vi_pattern_strings) - 1,
582 0, 0, vi_pattern_strings);
583 if (chan->ctrl_handler.error) {
584 dev_err(chan->vi->dev, "failed to add TPG ctrl handler: %d\n",
585 chan->ctrl_handler.error);
586 v4l2_ctrl_handler_free(&chan->ctrl_handler);
587 return chan->ctrl_handler.error;
588 }
589
590
591 ret = v4l2_ctrl_handler_setup(&chan->ctrl_handler);
592 if (ret < 0) {
593 dev_err(chan->vi->dev,
594 "failed to setup v4l2 ctrl handler: %d\n", ret);
595 return ret;
596 }
597
598 return 0;
599}
600
601
602static void vi_tpg_fmts_bitmap_init(struct tegra_vi_channel *chan)
603{
604 int index;
605
606 bitmap_zero(chan->tpg_fmts_bitmap, MAX_FORMAT_NUM);
607
608 index = tegra_get_format_idx_by_code(chan->vi,
609 MEDIA_BUS_FMT_SRGGB10_1X10);
610 bitmap_set(chan->tpg_fmts_bitmap, index, 1);
611
612 index = tegra_get_format_idx_by_code(chan->vi,
613 MEDIA_BUS_FMT_RGB888_1X32_PADHI);
614 bitmap_set(chan->tpg_fmts_bitmap, index, 1);
615}
616
617static void tegra_channel_cleanup(struct tegra_vi_channel *chan)
618{
619 v4l2_ctrl_handler_free(&chan->ctrl_handler);
620 media_entity_cleanup(&chan->video.entity);
621 host1x_syncpt_free(chan->mw_ack_sp);
622 host1x_syncpt_free(chan->frame_start_sp);
623 mutex_destroy(&chan->video_lock);
624}
625
626void tegra_channels_cleanup(struct tegra_vi *vi)
627{
628 struct tegra_vi_channel *chan, *tmp;
629
630 if (!vi)
631 return;
632
633 list_for_each_entry_safe(chan, tmp, &vi->vi_chans, list) {
634 tegra_channel_cleanup(chan);
635 list_del(&chan->list);
636 kfree(chan);
637 }
638}
639
640static int tegra_channel_init(struct tegra_vi_channel *chan)
641{
642 struct tegra_vi *vi = chan->vi;
643 struct tegra_video_device *vid = dev_get_drvdata(vi->client.host);
644 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
645 int ret;
646
647 mutex_init(&chan->video_lock);
648 INIT_LIST_HEAD(&chan->capture);
649 INIT_LIST_HEAD(&chan->done);
650 spin_lock_init(&chan->start_lock);
651 spin_lock_init(&chan->done_lock);
652 spin_lock_init(&chan->sp_incr_lock);
653 init_waitqueue_head(&chan->start_wait);
654 init_waitqueue_head(&chan->done_wait);
655
656
657 chan->fmtinfo = &tegra_default_format;
658 chan->format.pixelformat = chan->fmtinfo->fourcc;
659 chan->format.colorspace = V4L2_COLORSPACE_SRGB;
660 chan->format.field = V4L2_FIELD_NONE;
661 chan->format.width = TEGRA_DEF_WIDTH;
662 chan->format.height = TEGRA_DEF_HEIGHT;
663 chan->format.bytesperline = TEGRA_DEF_WIDTH * chan->fmtinfo->bpp;
664 chan->format.sizeimage = chan->format.bytesperline * TEGRA_DEF_HEIGHT;
665 tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp);
666
667 chan->frame_start_sp = host1x_syncpt_request(&vi->client, flags);
668 if (!chan->frame_start_sp) {
669 dev_err(vi->dev, "failed to request frame start syncpoint\n");
670 return -ENOMEM;
671 }
672
673 chan->mw_ack_sp = host1x_syncpt_request(&vi->client, flags);
674 if (!chan->mw_ack_sp) {
675 dev_err(vi->dev, "failed to request memory ack syncpoint\n");
676 ret = -ENOMEM;
677 goto free_fs_syncpt;
678 }
679
680
681 chan->pad.flags = MEDIA_PAD_FL_SINK;
682 ret = media_entity_pads_init(&chan->video.entity, 1, &chan->pad);
683 if (ret < 0) {
684 dev_err(vi->dev,
685 "failed to initialize media entity: %d\n", ret);
686 goto free_mw_ack_syncpt;
687 }
688
689 ret = v4l2_ctrl_handler_init(&chan->ctrl_handler, MAX_CID_CONTROLS);
690 if (chan->ctrl_handler.error) {
691 dev_err(vi->dev,
692 "failed to initialize v4l2 ctrl handler: %d\n", ret);
693 goto cleanup_media;
694 }
695
696
697 chan->video.fops = &tegra_channel_fops;
698 chan->video.v4l2_dev = &vid->v4l2_dev;
699 chan->video.release = video_device_release_empty;
700 chan->video.queue = &chan->queue;
701 snprintf(chan->video.name, sizeof(chan->video.name), "%s-%s-%u",
702 dev_name(vi->dev), "output", chan->portno);
703 chan->video.vfl_type = VFL_TYPE_VIDEO;
704 chan->video.vfl_dir = VFL_DIR_RX;
705 chan->video.ioctl_ops = &tegra_channel_ioctl_ops;
706 chan->video.ctrl_handler = &chan->ctrl_handler;
707 chan->video.lock = &chan->video_lock;
708 chan->video.device_caps = V4L2_CAP_VIDEO_CAPTURE |
709 V4L2_CAP_STREAMING |
710 V4L2_CAP_READWRITE;
711 video_set_drvdata(&chan->video, chan);
712
713 chan->queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
714 chan->queue.io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
715 chan->queue.lock = &chan->video_lock;
716 chan->queue.drv_priv = chan;
717 chan->queue.buf_struct_size = sizeof(struct tegra_channel_buffer);
718 chan->queue.ops = &tegra_channel_queue_qops;
719 chan->queue.mem_ops = &vb2_dma_contig_memops;
720 chan->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
721 chan->queue.min_buffers_needed = 2;
722 chan->queue.dev = vi->dev;
723 ret = vb2_queue_init(&chan->queue);
724 if (ret < 0) {
725 dev_err(vi->dev, "failed to initialize vb2 queue: %d\n", ret);
726 goto free_v4l2_ctrl_hdl;
727 }
728
729 return 0;
730
731free_v4l2_ctrl_hdl:
732 v4l2_ctrl_handler_free(&chan->ctrl_handler);
733cleanup_media:
734 media_entity_cleanup(&chan->video.entity);
735free_mw_ack_syncpt:
736 host1x_syncpt_free(chan->mw_ack_sp);
737free_fs_syncpt:
738 host1x_syncpt_free(chan->frame_start_sp);
739 return ret;
740}
741
742static int tegra_vi_tpg_channels_alloc(struct tegra_vi *vi)
743{
744 struct tegra_vi_channel *chan;
745 unsigned int port_num;
746 unsigned int nchannels = vi->soc->vi_max_channels;
747
748 for (port_num = 0; port_num < nchannels; port_num++) {
749
750
751
752
753
754
755 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
756 if (!chan)
757 return -ENOMEM;
758
759 chan->vi = vi;
760 chan->portno = port_num;
761 list_add_tail(&chan->list, &vi->vi_chans);
762 }
763
764 return 0;
765}
766
767static int tegra_vi_channels_init(struct tegra_vi *vi)
768{
769 struct tegra_vi_channel *chan;
770 int ret;
771
772 list_for_each_entry(chan, &vi->vi_chans, list) {
773 ret = tegra_channel_init(chan);
774 if (ret < 0) {
775 dev_err(vi->dev,
776 "failed to initialize channel-%d: %d\n",
777 chan->portno, ret);
778 goto cleanup;
779 }
780 }
781
782 return 0;
783
784cleanup:
785 list_for_each_entry_continue_reverse(chan, &vi->vi_chans, list)
786 tegra_channel_cleanup(chan);
787
788 return ret;
789}
790
791void tegra_v4l2_nodes_cleanup_tpg(struct tegra_video_device *vid)
792{
793 struct tegra_vi *vi = vid->vi;
794 struct tegra_csi *csi = vid->csi;
795 struct tegra_csi_channel *csi_chan;
796 struct tegra_vi_channel *chan;
797
798 list_for_each_entry(chan, &vi->vi_chans, list) {
799 video_unregister_device(&chan->video);
800 mutex_lock(&chan->video_lock);
801 vb2_queue_release(&chan->queue);
802 mutex_unlock(&chan->video_lock);
803 }
804
805 list_for_each_entry(csi_chan, &csi->csi_chans, list)
806 v4l2_device_unregister_subdev(&csi_chan->subdev);
807}
808
809int tegra_v4l2_nodes_setup_tpg(struct tegra_video_device *vid)
810{
811 struct tegra_vi *vi = vid->vi;
812 struct tegra_csi *csi = vid->csi;
813 struct tegra_vi_channel *vi_chan;
814 struct tegra_csi_channel *csi_chan;
815 u32 link_flags = MEDIA_LNK_FL_ENABLED;
816 int ret;
817
818 if (!vi || !csi)
819 return -ENODEV;
820
821 csi_chan = list_first_entry(&csi->csi_chans,
822 struct tegra_csi_channel, list);
823
824 list_for_each_entry(vi_chan, &vi->vi_chans, list) {
825 struct media_entity *source = &csi_chan->subdev.entity;
826 struct media_entity *sink = &vi_chan->video.entity;
827 struct media_pad *source_pad = csi_chan->pads;
828 struct media_pad *sink_pad = &vi_chan->pad;
829
830 ret = v4l2_device_register_subdev(&vid->v4l2_dev,
831 &csi_chan->subdev);
832 if (ret) {
833 dev_err(vi->dev,
834 "failed to register subdev: %d\n", ret);
835 goto cleanup;
836 }
837
838 ret = video_register_device(&vi_chan->video,
839 VFL_TYPE_VIDEO, -1);
840 if (ret < 0) {
841 dev_err(vi->dev,
842 "failed to register video device: %d\n", ret);
843 goto cleanup;
844 }
845
846 dev_dbg(vi->dev, "creating %s:%u -> %s:%u link\n",
847 source->name, source_pad->index,
848 sink->name, sink_pad->index);
849
850 ret = media_create_pad_link(source, source_pad->index,
851 sink, sink_pad->index,
852 link_flags);
853 if (ret < 0) {
854 dev_err(vi->dev,
855 "failed to create %s:%u -> %s:%u link: %d\n",
856 source->name, source_pad->index,
857 sink->name, sink_pad->index, ret);
858 goto cleanup;
859 }
860
861 ret = tegra_channel_setup_ctrl_handler(vi_chan);
862 if (ret < 0)
863 goto cleanup;
864
865 v4l2_set_subdev_hostdata(&csi_chan->subdev, vi_chan);
866 vi_tpg_fmts_bitmap_init(vi_chan);
867 csi_chan = list_next_entry(csi_chan, list);
868 }
869
870 return 0;
871
872cleanup:
873 tegra_v4l2_nodes_cleanup_tpg(vid);
874 return ret;
875}
876
877static int __maybe_unused vi_runtime_resume(struct device *dev)
878{
879 struct tegra_vi *vi = dev_get_drvdata(dev);
880 int ret;
881
882 ret = regulator_enable(vi->vdd);
883 if (ret) {
884 dev_err(dev, "failed to enable VDD supply: %d\n", ret);
885 return ret;
886 }
887
888 ret = clk_set_rate(vi->clk, vi->soc->vi_max_clk_hz);
889 if (ret) {
890 dev_err(dev, "failed to set vi clock rate: %d\n", ret);
891 goto disable_vdd;
892 }
893
894 ret = clk_prepare_enable(vi->clk);
895 if (ret) {
896 dev_err(dev, "failed to enable vi clock: %d\n", ret);
897 goto disable_vdd;
898 }
899
900 return 0;
901
902disable_vdd:
903 regulator_disable(vi->vdd);
904 return ret;
905}
906
907static int __maybe_unused vi_runtime_suspend(struct device *dev)
908{
909 struct tegra_vi *vi = dev_get_drvdata(dev);
910
911 clk_disable_unprepare(vi->clk);
912
913 regulator_disable(vi->vdd);
914
915 return 0;
916}
917
918static int tegra_vi_init(struct host1x_client *client)
919{
920 struct tegra_video_device *vid = dev_get_drvdata(client->host);
921 struct tegra_vi *vi = host1x_client_to_vi(client);
922 struct tegra_vi_channel *chan, *tmp;
923 int ret;
924
925 vid->media_dev.hw_revision = vi->soc->hw_revision;
926 snprintf(vid->media_dev.bus_info, sizeof(vid->media_dev.bus_info),
927 "platform:%s", dev_name(vi->dev));
928
929 INIT_LIST_HEAD(&vi->vi_chans);
930
931 ret = tegra_vi_tpg_channels_alloc(vi);
932 if (ret < 0) {
933 dev_err(vi->dev, "failed to allocate tpg channels: %d\n", ret);
934 goto free_chans;
935 }
936
937 ret = tegra_vi_channels_init(vi);
938 if (ret < 0)
939 goto free_chans;
940
941 vid->vi = vi;
942
943 return 0;
944
945free_chans:
946 list_for_each_entry_safe(chan, tmp, &vi->vi_chans, list) {
947 list_del(&chan->list);
948 kfree(chan);
949 }
950
951 return ret;
952}
953
954static int tegra_vi_exit(struct host1x_client *client)
955{
956
957
958
959
960
961
962
963 return 0;
964}
965
966static const struct host1x_client_ops vi_client_ops = {
967 .init = tegra_vi_init,
968 .exit = tegra_vi_exit,
969};
970
971static int tegra_vi_probe(struct platform_device *pdev)
972{
973 struct tegra_vi *vi;
974 int ret;
975
976 vi = devm_kzalloc(&pdev->dev, sizeof(*vi), GFP_KERNEL);
977 if (!vi)
978 return -ENOMEM;
979
980 vi->iomem = devm_platform_ioremap_resource(pdev, 0);
981 if (IS_ERR(vi->iomem))
982 return PTR_ERR(vi->iomem);
983
984 vi->soc = of_device_get_match_data(&pdev->dev);
985
986 vi->clk = devm_clk_get(&pdev->dev, NULL);
987 if (IS_ERR(vi->clk)) {
988 ret = PTR_ERR(vi->clk);
989 dev_err(&pdev->dev, "failed to get vi clock: %d\n", ret);
990 return ret;
991 }
992
993 vi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
994 if (IS_ERR(vi->vdd)) {
995 ret = PTR_ERR(vi->vdd);
996 dev_err(&pdev->dev, "failed to get VDD supply: %d\n", ret);
997 return ret;
998 }
999
1000 if (!pdev->dev.pm_domain) {
1001 ret = -ENOENT;
1002 dev_warn(&pdev->dev, "PM domain is not attached: %d\n", ret);
1003 return ret;
1004 }
1005
1006 ret = devm_of_platform_populate(&pdev->dev);
1007 if (ret < 0) {
1008 dev_err(&pdev->dev,
1009 "failed to populate vi child device: %d\n", ret);
1010 return ret;
1011 }
1012
1013 vi->dev = &pdev->dev;
1014 vi->ops = vi->soc->ops;
1015 platform_set_drvdata(pdev, vi);
1016 pm_runtime_enable(&pdev->dev);
1017
1018
1019 INIT_LIST_HEAD(&vi->client.list);
1020 vi->client.ops = &vi_client_ops;
1021 vi->client.dev = &pdev->dev;
1022
1023 ret = host1x_client_register(&vi->client);
1024 if (ret < 0) {
1025 dev_err(&pdev->dev,
1026 "failed to register host1x client: %d\n", ret);
1027 goto rpm_disable;
1028 }
1029
1030 return 0;
1031
1032rpm_disable:
1033 pm_runtime_disable(&pdev->dev);
1034 return ret;
1035}
1036
1037static int tegra_vi_remove(struct platform_device *pdev)
1038{
1039 struct tegra_vi *vi = platform_get_drvdata(pdev);
1040 int err;
1041
1042 err = host1x_client_unregister(&vi->client);
1043 if (err < 0) {
1044 dev_err(&pdev->dev,
1045 "failed to unregister host1x client: %d\n", err);
1046 return err;
1047 }
1048
1049 pm_runtime_disable(&pdev->dev);
1050
1051 return 0;
1052}
1053
1054static const struct of_device_id tegra_vi_of_id_table[] = {
1055#if defined(CONFIG_ARCH_TEGRA_210_SOC)
1056 { .compatible = "nvidia,tegra210-vi", .data = &tegra210_vi_soc },
1057#endif
1058 { }
1059};
1060MODULE_DEVICE_TABLE(of, tegra_vi_of_id_table);
1061
1062static const struct dev_pm_ops tegra_vi_pm_ops = {
1063 SET_RUNTIME_PM_OPS(vi_runtime_suspend, vi_runtime_resume, NULL)
1064};
1065
1066struct platform_driver tegra_vi_driver = {
1067 .driver = {
1068 .name = "tegra-vi",
1069 .of_match_table = tegra_vi_of_id_table,
1070 .pm = &tegra_vi_pm_ops,
1071 },
1072 .probe = tegra_vi_probe,
1073 .remove = tegra_vi_remove,
1074};
1075