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