1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2005-2006 Micronas USA Inc.
4 */
5
6#include <linux/module.h>
7#include <linux/delay.h>
8#include <linux/sched.h>
9#include <linux/spinlock.h>
10#include <linux/slab.h>
11#include <linux/fs.h>
12#include <linux/unistd.h>
13#include <linux/time.h>
14#include <linux/vmalloc.h>
15#include <linux/pagemap.h>
16#include <linux/i2c.h>
17#include <linux/mutex.h>
18#include <linux/uaccess.h>
19#include <linux/videodev2.h>
20#include <media/v4l2-common.h>
21#include <media/v4l2-ioctl.h>
22#include <media/v4l2-subdev.h>
23#include <media/v4l2-event.h>
24#include <media/videobuf2-vmalloc.h>
25#include <media/i2c/saa7115.h>
26
27#include "go7007-priv.h"
28
29#define call_all(dev, o, f, args...) \
30 v4l2_device_call_until_err(dev, 0, o, f, ##args)
31
32static bool valid_pixelformat(u32 pixelformat)
33{
34 switch (pixelformat) {
35 case V4L2_PIX_FMT_MJPEG:
36 case V4L2_PIX_FMT_MPEG1:
37 case V4L2_PIX_FMT_MPEG2:
38 case V4L2_PIX_FMT_MPEG4:
39 return true;
40 default:
41 return false;
42 }
43}
44
45static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
46{
47 u8 *ptr = vb2_plane_vaddr(vb: &vb->vb.vb2_buf, plane_no: 0);
48
49 switch (format) {
50 case V4L2_PIX_FMT_MJPEG:
51 return V4L2_BUF_FLAG_KEYFRAME;
52 case V4L2_PIX_FMT_MPEG4:
53 switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) {
54 case 0:
55 return V4L2_BUF_FLAG_KEYFRAME;
56 case 1:
57 return V4L2_BUF_FLAG_PFRAME;
58 case 2:
59 return V4L2_BUF_FLAG_BFRAME;
60 default:
61 return 0;
62 }
63 case V4L2_PIX_FMT_MPEG1:
64 case V4L2_PIX_FMT_MPEG2:
65 switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) {
66 case 1:
67 return V4L2_BUF_FLAG_KEYFRAME;
68 case 2:
69 return V4L2_BUF_FLAG_PFRAME;
70 case 3:
71 return V4L2_BUF_FLAG_BFRAME;
72 default:
73 return 0;
74 }
75 }
76
77 return 0;
78}
79
80static void get_resolution(struct go7007 *go, int *width, int *height)
81{
82 switch (go->standard) {
83 case GO7007_STD_NTSC:
84 *width = 720;
85 *height = 480;
86 break;
87 case GO7007_STD_PAL:
88 *width = 720;
89 *height = 576;
90 break;
91 case GO7007_STD_OTHER:
92 default:
93 *width = go->board_info->sensor_width;
94 *height = go->board_info->sensor_height;
95 break;
96 }
97}
98
99static void set_formatting(struct go7007 *go)
100{
101 if (go->format == V4L2_PIX_FMT_MJPEG) {
102 go->pali = 0;
103 go->aspect_ratio = GO7007_RATIO_1_1;
104 go->gop_size = 0;
105 go->ipb = 0;
106 go->closed_gop = 0;
107 go->repeat_seqhead = 0;
108 go->seq_header_enable = 0;
109 go->gop_header_enable = 0;
110 go->dvd_mode = 0;
111 return;
112 }
113
114 switch (go->format) {
115 case V4L2_PIX_FMT_MPEG1:
116 go->pali = 0;
117 break;
118 default:
119 case V4L2_PIX_FMT_MPEG2:
120 go->pali = 0x48;
121 break;
122 case V4L2_PIX_FMT_MPEG4:
123 /* For future reference: this is the list of MPEG4
124 * profiles that are available, although they are
125 * untested:
126 *
127 * Profile pali
128 * -------------- ----
129 * PROFILE_S_L0 0x08
130 * PROFILE_S_L1 0x01
131 * PROFILE_S_L2 0x02
132 * PROFILE_S_L3 0x03
133 * PROFILE_ARTS_L1 0x91
134 * PROFILE_ARTS_L2 0x92
135 * PROFILE_ARTS_L3 0x93
136 * PROFILE_ARTS_L4 0x94
137 * PROFILE_AS_L0 0xf0
138 * PROFILE_AS_L1 0xf1
139 * PROFILE_AS_L2 0xf2
140 * PROFILE_AS_L3 0xf3
141 * PROFILE_AS_L4 0xf4
142 * PROFILE_AS_L5 0xf5
143 */
144 go->pali = 0xf5;
145 break;
146 }
147 go->gop_size = v4l2_ctrl_g_ctrl(ctrl: go->mpeg_video_gop_size);
148 go->closed_gop = v4l2_ctrl_g_ctrl(ctrl: go->mpeg_video_gop_closure);
149 go->ipb = v4l2_ctrl_g_ctrl(ctrl: go->mpeg_video_b_frames) != 0;
150 go->bitrate = v4l2_ctrl_g_ctrl(ctrl: go->mpeg_video_bitrate);
151 go->repeat_seqhead = v4l2_ctrl_g_ctrl(ctrl: go->mpeg_video_rep_seqheader);
152 go->gop_header_enable = 1;
153 go->dvd_mode = 0;
154 if (go->format == V4L2_PIX_FMT_MPEG2)
155 go->dvd_mode =
156 go->bitrate == 9800000 &&
157 go->gop_size == 15 &&
158 go->ipb == 0 &&
159 go->repeat_seqhead == 1 &&
160 go->closed_gop;
161
162 switch (v4l2_ctrl_g_ctrl(ctrl: go->mpeg_video_aspect_ratio)) {
163 default:
164 case V4L2_MPEG_VIDEO_ASPECT_1x1:
165 go->aspect_ratio = GO7007_RATIO_1_1;
166 break;
167 case V4L2_MPEG_VIDEO_ASPECT_4x3:
168 go->aspect_ratio = GO7007_RATIO_4_3;
169 break;
170 case V4L2_MPEG_VIDEO_ASPECT_16x9:
171 go->aspect_ratio = GO7007_RATIO_16_9;
172 break;
173 }
174}
175
176static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
177{
178 int sensor_height = 0, sensor_width = 0;
179 int width, height;
180
181 if (fmt != NULL && !valid_pixelformat(pixelformat: fmt->fmt.pix.pixelformat))
182 return -EINVAL;
183
184 get_resolution(go, width: &sensor_width, height: &sensor_height);
185
186 if (fmt == NULL) {
187 width = sensor_width;
188 height = sensor_height;
189 } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
190 if (fmt->fmt.pix.width > sensor_width)
191 width = sensor_width;
192 else if (fmt->fmt.pix.width < 144)
193 width = 144;
194 else
195 width = fmt->fmt.pix.width & ~0x0f;
196
197 if (fmt->fmt.pix.height > sensor_height)
198 height = sensor_height;
199 else if (fmt->fmt.pix.height < 96)
200 height = 96;
201 else
202 height = fmt->fmt.pix.height & ~0x0f;
203 } else {
204 width = fmt->fmt.pix.width;
205
206 if (width <= sensor_width / 4) {
207 width = sensor_width / 4;
208 height = sensor_height / 4;
209 } else if (width <= sensor_width / 2) {
210 width = sensor_width / 2;
211 height = sensor_height / 2;
212 } else {
213 width = sensor_width;
214 height = sensor_height;
215 }
216 width &= ~0xf;
217 height &= ~0xf;
218 }
219
220 if (fmt != NULL) {
221 u32 pixelformat = fmt->fmt.pix.pixelformat;
222
223 memset(fmt, 0, sizeof(*fmt));
224 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
225 fmt->fmt.pix.width = width;
226 fmt->fmt.pix.height = height;
227 fmt->fmt.pix.pixelformat = pixelformat;
228 fmt->fmt.pix.field = V4L2_FIELD_NONE;
229 fmt->fmt.pix.bytesperline = 0;
230 fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
231 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
232 }
233
234 if (try)
235 return 0;
236
237 if (fmt)
238 go->format = fmt->fmt.pix.pixelformat;
239 go->width = width;
240 go->height = height;
241 go->encoder_h_offset = go->board_info->sensor_h_offset;
242 go->encoder_v_offset = go->board_info->sensor_v_offset;
243
244 if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
245 struct v4l2_subdev_format format = {
246 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
247 };
248
249 format.format.code = MEDIA_BUS_FMT_FIXED;
250 format.format.width = fmt ? fmt->fmt.pix.width : width;
251 format.format.height = height;
252 go->encoder_h_halve = 0;
253 go->encoder_v_halve = 0;
254 go->encoder_subsample = 0;
255 call_all(&go->v4l2_dev, pad, set_fmt, NULL, &format);
256 } else {
257 if (width <= sensor_width / 4) {
258 go->encoder_h_halve = 1;
259 go->encoder_v_halve = 1;
260 go->encoder_subsample = 1;
261 } else if (width <= sensor_width / 2) {
262 go->encoder_h_halve = 1;
263 go->encoder_v_halve = 1;
264 go->encoder_subsample = 0;
265 } else {
266 go->encoder_h_halve = 0;
267 go->encoder_v_halve = 0;
268 go->encoder_subsample = 0;
269 }
270 }
271 return 0;
272}
273
274static int vidioc_querycap(struct file *file, void *priv,
275 struct v4l2_capability *cap)
276{
277 struct go7007 *go = video_drvdata(file);
278
279 strscpy(cap->driver, "go7007", sizeof(cap->driver));
280 strscpy(cap->card, go->name, sizeof(cap->card));
281 strscpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
282 return 0;
283}
284
285static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
286 struct v4l2_fmtdesc *fmt)
287{
288 switch (fmt->index) {
289 case 0:
290 fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
291 break;
292 case 1:
293 fmt->pixelformat = V4L2_PIX_FMT_MPEG1;
294 break;
295 case 2:
296 fmt->pixelformat = V4L2_PIX_FMT_MPEG2;
297 break;
298 case 3:
299 fmt->pixelformat = V4L2_PIX_FMT_MPEG4;
300 break;
301 default:
302 return -EINVAL;
303 }
304 return 0;
305}
306
307static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
308 struct v4l2_format *fmt)
309{
310 struct go7007 *go = video_drvdata(file);
311
312 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
313 fmt->fmt.pix.width = go->width;
314 fmt->fmt.pix.height = go->height;
315 fmt->fmt.pix.pixelformat = go->format;
316 fmt->fmt.pix.field = V4L2_FIELD_NONE;
317 fmt->fmt.pix.bytesperline = 0;
318 fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
319 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
320
321 return 0;
322}
323
324static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
325 struct v4l2_format *fmt)
326{
327 struct go7007 *go = video_drvdata(file);
328
329 return set_capture_size(go, fmt, try: 1);
330}
331
332static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
333 struct v4l2_format *fmt)
334{
335 struct go7007 *go = video_drvdata(file);
336
337 if (vb2_is_busy(q: &go->vidq))
338 return -EBUSY;
339
340 return set_capture_size(go, fmt, try: 0);
341}
342
343static int go7007_queue_setup(struct vb2_queue *q,
344 unsigned int *num_buffers, unsigned int *num_planes,
345 unsigned int sizes[], struct device *alloc_devs[])
346{
347 sizes[0] = GO7007_BUF_SIZE;
348 *num_planes = 1;
349
350 if (*num_buffers < 2)
351 *num_buffers = 2;
352
353 return 0;
354}
355
356static void go7007_buf_queue(struct vb2_buffer *vb)
357{
358 struct vb2_queue *vq = vb->vb2_queue;
359 struct go7007 *go = vb2_get_drv_priv(q: vq);
360 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
361 struct go7007_buffer *go7007_vb =
362 container_of(vbuf, struct go7007_buffer, vb);
363 unsigned long flags;
364
365 spin_lock_irqsave(&go->spinlock, flags);
366 list_add_tail(new: &go7007_vb->list, head: &go->vidq_active);
367 spin_unlock_irqrestore(lock: &go->spinlock, flags);
368}
369
370static int go7007_buf_prepare(struct vb2_buffer *vb)
371{
372 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
373 struct go7007_buffer *go7007_vb =
374 container_of(vbuf, struct go7007_buffer, vb);
375
376 go7007_vb->modet_active = 0;
377 go7007_vb->frame_offset = 0;
378 vb->planes[0].bytesused = 0;
379 return 0;
380}
381
382static void go7007_buf_finish(struct vb2_buffer *vb)
383{
384 struct vb2_queue *vq = vb->vb2_queue;
385 struct go7007 *go = vb2_get_drv_priv(q: vq);
386 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
387 struct go7007_buffer *go7007_vb =
388 container_of(vbuf, struct go7007_buffer, vb);
389 u32 frame_type_flag = get_frame_type_flag(vb: go7007_vb, format: go->format);
390
391 vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
392 V4L2_BUF_FLAG_PFRAME);
393 vbuf->flags |= frame_type_flag;
394 vbuf->field = V4L2_FIELD_NONE;
395}
396
397static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
398{
399 struct go7007 *go = vb2_get_drv_priv(q);
400 int ret;
401
402 set_formatting(go);
403 mutex_lock(&go->hw_lock);
404 go->next_seq = 0;
405 go->active_buf = NULL;
406 go->modet_event_status = 0;
407 if (go7007_start_encoder(go) < 0)
408 ret = -EIO;
409 else
410 ret = 0;
411 mutex_unlock(lock: &go->hw_lock);
412 if (ret)
413 return ret;
414 call_all(&go->v4l2_dev, video, s_stream, 1);
415 v4l2_ctrl_grab(ctrl: go->mpeg_video_gop_size, grabbed: true);
416 v4l2_ctrl_grab(ctrl: go->mpeg_video_gop_closure, grabbed: true);
417 v4l2_ctrl_grab(ctrl: go->mpeg_video_bitrate, grabbed: true);
418 v4l2_ctrl_grab(ctrl: go->mpeg_video_aspect_ratio, grabbed: true);
419 /* Turn on Capture LED */
420 if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
421 go7007_write_addr(go, 0x3c82, 0x0005);
422 return ret;
423}
424
425static void go7007_stop_streaming(struct vb2_queue *q)
426{
427 struct go7007 *go = vb2_get_drv_priv(q);
428 unsigned long flags;
429
430 go7007_stream_stop(go);
431 mutex_lock(&go->hw_lock);
432 go7007_reset_encoder(go);
433 mutex_unlock(lock: &go->hw_lock);
434 call_all(&go->v4l2_dev, video, s_stream, 0);
435
436 spin_lock_irqsave(&go->spinlock, flags);
437 INIT_LIST_HEAD(list: &go->vidq_active);
438 spin_unlock_irqrestore(lock: &go->spinlock, flags);
439 v4l2_ctrl_grab(ctrl: go->mpeg_video_gop_size, grabbed: false);
440 v4l2_ctrl_grab(ctrl: go->mpeg_video_gop_closure, grabbed: false);
441 v4l2_ctrl_grab(ctrl: go->mpeg_video_bitrate, grabbed: false);
442 v4l2_ctrl_grab(ctrl: go->mpeg_video_aspect_ratio, grabbed: false);
443 /* Turn on Capture LED */
444 if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
445 go7007_write_addr(go, 0x3c82, 0x000d);
446}
447
448static const struct vb2_ops go7007_video_qops = {
449 .queue_setup = go7007_queue_setup,
450 .buf_queue = go7007_buf_queue,
451 .buf_prepare = go7007_buf_prepare,
452 .buf_finish = go7007_buf_finish,
453 .start_streaming = go7007_start_streaming,
454 .stop_streaming = go7007_stop_streaming,
455 .wait_prepare = vb2_ops_wait_prepare,
456 .wait_finish = vb2_ops_wait_finish,
457};
458
459static int vidioc_g_parm(struct file *filp, void *priv,
460 struct v4l2_streamparm *parm)
461{
462 struct go7007 *go = video_drvdata(file: filp);
463 struct v4l2_fract timeperframe = {
464 .numerator = 1001 * go->fps_scale,
465 .denominator = go->sensor_framerate,
466 };
467
468 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
469 return -EINVAL;
470
471 parm->parm.capture.readbuffers = 2;
472 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
473 parm->parm.capture.timeperframe = timeperframe;
474
475 return 0;
476}
477
478static int vidioc_s_parm(struct file *filp, void *priv,
479 struct v4l2_streamparm *parm)
480{
481 struct go7007 *go = video_drvdata(file: filp);
482 unsigned int n, d;
483
484 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
485 return -EINVAL;
486
487 n = go->sensor_framerate *
488 parm->parm.capture.timeperframe.numerator;
489 d = 1001 * parm->parm.capture.timeperframe.denominator;
490 if (n != 0 && d != 0 && n > d)
491 go->fps_scale = (n + d/2) / d;
492 else
493 go->fps_scale = 1;
494
495 return vidioc_g_parm(filp, priv, parm);
496}
497
498/* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and
499 its resolution, when the device is not connected to TV.
500 This is were an API abuse, probably used by the lack of specific IOCTL's to
501 enumerate it, by the time the driver was written.
502
503 However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
504 and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
505
506 The two functions below implement the newer ioctls
507*/
508static int vidioc_enum_framesizes(struct file *filp, void *priv,
509 struct v4l2_frmsizeenum *fsize)
510{
511 struct go7007 *go = video_drvdata(file: filp);
512 int width, height;
513
514 if (fsize->index > 2)
515 return -EINVAL;
516
517 if (!valid_pixelformat(pixelformat: fsize->pixel_format))
518 return -EINVAL;
519
520 get_resolution(go, width: &width, height: &height);
521 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
522 fsize->discrete.width = (width >> fsize->index) & ~0xf;
523 fsize->discrete.height = (height >> fsize->index) & ~0xf;
524 return 0;
525}
526
527static int vidioc_enum_frameintervals(struct file *filp, void *priv,
528 struct v4l2_frmivalenum *fival)
529{
530 struct go7007 *go = video_drvdata(file: filp);
531 int width, height;
532 int i;
533
534 if (fival->index > 4)
535 return -EINVAL;
536
537 if (!valid_pixelformat(pixelformat: fival->pixel_format))
538 return -EINVAL;
539
540 if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) {
541 get_resolution(go, width: &width, height: &height);
542 for (i = 0; i <= 2; i++)
543 if (fival->width == ((width >> i) & ~0xf) &&
544 fival->height == ((height >> i) & ~0xf))
545 break;
546 if (i > 2)
547 return -EINVAL;
548 }
549 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
550 fival->discrete.numerator = 1001 * (fival->index + 1);
551 fival->discrete.denominator = go->sensor_framerate;
552 return 0;
553}
554
555static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
556{
557 struct go7007 *go = video_drvdata(file);
558
559 *std = go->std;
560 return 0;
561}
562
563static int go7007_s_std(struct go7007 *go)
564{
565 if (go->std & V4L2_STD_625_50) {
566 go->standard = GO7007_STD_PAL;
567 go->sensor_framerate = 25025;
568 } else {
569 go->standard = GO7007_STD_NTSC;
570 go->sensor_framerate = 30000;
571 }
572
573 call_all(&go->v4l2_dev, video, s_std, go->std);
574 set_capture_size(go, NULL, try: 0);
575 return 0;
576}
577
578static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
579{
580 struct go7007 *go = video_drvdata(file);
581
582 if (vb2_is_busy(q: &go->vidq))
583 return -EBUSY;
584
585 go->std = std;
586
587 return go7007_s_std(go);
588}
589
590static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
591{
592 struct go7007 *go = video_drvdata(file);
593
594 return call_all(&go->v4l2_dev, video, querystd, std);
595}
596
597static int vidioc_enum_input(struct file *file, void *priv,
598 struct v4l2_input *inp)
599{
600 struct go7007 *go = video_drvdata(file);
601
602 if (inp->index >= go->board_info->num_inputs)
603 return -EINVAL;
604
605 strscpy(inp->name, go->board_info->inputs[inp->index].name,
606 sizeof(inp->name));
607
608 /* If this board has a tuner, it will be the first input */
609 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
610 inp->index == 0)
611 inp->type = V4L2_INPUT_TYPE_TUNER;
612 else
613 inp->type = V4L2_INPUT_TYPE_CAMERA;
614
615 if (go->board_info->num_aud_inputs)
616 inp->audioset = (1 << go->board_info->num_aud_inputs) - 1;
617 else
618 inp->audioset = 0;
619 inp->tuner = 0;
620 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
621 inp->std = video_devdata(file)->tvnorms;
622 else
623 inp->std = 0;
624
625 return 0;
626}
627
628
629static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
630{
631 struct go7007 *go = video_drvdata(file);
632
633 *input = go->input;
634
635 return 0;
636}
637
638static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
639{
640 struct go7007 *go = video_drvdata(file);
641
642 if (a->index >= go->board_info->num_aud_inputs)
643 return -EINVAL;
644 strscpy(a->name, go->board_info->aud_inputs[a->index].name,
645 sizeof(a->name));
646 a->capability = V4L2_AUDCAP_STEREO;
647 return 0;
648}
649
650static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
651{
652 struct go7007 *go = video_drvdata(file);
653
654 a->index = go->aud_input;
655 strscpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
656 sizeof(a->name));
657 a->capability = V4L2_AUDCAP_STEREO;
658 return 0;
659}
660
661static int vidioc_s_audio(struct file *file, void *fh,
662 const struct v4l2_audio *a)
663{
664 struct go7007 *go = video_drvdata(file);
665
666 if (a->index >= go->board_info->num_aud_inputs)
667 return -EINVAL;
668 go->aud_input = a->index;
669 v4l2_subdev_call(go->sd_audio, audio, s_routing,
670 go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0);
671 return 0;
672}
673
674static void go7007_s_input(struct go7007 *go)
675{
676 unsigned int input = go->input;
677
678 v4l2_subdev_call(go->sd_video, video, s_routing,
679 go->board_info->inputs[input].video_input, 0,
680 go->board_info->video_config);
681 if (go->board_info->num_aud_inputs) {
682 int aud_input = go->board_info->inputs[input].audio_index;
683
684 v4l2_subdev_call(go->sd_audio, audio, s_routing,
685 go->board_info->aud_inputs[aud_input].audio_input, 0, 0);
686 go->aud_input = aud_input;
687 }
688}
689
690static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
691{
692 struct go7007 *go = video_drvdata(file);
693
694 if (input >= go->board_info->num_inputs)
695 return -EINVAL;
696 if (vb2_is_busy(q: &go->vidq))
697 return -EBUSY;
698
699 go->input = input;
700 go7007_s_input(go);
701
702 return 0;
703}
704
705static int vidioc_g_tuner(struct file *file, void *priv,
706 struct v4l2_tuner *t)
707{
708 struct go7007 *go = video_drvdata(file);
709
710 if (t->index != 0)
711 return -EINVAL;
712
713 strscpy(t->name, "Tuner", sizeof(t->name));
714 return call_all(&go->v4l2_dev, tuner, g_tuner, t);
715}
716
717static int vidioc_s_tuner(struct file *file, void *priv,
718 const struct v4l2_tuner *t)
719{
720 struct go7007 *go = video_drvdata(file);
721
722 if (t->index != 0)
723 return -EINVAL;
724
725 return call_all(&go->v4l2_dev, tuner, s_tuner, t);
726}
727
728static int vidioc_g_frequency(struct file *file, void *priv,
729 struct v4l2_frequency *f)
730{
731 struct go7007 *go = video_drvdata(file);
732
733 if (f->tuner)
734 return -EINVAL;
735
736 return call_all(&go->v4l2_dev, tuner, g_frequency, f);
737}
738
739static int vidioc_s_frequency(struct file *file, void *priv,
740 const struct v4l2_frequency *f)
741{
742 struct go7007 *go = video_drvdata(file);
743
744 if (f->tuner)
745 return -EINVAL;
746
747 return call_all(&go->v4l2_dev, tuner, s_frequency, f);
748}
749
750static int vidioc_log_status(struct file *file, void *priv)
751{
752 struct go7007 *go = video_drvdata(file);
753
754 v4l2_ctrl_log_status(file, fh: priv);
755 return call_all(&go->v4l2_dev, core, log_status);
756}
757
758static int vidioc_subscribe_event(struct v4l2_fh *fh,
759 const struct v4l2_event_subscription *sub)
760{
761
762 switch (sub->type) {
763 case V4L2_EVENT_MOTION_DET:
764 /* Allow for up to 30 events (1 second for NTSC) to be
765 * stored. */
766 return v4l2_event_subscribe(fh, sub, elems: 30, NULL);
767 default:
768 return v4l2_ctrl_subscribe_event(fh, sub);
769 }
770}
771
772
773static int go7007_s_ctrl(struct v4l2_ctrl *ctrl)
774{
775 struct go7007 *go =
776 container_of(ctrl->handler, struct go7007, hdl);
777 unsigned y;
778 u8 *mt;
779
780 switch (ctrl->id) {
781 case V4L2_CID_PIXEL_THRESHOLD0:
782 go->modet[0].pixel_threshold = ctrl->val;
783 break;
784 case V4L2_CID_MOTION_THRESHOLD0:
785 go->modet[0].motion_threshold = ctrl->val;
786 break;
787 case V4L2_CID_MB_THRESHOLD0:
788 go->modet[0].mb_threshold = ctrl->val;
789 break;
790 case V4L2_CID_PIXEL_THRESHOLD1:
791 go->modet[1].pixel_threshold = ctrl->val;
792 break;
793 case V4L2_CID_MOTION_THRESHOLD1:
794 go->modet[1].motion_threshold = ctrl->val;
795 break;
796 case V4L2_CID_MB_THRESHOLD1:
797 go->modet[1].mb_threshold = ctrl->val;
798 break;
799 case V4L2_CID_PIXEL_THRESHOLD2:
800 go->modet[2].pixel_threshold = ctrl->val;
801 break;
802 case V4L2_CID_MOTION_THRESHOLD2:
803 go->modet[2].motion_threshold = ctrl->val;
804 break;
805 case V4L2_CID_MB_THRESHOLD2:
806 go->modet[2].mb_threshold = ctrl->val;
807 break;
808 case V4L2_CID_PIXEL_THRESHOLD3:
809 go->modet[3].pixel_threshold = ctrl->val;
810 break;
811 case V4L2_CID_MOTION_THRESHOLD3:
812 go->modet[3].motion_threshold = ctrl->val;
813 break;
814 case V4L2_CID_MB_THRESHOLD3:
815 go->modet[3].mb_threshold = ctrl->val;
816 break;
817 case V4L2_CID_DETECT_MD_REGION_GRID:
818 mt = go->modet_map;
819 for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
820 memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
821 break;
822 default:
823 return -EINVAL;
824 }
825 return 0;
826}
827
828static const struct v4l2_file_operations go7007_fops = {
829 .owner = THIS_MODULE,
830 .open = v4l2_fh_open,
831 .release = vb2_fop_release,
832 .unlocked_ioctl = video_ioctl2,
833 .read = vb2_fop_read,
834 .mmap = vb2_fop_mmap,
835 .poll = vb2_fop_poll,
836};
837
838static const struct v4l2_ioctl_ops video_ioctl_ops = {
839 .vidioc_querycap = vidioc_querycap,
840 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
841 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
842 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
843 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
844 .vidioc_reqbufs = vb2_ioctl_reqbufs,
845 .vidioc_querybuf = vb2_ioctl_querybuf,
846 .vidioc_qbuf = vb2_ioctl_qbuf,
847 .vidioc_dqbuf = vb2_ioctl_dqbuf,
848 .vidioc_g_std = vidioc_g_std,
849 .vidioc_s_std = vidioc_s_std,
850 .vidioc_querystd = vidioc_querystd,
851 .vidioc_enum_input = vidioc_enum_input,
852 .vidioc_g_input = vidioc_g_input,
853 .vidioc_s_input = vidioc_s_input,
854 .vidioc_enumaudio = vidioc_enumaudio,
855 .vidioc_g_audio = vidioc_g_audio,
856 .vidioc_s_audio = vidioc_s_audio,
857 .vidioc_streamon = vb2_ioctl_streamon,
858 .vidioc_streamoff = vb2_ioctl_streamoff,
859 .vidioc_g_tuner = vidioc_g_tuner,
860 .vidioc_s_tuner = vidioc_s_tuner,
861 .vidioc_g_frequency = vidioc_g_frequency,
862 .vidioc_s_frequency = vidioc_s_frequency,
863 .vidioc_g_parm = vidioc_g_parm,
864 .vidioc_s_parm = vidioc_s_parm,
865 .vidioc_enum_framesizes = vidioc_enum_framesizes,
866 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
867 .vidioc_log_status = vidioc_log_status,
868 .vidioc_subscribe_event = vidioc_subscribe_event,
869 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
870};
871
872static const struct video_device go7007_template = {
873 .name = "go7007",
874 .fops = &go7007_fops,
875 .release = video_device_release_empty,
876 .ioctl_ops = &video_ioctl_ops,
877 .tvnorms = V4L2_STD_ALL,
878};
879
880static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
881 .s_ctrl = go7007_s_ctrl,
882};
883
884static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
885 .ops = &go7007_ctrl_ops,
886 .id = V4L2_CID_PIXEL_THRESHOLD0,
887 .name = "Pixel Threshold Region 0",
888 .type = V4L2_CTRL_TYPE_INTEGER,
889 .def = 20,
890 .max = 32767,
891 .step = 1,
892};
893
894static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
895 .ops = &go7007_ctrl_ops,
896 .id = V4L2_CID_MOTION_THRESHOLD0,
897 .name = "Motion Threshold Region 0",
898 .type = V4L2_CTRL_TYPE_INTEGER,
899 .def = 80,
900 .max = 32767,
901 .step = 1,
902};
903
904static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = {
905 .ops = &go7007_ctrl_ops,
906 .id = V4L2_CID_MB_THRESHOLD0,
907 .name = "MB Threshold Region 0",
908 .type = V4L2_CTRL_TYPE_INTEGER,
909 .def = 200,
910 .max = 32767,
911 .step = 1,
912};
913
914static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = {
915 .ops = &go7007_ctrl_ops,
916 .id = V4L2_CID_PIXEL_THRESHOLD1,
917 .name = "Pixel Threshold Region 1",
918 .type = V4L2_CTRL_TYPE_INTEGER,
919 .def = 20,
920 .max = 32767,
921 .step = 1,
922};
923
924static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = {
925 .ops = &go7007_ctrl_ops,
926 .id = V4L2_CID_MOTION_THRESHOLD1,
927 .name = "Motion Threshold Region 1",
928 .type = V4L2_CTRL_TYPE_INTEGER,
929 .def = 80,
930 .max = 32767,
931 .step = 1,
932};
933
934static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = {
935 .ops = &go7007_ctrl_ops,
936 .id = V4L2_CID_MB_THRESHOLD1,
937 .name = "MB Threshold Region 1",
938 .type = V4L2_CTRL_TYPE_INTEGER,
939 .def = 200,
940 .max = 32767,
941 .step = 1,
942};
943
944static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = {
945 .ops = &go7007_ctrl_ops,
946 .id = V4L2_CID_PIXEL_THRESHOLD2,
947 .name = "Pixel Threshold Region 2",
948 .type = V4L2_CTRL_TYPE_INTEGER,
949 .def = 20,
950 .max = 32767,
951 .step = 1,
952};
953
954static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = {
955 .ops = &go7007_ctrl_ops,
956 .id = V4L2_CID_MOTION_THRESHOLD2,
957 .name = "Motion Threshold Region 2",
958 .type = V4L2_CTRL_TYPE_INTEGER,
959 .def = 80,
960 .max = 32767,
961 .step = 1,
962};
963
964static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = {
965 .ops = &go7007_ctrl_ops,
966 .id = V4L2_CID_MB_THRESHOLD2,
967 .name = "MB Threshold Region 2",
968 .type = V4L2_CTRL_TYPE_INTEGER,
969 .def = 200,
970 .max = 32767,
971 .step = 1,
972};
973
974static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = {
975 .ops = &go7007_ctrl_ops,
976 .id = V4L2_CID_PIXEL_THRESHOLD3,
977 .name = "Pixel Threshold Region 3",
978 .type = V4L2_CTRL_TYPE_INTEGER,
979 .def = 20,
980 .max = 32767,
981 .step = 1,
982};
983
984static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = {
985 .ops = &go7007_ctrl_ops,
986 .id = V4L2_CID_MOTION_THRESHOLD3,
987 .name = "Motion Threshold Region 3",
988 .type = V4L2_CTRL_TYPE_INTEGER,
989 .def = 80,
990 .max = 32767,
991 .step = 1,
992};
993
994static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = {
995 .ops = &go7007_ctrl_ops,
996 .id = V4L2_CID_MB_THRESHOLD3,
997 .name = "MB Threshold Region 3",
998 .type = V4L2_CTRL_TYPE_INTEGER,
999 .def = 200,
1000 .max = 32767,
1001 .step = 1,
1002};
1003
1004static const struct v4l2_ctrl_config go7007_mb_regions_ctrl = {
1005 .ops = &go7007_ctrl_ops,
1006 .id = V4L2_CID_DETECT_MD_REGION_GRID,
1007 .dims = { 576 / 16, 720 / 16 },
1008 .max = 3,
1009 .step = 1,
1010};
1011
1012int go7007_v4l2_ctrl_init(struct go7007 *go)
1013{
1014 struct v4l2_ctrl_handler *hdl = &go->hdl;
1015 struct v4l2_ctrl *ctrl;
1016
1017 v4l2_ctrl_handler_init(hdl, 22);
1018 go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
1019 V4L2_CID_MPEG_VIDEO_GOP_SIZE, min: 0, max: 34, step: 1, def: 15);
1020 go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
1021 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, min: 0, max: 1, step: 1, def: 1);
1022 go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL,
1023 V4L2_CID_MPEG_VIDEO_BITRATE,
1024 min: 64000, max: 10000000, step: 1, def: 9800000);
1025 go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL,
1026 V4L2_CID_MPEG_VIDEO_B_FRAMES, min: 0, max: 2, step: 2, def: 0);
1027 go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL,
1028 V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, min: 0, max: 1, step: 1, def: 1);
1029
1030 go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL,
1031 V4L2_CID_MPEG_VIDEO_ASPECT,
1032 max: V4L2_MPEG_VIDEO_ASPECT_16x9, mask: 0,
1033 def: V4L2_MPEG_VIDEO_ASPECT_1x1);
1034 ctrl = v4l2_ctrl_new_std(hdl, NULL,
1035 V4L2_CID_JPEG_ACTIVE_MARKER, min: 0,
1036 V4L2_JPEG_ACTIVE_MARKER_DQT |
1037 V4L2_JPEG_ACTIVE_MARKER_DHT, step: 0,
1038 V4L2_JPEG_ACTIVE_MARKER_DQT |
1039 V4L2_JPEG_ACTIVE_MARKER_DHT);
1040 if (ctrl)
1041 ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1042 v4l2_ctrl_new_custom(hdl, cfg: &go7007_pixel_threshold0_ctrl, NULL);
1043 v4l2_ctrl_new_custom(hdl, cfg: &go7007_motion_threshold0_ctrl, NULL);
1044 v4l2_ctrl_new_custom(hdl, cfg: &go7007_mb_threshold0_ctrl, NULL);
1045 v4l2_ctrl_new_custom(hdl, cfg: &go7007_pixel_threshold1_ctrl, NULL);
1046 v4l2_ctrl_new_custom(hdl, cfg: &go7007_motion_threshold1_ctrl, NULL);
1047 v4l2_ctrl_new_custom(hdl, cfg: &go7007_mb_threshold1_ctrl, NULL);
1048 v4l2_ctrl_new_custom(hdl, cfg: &go7007_pixel_threshold2_ctrl, NULL);
1049 v4l2_ctrl_new_custom(hdl, cfg: &go7007_motion_threshold2_ctrl, NULL);
1050 v4l2_ctrl_new_custom(hdl, cfg: &go7007_mb_threshold2_ctrl, NULL);
1051 v4l2_ctrl_new_custom(hdl, cfg: &go7007_pixel_threshold3_ctrl, NULL);
1052 v4l2_ctrl_new_custom(hdl, cfg: &go7007_motion_threshold3_ctrl, NULL);
1053 v4l2_ctrl_new_custom(hdl, cfg: &go7007_mb_threshold3_ctrl, NULL);
1054 v4l2_ctrl_new_custom(hdl, cfg: &go7007_mb_regions_ctrl, NULL);
1055 go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL,
1056 V4L2_CID_DETECT_MD_MODE,
1057 max: V4L2_DETECT_MD_MODE_REGION_GRID,
1058 mask: 1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID,
1059 def: V4L2_DETECT_MD_MODE_DISABLED);
1060 if (hdl->error) {
1061 int rv = hdl->error;
1062
1063 v4l2_err(&go->v4l2_dev, "Could not register controls\n");
1064 return rv;
1065 }
1066 go->v4l2_dev.ctrl_handler = hdl;
1067 return 0;
1068}
1069
1070int go7007_v4l2_init(struct go7007 *go)
1071{
1072 struct video_device *vdev = &go->vdev;
1073 int rv;
1074
1075 mutex_init(&go->serialize_lock);
1076 mutex_init(&go->queue_lock);
1077
1078 INIT_LIST_HEAD(list: &go->vidq_active);
1079 go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1080 go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1081 go->vidq.ops = &go7007_video_qops;
1082 go->vidq.mem_ops = &vb2_vmalloc_memops;
1083 go->vidq.drv_priv = go;
1084 go->vidq.buf_struct_size = sizeof(struct go7007_buffer);
1085 go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1086 go->vidq.lock = &go->queue_lock;
1087 rv = vb2_queue_init(q: &go->vidq);
1088 if (rv)
1089 return rv;
1090 *vdev = go7007_template;
1091 vdev->lock = &go->serialize_lock;
1092 vdev->queue = &go->vidq;
1093 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
1094 V4L2_CAP_STREAMING;
1095 if (go->board_info->num_aud_inputs)
1096 vdev->device_caps |= V4L2_CAP_AUDIO;
1097 if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
1098 vdev->device_caps |= V4L2_CAP_TUNER;
1099 video_set_drvdata(vdev, data: go);
1100 vdev->v4l2_dev = &go->v4l2_dev;
1101 if (!v4l2_device_has_op(&go->v4l2_dev, 0, video, querystd))
1102 v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
1103 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
1104 v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
1105 v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY);
1106 v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER);
1107 v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER);
1108 } else {
1109 struct v4l2_frequency f = {
1110 .type = V4L2_TUNER_ANALOG_TV,
1111 .frequency = 980,
1112 };
1113
1114 call_all(&go->v4l2_dev, tuner, s_frequency, &f);
1115 }
1116 if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) {
1117 v4l2_disable_ioctl(vdev, VIDIOC_G_STD);
1118 v4l2_disable_ioctl(vdev, VIDIOC_S_STD);
1119 vdev->tvnorms = 0;
1120 }
1121 if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING)
1122 v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES);
1123 if (go->board_info->num_aud_inputs == 0) {
1124 v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO);
1125 v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO);
1126 v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO);
1127 }
1128 /* Setup correct crystal frequency on this board */
1129 if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115)
1130 v4l2_subdev_call(go->sd_video, video, s_crystal_freq,
1131 SAA7115_FREQ_24_576_MHZ,
1132 SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC |
1133 SAA7115_FREQ_FL_DOUBLE_ASCLK);
1134 go7007_s_input(go);
1135 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1136 go7007_s_std(go);
1137 rv = video_register_device(vdev, type: VFL_TYPE_VIDEO, nr: -1);
1138 if (rv < 0)
1139 return rv;
1140 dev_info(go->dev, "registered device %s [v4l2]\n",
1141 video_device_node_name(vdev));
1142
1143 return 0;
1144}
1145
1146void go7007_v4l2_remove(struct go7007 *go)
1147{
1148 v4l2_ctrl_handler_free(hdl: &go->hdl);
1149}
1150

source code of linux/drivers/media/usb/go7007/go7007-v4l2.c