Merge tag 'xtensa-next-20160320' of git://github.com/czankel/xtensa-linux
[deliverable/linux.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,
ffcc1c08
HV
372 unsigned int *num_buffers, unsigned int *num_planes,
373 unsigned int sizes[], void *alloc_ctxs[])
65f9f619 374{
ffcc1c08
HV
375 sizes[0] = GO7007_BUF_SIZE;
376 *num_planes = 1;
866b8695 377
ffcc1c08
HV
378 if (*num_buffers < 2)
379 *num_buffers = 2;
65f9f619
MCC
380
381 return 0;
65f9f619
MCC
382}
383
ffcc1c08 384static void go7007_buf_queue(struct vb2_buffer *vb)
65f9f619 385{
ffcc1c08
HV
386 struct vb2_queue *vq = vb->vb2_queue;
387 struct go7007 *go = vb2_get_drv_priv(vq);
2d700715 388 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
ffcc1c08 389 struct go7007_buffer *go7007_vb =
2d700715 390 container_of(vbuf, struct go7007_buffer, vb);
65f9f619 391 unsigned long flags;
65f9f619 392
65f9f619 393 spin_lock_irqsave(&go->spinlock, flags);
ffcc1c08 394 list_add_tail(&go7007_vb->list, &go->vidq_active);
65f9f619 395 spin_unlock_irqrestore(&go->spinlock, flags);
ffcc1c08 396}
65f9f619 397
ffcc1c08
HV
398static int go7007_buf_prepare(struct vb2_buffer *vb)
399{
2d700715 400 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
ffcc1c08 401 struct go7007_buffer *go7007_vb =
2d700715 402 container_of(vbuf, struct go7007_buffer, vb);
65f9f619 403
ffcc1c08
HV
404 go7007_vb->modet_active = 0;
405 go7007_vb->frame_offset = 0;
2d700715 406 vb->planes[0].bytesused = 0;
ffcc1c08 407 return 0;
65f9f619
MCC
408}
409
06470642 410static void go7007_buf_finish(struct vb2_buffer *vb)
65f9f619 411{
ffcc1c08
HV
412 struct vb2_queue *vq = vb->vb2_queue;
413 struct go7007 *go = vb2_get_drv_priv(vq);
2d700715 414 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
ffcc1c08 415 struct go7007_buffer *go7007_vb =
2d700715 416 container_of(vbuf, struct go7007_buffer, vb);
ffcc1c08 417 u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
ffcc1c08 418
2d700715 419 vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
ffcc1c08 420 V4L2_BUF_FLAG_PFRAME);
2d700715
JS
421 vbuf->flags |= frame_type_flag;
422 vbuf->field = V4L2_FIELD_NONE;
65f9f619
MCC
423}
424
ffcc1c08 425static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
65f9f619 426{
ffcc1c08
HV
427 struct go7007 *go = vb2_get_drv_priv(q);
428 int ret;
65f9f619 429
ffcc1c08 430 set_formatting(go);
fd9a40da 431 mutex_lock(&go->hw_lock);
ffcc1c08
HV
432 go->next_seq = 0;
433 go->active_buf = NULL;
0ee58f84 434 go->modet_event_status = 0;
ffcc1c08
HV
435 q->streaming = 1;
436 if (go7007_start_encoder(go) < 0)
437 ret = -EIO;
438 else
439 ret = 0;
fd9a40da 440 mutex_unlock(&go->hw_lock);
ffcc1c08
HV
441 if (ret) {
442 q->streaming = 0;
443 return ret;
444 }
0a147c3b 445 call_all(&go->v4l2_dev, video, s_stream, 1);
35d2d76d
HV
446 v4l2_ctrl_grab(go->mpeg_video_gop_size, true);
447 v4l2_ctrl_grab(go->mpeg_video_gop_closure, true);
448 v4l2_ctrl_grab(go->mpeg_video_bitrate, true);
449 v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true);
1f1aed2e
HV
450 /* Turn on Capture LED */
451 if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
452 go7007_write_addr(go, 0x3c82, 0x0005);
ffcc1c08 453 return ret;
65f9f619
MCC
454}
455
e37559b2 456static void go7007_stop_streaming(struct vb2_queue *q)
65f9f619 457{
ffcc1c08
HV
458 struct go7007 *go = vb2_get_drv_priv(q);
459 unsigned long flags;
65f9f619 460
ffcc1c08
HV
461 q->streaming = 0;
462 go7007_stream_stop(go);
463 mutex_lock(&go->hw_lock);
464 go7007_reset_encoder(go);
465 mutex_unlock(&go->hw_lock);
0a147c3b 466 call_all(&go->v4l2_dev, video, s_stream, 0);
65f9f619 467
ffcc1c08
HV
468 spin_lock_irqsave(&go->spinlock, flags);
469 INIT_LIST_HEAD(&go->vidq_active);
470 spin_unlock_irqrestore(&go->spinlock, flags);
471 v4l2_ctrl_grab(go->mpeg_video_gop_size, false);
472 v4l2_ctrl_grab(go->mpeg_video_gop_closure, false);
473 v4l2_ctrl_grab(go->mpeg_video_bitrate, false);
474 v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false);
1f1aed2e
HV
475 /* Turn on Capture LED */
476 if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
477 go7007_write_addr(go, 0x3c82, 0x000d);
65f9f619
MCC
478}
479
ffcc1c08
HV
480static struct vb2_ops go7007_video_qops = {
481 .queue_setup = go7007_queue_setup,
482 .buf_queue = go7007_buf_queue,
483 .buf_prepare = go7007_buf_prepare,
484 .buf_finish = go7007_buf_finish,
485 .start_streaming = go7007_start_streaming,
486 .stop_streaming = go7007_stop_streaming,
487 .wait_prepare = vb2_ops_wait_prepare,
488 .wait_finish = vb2_ops_wait_finish,
489};
490
65f9f619
MCC
491static int vidioc_g_parm(struct file *filp, void *priv,
492 struct v4l2_streamparm *parm)
493{
899eb84c 494 struct go7007 *go = video_drvdata(filp);
65f9f619
MCC
495 struct v4l2_fract timeperframe = {
496 .numerator = 1001 * go->fps_scale,
497 .denominator = go->sensor_framerate,
498 };
499
500 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
501 return -EINVAL;
502
50deb749
HV
503 parm->parm.capture.readbuffers = 2;
504 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
65f9f619
MCC
505 parm->parm.capture.timeperframe = timeperframe;
506
507 return 0;
508}
509
510static int vidioc_s_parm(struct file *filp, void *priv,
511 struct v4l2_streamparm *parm)
512{
899eb84c 513 struct go7007 *go = video_drvdata(filp);
65f9f619
MCC
514 unsigned int n, d;
515
516 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
517 return -EINVAL;
65f9f619
MCC
518
519 n = go->sensor_framerate *
520 parm->parm.capture.timeperframe.numerator;
521 d = 1001 * parm->parm.capture.timeperframe.denominator;
522 if (n != 0 && d != 0 && n > d)
523 go->fps_scale = (n + d/2) / d;
524 else
525 go->fps_scale = 1;
526
50deb749 527 return vidioc_g_parm(filp, priv, parm);
65f9f619
MCC
528}
529
b47acf2a 530/* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and
65f9f619 531 its resolution, when the device is not connected to TV.
b47acf2a
JM
532 This is were an API abuse, probably used by the lack of specific IOCTL's to
533 enumerate it, by the time the driver was written.
65f9f619
MCC
534
535 However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
536 and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
537
b47acf2a 538 The two functions below implement the newer ioctls
65f9f619 539*/
65f9f619
MCC
540static int vidioc_enum_framesizes(struct file *filp, void *priv,
541 struct v4l2_frmsizeenum *fsize)
542{
899eb84c 543 struct go7007 *go = video_drvdata(filp);
50deb749 544 int width, height;
65f9f619 545
50deb749 546 if (fsize->index > 2)
65f9f619
MCC
547 return -EINVAL;
548
35d2d76d 549 if (!valid_pixelformat(fsize->pixel_format))
65f9f619
MCC
550 return -EINVAL;
551
50deb749 552 get_resolution(go, &width, &height);
65f9f619 553 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
50deb749
HV
554 fsize->discrete.width = (width >> fsize->index) & ~0xf;
555 fsize->discrete.height = (height >> fsize->index) & ~0xf;
65f9f619
MCC
556 return 0;
557}
558
559static int vidioc_enum_frameintervals(struct file *filp, void *priv,
560 struct v4l2_frmivalenum *fival)
561{
899eb84c 562 struct go7007 *go = video_drvdata(filp);
50deb749
HV
563 int width, height;
564 int i;
65f9f619 565
50deb749 566 if (fival->index > 4)
65f9f619
MCC
567 return -EINVAL;
568
35d2d76d 569 if (!valid_pixelformat(fival->pixel_format))
65f9f619
MCC
570 return -EINVAL;
571
50deb749
HV
572 if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) {
573 get_resolution(go, &width, &height);
574 for (i = 0; i <= 2; i++)
575 if (fival->width == ((width >> i) & ~0xf) &&
576 fival->height == ((height >> i) & ~0xf))
577 break;
578 if (i > 2)
579 return -EINVAL;
580 }
65f9f619 581 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
50deb749
HV
582 fival->discrete.numerator = 1001 * (fival->index + 1);
583 fival->discrete.denominator = go->sensor_framerate;
65f9f619
MCC
584 return 0;
585}
586
bb871652
PE
587static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
588{
899eb84c 589 struct go7007 *go = video_drvdata(file);
bb871652 590
50deb749
HV
591 *std = go->std;
592 return 0;
593}
594
595static int go7007_s_std(struct go7007 *go)
596{
3e4c8478 597 if (go->std & V4L2_STD_625_50) {
50deb749
HV
598 go->standard = GO7007_STD_PAL;
599 go->sensor_framerate = 25025;
3e4c8478
HV
600 } else {
601 go->standard = GO7007_STD_NTSC;
602 go->sensor_framerate = 30000;
bb871652
PE
603 }
604
8774bed9 605 call_all(&go->v4l2_dev, video, s_std, go->std);
50deb749 606 set_capture_size(go, NULL, 0);
bb871652
PE
607 return 0;
608}
609
314527ac 610static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
65f9f619 611{
50deb749 612 struct go7007 *go = video_drvdata(file);
65f9f619 613
ffcc1c08 614 if (vb2_is_busy(&go->vidq))
65f9f619
MCC
615 return -EBUSY;
616
50deb749 617 go->std = std;
866b8695 618
50deb749 619 return go7007_s_std(go);
65f9f619 620}
d73f822c 621
bb871652
PE
622static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
623{
899eb84c 624 struct go7007 *go = video_drvdata(file);
866b8695 625
50deb749 626 return call_all(&go->v4l2_dev, video, querystd, std);
bb871652 627}
866b8695 628
65f9f619
MCC
629static int vidioc_enum_input(struct file *file, void *priv,
630 struct v4l2_input *inp)
631{
899eb84c 632 struct go7007 *go = video_drvdata(file);
866b8695 633
65f9f619
MCC
634 if (inp->index >= go->board_info->num_inputs)
635 return -EINVAL;
866b8695 636
65f9f619
MCC
637 strncpy(inp->name, go->board_info->inputs[inp->index].name,
638 sizeof(inp->name));
866b8695 639
3acd16ab 640 /* If this board has a tuner, it will be the first input */
65f9f619 641 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
3acd16ab 642 inp->index == 0)
65f9f619
MCC
643 inp->type = V4L2_INPUT_TYPE_TUNER;
644 else
645 inp->type = V4L2_INPUT_TYPE_CAMERA;
866b8695 646
5e410546
HV
647 if (go->board_info->num_aud_inputs)
648 inp->audioset = (1 << go->board_info->num_aud_inputs) - 1;
649 else
650 inp->audioset = 0;
65f9f619
MCC
651 inp->tuner = 0;
652 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
50deb749 653 inp->std = video_devdata(file)->tvnorms;
65f9f619
MCC
654 else
655 inp->std = 0;
866b8695 656
65f9f619
MCC
657 return 0;
658}
866b8695 659
866b8695 660
65f9f619
MCC
661static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
662{
899eb84c 663 struct go7007 *go = video_drvdata(file);
866b8695 664
65f9f619 665 *input = go->input;
866b8695 666
65f9f619
MCC
667 return 0;
668}
669
5e410546
HV
670static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
671{
672 struct go7007 *go = video_drvdata(file);
673
674 if (a->index >= go->board_info->num_aud_inputs)
675 return -EINVAL;
5935caec
AO
676 strlcpy(a->name, go->board_info->aud_inputs[a->index].name,
677 sizeof(a->name));
5e410546
HV
678 a->capability = V4L2_AUDCAP_STEREO;
679 return 0;
680}
681
682static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
683{
684 struct go7007 *go = video_drvdata(file);
685
686 a->index = go->aud_input;
5935caec
AO
687 strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
688 sizeof(a->name));
5e410546
HV
689 a->capability = V4L2_AUDCAP_STEREO;
690 return 0;
691}
692
5935caec
AO
693static int vidioc_s_audio(struct file *file, void *fh,
694 const struct v4l2_audio *a)
5e410546
HV
695{
696 struct go7007 *go = video_drvdata(file);
697
698 if (a->index >= go->board_info->num_aud_inputs)
699 return -EINVAL;
700 go->aud_input = a->index;
701 v4l2_subdev_call(go->sd_audio, audio, s_routing,
5935caec 702 go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0);
5e410546
HV
703 return 0;
704}
705
50deb749 706static void go7007_s_input(struct go7007 *go)
65f9f619 707{
50deb749 708 unsigned int input = go->input;
866b8695 709
3acd16ab
HV
710 v4l2_subdev_call(go->sd_video, video, s_routing,
711 go->board_info->inputs[input].video_input, 0,
712 go->board_info->video_config);
713 if (go->board_info->num_aud_inputs) {
714 int aud_input = go->board_info->inputs[input].audio_index;
715
716 v4l2_subdev_call(go->sd_audio, audio, s_routing,
717 go->board_info->aud_inputs[aud_input].audio_input, 0, 0);
718 go->aud_input = aud_input;
719 }
50deb749
HV
720}
721
722static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
723{
724 struct go7007 *go = video_drvdata(file);
725
726 if (input >= go->board_info->num_inputs)
727 return -EINVAL;
ffcc1c08 728 if (vb2_is_busy(&go->vidq))
50deb749
HV
729 return -EBUSY;
730
731 go->input = input;
732 go7007_s_input(go);
733
3acd16ab 734 return 0;
65f9f619
MCC
735}
736
737static int vidioc_g_tuner(struct file *file, void *priv,
738 struct v4l2_tuner *t)
739{
899eb84c 740 struct go7007 *go = video_drvdata(file);
65f9f619 741
65f9f619
MCC
742 if (t->index != 0)
743 return -EINVAL;
65f9f619 744
e4d2a616 745 strlcpy(t->name, "Tuner", sizeof(t->name));
fa3c39bd 746 return call_all(&go->v4l2_dev, tuner, g_tuner, t);
65f9f619
MCC
747}
748
749static int vidioc_s_tuner(struct file *file, void *priv,
2f73c7c5 750 const struct v4l2_tuner *t)
65f9f619 751{
899eb84c 752 struct go7007 *go = video_drvdata(file);
65f9f619 753
65f9f619
MCC
754 if (t->index != 0)
755 return -EINVAL;
65f9f619 756
fa3c39bd 757 return call_all(&go->v4l2_dev, tuner, s_tuner, t);
65f9f619
MCC
758}
759
760static int vidioc_g_frequency(struct file *file, void *priv,
761 struct v4l2_frequency *f)
762{
899eb84c 763 struct go7007 *go = video_drvdata(file);
65f9f619 764
50deb749 765 if (f->tuner)
65f9f619 766 return -EINVAL;
fa3c39bd
PE
767
768 return call_all(&go->v4l2_dev, tuner, g_frequency, f);
65f9f619
MCC
769}
770
771static int vidioc_s_frequency(struct file *file, void *priv,
b530a447 772 const struct v4l2_frequency *f)
65f9f619 773{
899eb84c 774 struct go7007 *go = video_drvdata(file);
65f9f619 775
50deb749 776 if (f->tuner)
65f9f619 777 return -EINVAL;
65f9f619 778
fa3c39bd 779 return call_all(&go->v4l2_dev, tuner, s_frequency, f);
65f9f619
MCC
780}
781
59d7b91a
HV
782static int vidioc_log_status(struct file *file, void *priv)
783{
899eb84c 784 struct go7007 *go = video_drvdata(file);
59d7b91a
HV
785
786 v4l2_ctrl_log_status(file, priv);
787 return call_all(&go->v4l2_dev, core, log_status);
788}
789
0ee58f84
HV
790static int vidioc_subscribe_event(struct v4l2_fh *fh,
791 const struct v4l2_event_subscription *sub)
792{
866b8695 793
0ee58f84
HV
794 switch (sub->type) {
795 case V4L2_EVENT_CTRL:
796 return v4l2_ctrl_subscribe_event(fh, sub);
797 case V4L2_EVENT_MOTION_DET:
798 /* Allow for up to 30 events (1 second for NTSC) to be
799 * stored. */
800 return v4l2_event_subscribe(fh, sub, 30, NULL);
866b8695 801 }
0ee58f84
HV
802 return -EINVAL;
803}
866b8695 804
0ee58f84
HV
805
806static int go7007_s_ctrl(struct v4l2_ctrl *ctrl)
807{
808 struct go7007 *go =
809 container_of(ctrl->handler, struct go7007, hdl);
810 unsigned y;
811 u8 *mt;
812
813 switch (ctrl->id) {
814 case V4L2_CID_PIXEL_THRESHOLD0:
815 go->modet[0].pixel_threshold = ctrl->val;
816 break;
817 case V4L2_CID_MOTION_THRESHOLD0:
818 go->modet[0].motion_threshold = ctrl->val;
819 break;
820 case V4L2_CID_MB_THRESHOLD0:
821 go->modet[0].mb_threshold = ctrl->val;
822 break;
823 case V4L2_CID_PIXEL_THRESHOLD1:
824 go->modet[1].pixel_threshold = ctrl->val;
825 break;
826 case V4L2_CID_MOTION_THRESHOLD1:
827 go->modet[1].motion_threshold = ctrl->val;
828 break;
829 case V4L2_CID_MB_THRESHOLD1:
830 go->modet[1].mb_threshold = ctrl->val;
831 break;
832 case V4L2_CID_PIXEL_THRESHOLD2:
833 go->modet[2].pixel_threshold = ctrl->val;
834 break;
835 case V4L2_CID_MOTION_THRESHOLD2:
836 go->modet[2].motion_threshold = ctrl->val;
837 break;
838 case V4L2_CID_MB_THRESHOLD2:
839 go->modet[2].mb_threshold = ctrl->val;
840 break;
841 case V4L2_CID_PIXEL_THRESHOLD3:
842 go->modet[3].pixel_threshold = ctrl->val;
843 break;
844 case V4L2_CID_MOTION_THRESHOLD3:
845 go->modet[3].motion_threshold = ctrl->val;
846 break;
847 case V4L2_CID_MB_THRESHOLD3:
848 go->modet[3].mb_threshold = ctrl->val;
849 break;
850 case V4L2_CID_DETECT_MD_REGION_GRID:
851 mt = go->modet_map;
852 for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
853 memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
854 break;
855 default:
856 return -EINVAL;
866b8695 857 }
0ee58f84
HV
858 return 0;
859}
866b8695 860
60572c0d 861static struct v4l2_file_operations go7007_fops = {
866b8695 862 .owner = THIS_MODULE,
899eb84c 863 .open = v4l2_fh_open,
ffcc1c08
HV
864 .release = vb2_fop_release,
865 .unlocked_ioctl = video_ioctl2,
866 .read = vb2_fop_read,
867 .mmap = vb2_fop_mmap,
868 .poll = vb2_fop_poll,
866b8695
GKH
869};
870
65f9f619
MCC
871static const struct v4l2_ioctl_ops video_ioctl_ops = {
872 .vidioc_querycap = vidioc_querycap,
873 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
874 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
875 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
876 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
ffcc1c08
HV
877 .vidioc_reqbufs = vb2_ioctl_reqbufs,
878 .vidioc_querybuf = vb2_ioctl_querybuf,
879 .vidioc_qbuf = vb2_ioctl_qbuf,
880 .vidioc_dqbuf = vb2_ioctl_dqbuf,
bb871652 881 .vidioc_g_std = vidioc_g_std,
65f9f619 882 .vidioc_s_std = vidioc_s_std,
bb871652 883 .vidioc_querystd = vidioc_querystd,
65f9f619
MCC
884 .vidioc_enum_input = vidioc_enum_input,
885 .vidioc_g_input = vidioc_g_input,
886 .vidioc_s_input = vidioc_s_input,
5e410546
HV
887 .vidioc_enumaudio = vidioc_enumaudio,
888 .vidioc_g_audio = vidioc_g_audio,
889 .vidioc_s_audio = vidioc_s_audio,
ffcc1c08
HV
890 .vidioc_streamon = vb2_ioctl_streamon,
891 .vidioc_streamoff = vb2_ioctl_streamoff,
65f9f619
MCC
892 .vidioc_g_tuner = vidioc_g_tuner,
893 .vidioc_s_tuner = vidioc_s_tuner,
894 .vidioc_g_frequency = vidioc_g_frequency,
895 .vidioc_s_frequency = vidioc_s_frequency,
896 .vidioc_g_parm = vidioc_g_parm,
897 .vidioc_s_parm = vidioc_s_parm,
65f9f619
MCC
898 .vidioc_enum_framesizes = vidioc_enum_framesizes,
899 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
59d7b91a 900 .vidioc_log_status = vidioc_log_status,
0ee58f84 901 .vidioc_subscribe_event = vidioc_subscribe_event,
bae74320 902 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
65f9f619
MCC
903};
904
866b8695
GKH
905static struct video_device go7007_template = {
906 .name = "go7007",
907 .fops = &go7007_fops,
6bb0e65d 908 .release = video_device_release_empty,
65f9f619
MCC
909 .ioctl_ops = &video_ioctl_ops,
910 .tvnorms = V4L2_STD_ALL,
866b8695
GKH
911};
912
0ee58f84
HV
913static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
914 .s_ctrl = go7007_s_ctrl,
915};
916
917static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
918 .ops = &go7007_ctrl_ops,
919 .id = V4L2_CID_PIXEL_THRESHOLD0,
920 .name = "Pixel Threshold Region 0",
921 .type = V4L2_CTRL_TYPE_INTEGER,
922 .def = 20,
923 .max = 32767,
924 .step = 1,
925};
926
927static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
928 .ops = &go7007_ctrl_ops,
929 .id = V4L2_CID_MOTION_THRESHOLD0,
930 .name = "Motion Threshold Region 0",
931 .type = V4L2_CTRL_TYPE_INTEGER,
932 .def = 80,
933 .max = 32767,
934 .step = 1,
935};
936
937static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = {
938 .ops = &go7007_ctrl_ops,
939 .id = V4L2_CID_MB_THRESHOLD0,
940 .name = "MB Threshold Region 0",
941 .type = V4L2_CTRL_TYPE_INTEGER,
942 .def = 200,
943 .max = 32767,
944 .step = 1,
945};
946
947static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = {
948 .ops = &go7007_ctrl_ops,
949 .id = V4L2_CID_PIXEL_THRESHOLD1,
950 .name = "Pixel Threshold Region 1",
951 .type = V4L2_CTRL_TYPE_INTEGER,
952 .def = 20,
953 .max = 32767,
954 .step = 1,
955};
956
957static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = {
958 .ops = &go7007_ctrl_ops,
959 .id = V4L2_CID_MOTION_THRESHOLD1,
960 .name = "Motion Threshold Region 1",
961 .type = V4L2_CTRL_TYPE_INTEGER,
962 .def = 80,
963 .max = 32767,
964 .step = 1,
965};
966
967static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = {
968 .ops = &go7007_ctrl_ops,
969 .id = V4L2_CID_MB_THRESHOLD1,
970 .name = "MB Threshold Region 1",
971 .type = V4L2_CTRL_TYPE_INTEGER,
972 .def = 200,
973 .max = 32767,
974 .step = 1,
975};
976
977static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = {
978 .ops = &go7007_ctrl_ops,
979 .id = V4L2_CID_PIXEL_THRESHOLD2,
980 .name = "Pixel Threshold Region 2",
981 .type = V4L2_CTRL_TYPE_INTEGER,
982 .def = 20,
983 .max = 32767,
984 .step = 1,
985};
986
987static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = {
988 .ops = &go7007_ctrl_ops,
989 .id = V4L2_CID_MOTION_THRESHOLD2,
990 .name = "Motion Threshold Region 2",
991 .type = V4L2_CTRL_TYPE_INTEGER,
992 .def = 80,
993 .max = 32767,
994 .step = 1,
995};
996
997static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = {
998 .ops = &go7007_ctrl_ops,
999 .id = V4L2_CID_MB_THRESHOLD2,
1000 .name = "MB Threshold Region 2",
1001 .type = V4L2_CTRL_TYPE_INTEGER,
1002 .def = 200,
1003 .max = 32767,
1004 .step = 1,
1005};
1006
1007static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = {
1008 .ops = &go7007_ctrl_ops,
1009 .id = V4L2_CID_PIXEL_THRESHOLD3,
1010 .name = "Pixel Threshold Region 3",
1011 .type = V4L2_CTRL_TYPE_INTEGER,
1012 .def = 20,
1013 .max = 32767,
1014 .step = 1,
1015};
1016
1017static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = {
1018 .ops = &go7007_ctrl_ops,
1019 .id = V4L2_CID_MOTION_THRESHOLD3,
1020 .name = "Motion Threshold Region 3",
1021 .type = V4L2_CTRL_TYPE_INTEGER,
1022 .def = 80,
1023 .max = 32767,
1024 .step = 1,
1025};
1026
1027static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = {
1028 .ops = &go7007_ctrl_ops,
1029 .id = V4L2_CID_MB_THRESHOLD3,
1030 .name = "MB Threshold Region 3",
1031 .type = V4L2_CTRL_TYPE_INTEGER,
1032 .def = 200,
1033 .max = 32767,
1034 .step = 1,
1035};
1036
1037static const struct v4l2_ctrl_config go7007_mb_regions_ctrl = {
1038 .ops = &go7007_ctrl_ops,
1039 .id = V4L2_CID_DETECT_MD_REGION_GRID,
1040 .dims = { 576 / 16, 720 / 16 },
1041 .max = 3,
1042 .step = 1,
1043};
1044
9b8451d5
HV
1045int go7007_v4l2_ctrl_init(struct go7007 *go)
1046{
1047 struct v4l2_ctrl_handler *hdl = &go->hdl;
1048 struct v4l2_ctrl *ctrl;
1049
0ee58f84 1050 v4l2_ctrl_handler_init(hdl, 22);
35d2d76d 1051 go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
9b8451d5 1052 V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15);
35d2d76d
HV
1053 go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
1054 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
1055 go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL,
9b8451d5 1056 V4L2_CID_MPEG_VIDEO_BITRATE,
35d2d76d 1057 64000, 10000000, 1, 9800000);
7e4bfb9e
VK
1058 go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL,
1059 V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 2, 2, 0);
778ca511
HV
1060 go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL,
1061 V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 0, 1, 1, 1);
7e4bfb9e 1062
35d2d76d
HV
1063 go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL,
1064 V4L2_CID_MPEG_VIDEO_ASPECT,
1065 V4L2_MPEG_VIDEO_ASPECT_16x9, 0,
1066 V4L2_MPEG_VIDEO_ASPECT_1x1);
1067 ctrl = v4l2_ctrl_new_std(hdl, NULL,
9b8451d5 1068 V4L2_CID_JPEG_ACTIVE_MARKER, 0,
5935caec
AO
1069 V4L2_JPEG_ACTIVE_MARKER_DQT |
1070 V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
1071 V4L2_JPEG_ACTIVE_MARKER_DQT |
1072 V4L2_JPEG_ACTIVE_MARKER_DHT);
9b8451d5
HV
1073 if (ctrl)
1074 ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
0ee58f84
HV
1075 v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold0_ctrl, NULL);
1076 v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold0_ctrl, NULL);
1077 v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold0_ctrl, NULL);
1078 v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold1_ctrl, NULL);
1079 v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold1_ctrl, NULL);
1080 v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold1_ctrl, NULL);
1081 v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold2_ctrl, NULL);
1082 v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold2_ctrl, NULL);
1083 v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold2_ctrl, NULL);
1084 v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold3_ctrl, NULL);
1085 v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold3_ctrl, NULL);
1086 v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold3_ctrl, NULL);
1087 v4l2_ctrl_new_custom(hdl, &go7007_mb_regions_ctrl, NULL);
1088 go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL,
1089 V4L2_CID_DETECT_MD_MODE,
1090 V4L2_DETECT_MD_MODE_REGION_GRID,
1091 1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID,
1092 V4L2_DETECT_MD_MODE_DISABLED);
9b8451d5
HV
1093 if (hdl->error) {
1094 int rv = hdl->error;
1095
1096 v4l2_err(&go->v4l2_dev, "Could not register controls\n");
1097 return rv;
1098 }
1099 go->v4l2_dev.ctrl_handler = hdl;
1100 return 0;
1101}
1102
866b8695
GKH
1103int go7007_v4l2_init(struct go7007 *go)
1104{
6bb0e65d 1105 struct video_device *vdev = &go->vdev;
866b8695
GKH
1106 int rv;
1107
ffcc1c08
HV
1108 mutex_init(&go->serialize_lock);
1109 mutex_init(&go->queue_lock);
1110
1111 INIT_LIST_HEAD(&go->vidq_active);
1112 go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1113 go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1114 go->vidq.ops = &go7007_video_qops;
1115 go->vidq.mem_ops = &vb2_vmalloc_memops;
1116 go->vidq.drv_priv = go;
1117 go->vidq.buf_struct_size = sizeof(struct go7007_buffer);
ade48681 1118 go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
ffcc1c08
HV
1119 go->vidq.lock = &go->queue_lock;
1120 rv = vb2_queue_init(&go->vidq);
1121 if (rv)
1122 return rv;
6bb0e65d
HV
1123 *vdev = go7007_template;
1124 vdev->lock = &go->serialize_lock;
1125 vdev->queue = &go->vidq;
6bb0e65d
HV
1126 video_set_drvdata(vdev, go);
1127 vdev->v4l2_dev = &go->v4l2_dev;
50deb749 1128 if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd))
6bb0e65d 1129 v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
50deb749 1130 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
6bb0e65d
HV
1131 v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
1132 v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY);
1133 v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER);
1134 v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER);
50deb749
HV
1135 } else {
1136 struct v4l2_frequency f = {
1137 .type = V4L2_TUNER_ANALOG_TV,
1138 .frequency = 980,
1139 };
1140
1141 call_all(&go->v4l2_dev, tuner, s_frequency, &f);
1142 }
1143 if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) {
6bb0e65d
HV
1144 v4l2_disable_ioctl(vdev, VIDIOC_G_STD);
1145 v4l2_disable_ioctl(vdev, VIDIOC_S_STD);
1146 vdev->tvnorms = 0;
866b8695 1147 }
50deb749 1148 if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING)
6bb0e65d 1149 v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES);
5e410546 1150 if (go->board_info->num_aud_inputs == 0) {
6bb0e65d
HV
1151 v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO);
1152 v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO);
1153 v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO);
5e410546 1154 }
b95dd82c
HV
1155 /* Setup correct crystal frequency on this board */
1156 if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115)
1157 v4l2_subdev_call(go->sd_video, video, s_crystal_freq,
1158 SAA7115_FREQ_24_576_MHZ,
1159 SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC |
1160 SAA7115_FREQ_FL_DOUBLE_ASCLK);
50deb749
HV
1161 go7007_s_input(go);
1162 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1163 go7007_s_std(go);
6bb0e65d
HV
1164 rv = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1165 if (rv < 0)
50deb749 1166 return rv;
34047bac 1167 dev_info(go->dev, "registered device %s [v4l2]\n",
6bb0e65d 1168 video_device_node_name(vdev));
866b8695
GKH
1169
1170 return 0;
1171}
1172
1173void go7007_v4l2_remove(struct go7007 *go)
1174{
9b8451d5 1175 v4l2_ctrl_handler_free(&go->hdl);
866b8695 1176}
This page took 0.660302 seconds and 5 git commands to generate.