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