Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2005-2006 Micronas USA Inc.
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/delay.h>
0008 #include <linux/sched.h>
0009 #include <linux/spinlock.h>
0010 #include <linux/slab.h>
0011 #include <linux/fs.h>
0012 #include <linux/unistd.h>
0013 #include <linux/time.h>
0014 #include <linux/vmalloc.h>
0015 #include <linux/pagemap.h>
0016 #include <linux/i2c.h>
0017 #include <linux/mutex.h>
0018 #include <linux/uaccess.h>
0019 #include <linux/videodev2.h>
0020 #include <media/v4l2-common.h>
0021 #include <media/v4l2-ioctl.h>
0022 #include <media/v4l2-subdev.h>
0023 #include <media/v4l2-event.h>
0024 #include <media/videobuf2-vmalloc.h>
0025 #include <media/i2c/saa7115.h>
0026 
0027 #include "go7007-priv.h"
0028 
0029 #define call_all(dev, o, f, args...) \
0030     v4l2_device_call_until_err(dev, 0, o, f, ##args)
0031 
0032 static bool valid_pixelformat(u32 pixelformat)
0033 {
0034     switch (pixelformat) {
0035     case V4L2_PIX_FMT_MJPEG:
0036     case V4L2_PIX_FMT_MPEG1:
0037     case V4L2_PIX_FMT_MPEG2:
0038     case V4L2_PIX_FMT_MPEG4:
0039         return true;
0040     default:
0041         return false;
0042     }
0043 }
0044 
0045 static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
0046 {
0047     u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
0048 
0049     switch (format) {
0050     case V4L2_PIX_FMT_MJPEG:
0051         return V4L2_BUF_FLAG_KEYFRAME;
0052     case V4L2_PIX_FMT_MPEG4:
0053         switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) {
0054         case 0:
0055             return V4L2_BUF_FLAG_KEYFRAME;
0056         case 1:
0057             return V4L2_BUF_FLAG_PFRAME;
0058         case 2:
0059             return V4L2_BUF_FLAG_BFRAME;
0060         default:
0061             return 0;
0062         }
0063     case V4L2_PIX_FMT_MPEG1:
0064     case V4L2_PIX_FMT_MPEG2:
0065         switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) {
0066         case 1:
0067             return V4L2_BUF_FLAG_KEYFRAME;
0068         case 2:
0069             return V4L2_BUF_FLAG_PFRAME;
0070         case 3:
0071             return V4L2_BUF_FLAG_BFRAME;
0072         default:
0073             return 0;
0074         }
0075     }
0076 
0077     return 0;
0078 }
0079 
0080 static void get_resolution(struct go7007 *go, int *width, int *height)
0081 {
0082     switch (go->standard) {
0083     case GO7007_STD_NTSC:
0084         *width = 720;
0085         *height = 480;
0086         break;
0087     case GO7007_STD_PAL:
0088         *width = 720;
0089         *height = 576;
0090         break;
0091     case GO7007_STD_OTHER:
0092     default:
0093         *width = go->board_info->sensor_width;
0094         *height = go->board_info->sensor_height;
0095         break;
0096     }
0097 }
0098 
0099 static void set_formatting(struct go7007 *go)
0100 {
0101     if (go->format == V4L2_PIX_FMT_MJPEG) {
0102         go->pali = 0;
0103         go->aspect_ratio = GO7007_RATIO_1_1;
0104         go->gop_size = 0;
0105         go->ipb = 0;
0106         go->closed_gop = 0;
0107         go->repeat_seqhead = 0;
0108         go->seq_header_enable = 0;
0109         go->gop_header_enable = 0;
0110         go->dvd_mode = 0;
0111         return;
0112     }
0113 
0114     switch (go->format) {
0115     case V4L2_PIX_FMT_MPEG1:
0116         go->pali = 0;
0117         break;
0118     default:
0119     case V4L2_PIX_FMT_MPEG2:
0120         go->pali = 0x48;
0121         break;
0122     case V4L2_PIX_FMT_MPEG4:
0123         /* For future reference: this is the list of MPEG4
0124          * profiles that are available, although they are
0125          * untested:
0126          *
0127          * Profile      pali
0128          * --------------   ----
0129          * PROFILE_S_L0     0x08
0130          * PROFILE_S_L1     0x01
0131          * PROFILE_S_L2     0x02
0132          * PROFILE_S_L3     0x03
0133          * PROFILE_ARTS_L1  0x91
0134          * PROFILE_ARTS_L2  0x92
0135          * PROFILE_ARTS_L3  0x93
0136          * PROFILE_ARTS_L4  0x94
0137          * PROFILE_AS_L0    0xf0
0138          * PROFILE_AS_L1    0xf1
0139          * PROFILE_AS_L2    0xf2
0140          * PROFILE_AS_L3    0xf3
0141          * PROFILE_AS_L4    0xf4
0142          * PROFILE_AS_L5    0xf5
0143          */
0144         go->pali = 0xf5;
0145         break;
0146     }
0147     go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size);
0148     go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure);
0149     go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0;
0150     go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate);
0151     go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader);
0152     go->gop_header_enable = 1;
0153     go->dvd_mode = 0;
0154     if (go->format == V4L2_PIX_FMT_MPEG2)
0155         go->dvd_mode =
0156             go->bitrate == 9800000 &&
0157             go->gop_size == 15 &&
0158             go->ipb == 0 &&
0159             go->repeat_seqhead == 1 &&
0160             go->closed_gop;
0161 
0162     switch (v4l2_ctrl_g_ctrl(go->mpeg_video_aspect_ratio)) {
0163     default:
0164     case V4L2_MPEG_VIDEO_ASPECT_1x1:
0165         go->aspect_ratio = GO7007_RATIO_1_1;
0166         break;
0167     case V4L2_MPEG_VIDEO_ASPECT_4x3:
0168         go->aspect_ratio = GO7007_RATIO_4_3;
0169         break;
0170     case V4L2_MPEG_VIDEO_ASPECT_16x9:
0171         go->aspect_ratio = GO7007_RATIO_16_9;
0172         break;
0173     }
0174 }
0175 
0176 static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
0177 {
0178     int sensor_height = 0, sensor_width = 0;
0179     int width, height;
0180 
0181     if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat))
0182         return -EINVAL;
0183 
0184     get_resolution(go, &sensor_width, &sensor_height);
0185 
0186     if (fmt == NULL) {
0187         width = sensor_width;
0188         height = sensor_height;
0189     } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
0190         if (fmt->fmt.pix.width > sensor_width)
0191             width = sensor_width;
0192         else if (fmt->fmt.pix.width < 144)
0193             width = 144;
0194         else
0195             width = fmt->fmt.pix.width & ~0x0f;
0196 
0197         if (fmt->fmt.pix.height > sensor_height)
0198             height = sensor_height;
0199         else if (fmt->fmt.pix.height < 96)
0200             height = 96;
0201         else
0202             height = fmt->fmt.pix.height & ~0x0f;
0203     } else {
0204         width = fmt->fmt.pix.width;
0205 
0206         if (width <= sensor_width / 4) {
0207             width = sensor_width / 4;
0208             height = sensor_height / 4;
0209         } else if (width <= sensor_width / 2) {
0210             width = sensor_width / 2;
0211             height = sensor_height / 2;
0212         } else {
0213             width = sensor_width;
0214             height = sensor_height;
0215         }
0216         width &= ~0xf;
0217         height &= ~0xf;
0218     }
0219 
0220     if (fmt != NULL) {
0221         u32 pixelformat = fmt->fmt.pix.pixelformat;
0222 
0223         memset(fmt, 0, sizeof(*fmt));
0224         fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
0225         fmt->fmt.pix.width = width;
0226         fmt->fmt.pix.height = height;
0227         fmt->fmt.pix.pixelformat = pixelformat;
0228         fmt->fmt.pix.field = V4L2_FIELD_NONE;
0229         fmt->fmt.pix.bytesperline = 0;
0230         fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
0231         fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
0232     }
0233 
0234     if (try)
0235         return 0;
0236 
0237     if (fmt)
0238         go->format = fmt->fmt.pix.pixelformat;
0239     go->width = width;
0240     go->height = height;
0241     go->encoder_h_offset = go->board_info->sensor_h_offset;
0242     go->encoder_v_offset = go->board_info->sensor_v_offset;
0243 
0244     if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
0245         struct v4l2_subdev_format format = {
0246             .which = V4L2_SUBDEV_FORMAT_ACTIVE,
0247         };
0248 
0249         format.format.code = MEDIA_BUS_FMT_FIXED;
0250         format.format.width = fmt ? fmt->fmt.pix.width : width;
0251         format.format.height = height;
0252         go->encoder_h_halve = 0;
0253         go->encoder_v_halve = 0;
0254         go->encoder_subsample = 0;
0255         call_all(&go->v4l2_dev, pad, set_fmt, NULL, &format);
0256     } else {
0257         if (width <= sensor_width / 4) {
0258             go->encoder_h_halve = 1;
0259             go->encoder_v_halve = 1;
0260             go->encoder_subsample = 1;
0261         } else if (width <= sensor_width / 2) {
0262             go->encoder_h_halve = 1;
0263             go->encoder_v_halve = 1;
0264             go->encoder_subsample = 0;
0265         } else {
0266             go->encoder_h_halve = 0;
0267             go->encoder_v_halve = 0;
0268             go->encoder_subsample = 0;
0269         }
0270     }
0271     return 0;
0272 }
0273 
0274 static int vidioc_querycap(struct file *file, void  *priv,
0275                     struct v4l2_capability *cap)
0276 {
0277     struct go7007 *go = video_drvdata(file);
0278 
0279     strscpy(cap->driver, "go7007", sizeof(cap->driver));
0280     strscpy(cap->card, go->name, sizeof(cap->card));
0281     strscpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
0282     return 0;
0283 }
0284 
0285 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
0286                     struct v4l2_fmtdesc *fmt)
0287 {
0288     switch (fmt->index) {
0289     case 0:
0290         fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
0291         break;
0292     case 1:
0293         fmt->pixelformat = V4L2_PIX_FMT_MPEG1;
0294         break;
0295     case 2:
0296         fmt->pixelformat = V4L2_PIX_FMT_MPEG2;
0297         break;
0298     case 3:
0299         fmt->pixelformat = V4L2_PIX_FMT_MPEG4;
0300         break;
0301     default:
0302         return -EINVAL;
0303     }
0304     return 0;
0305 }
0306 
0307 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
0308                     struct v4l2_format *fmt)
0309 {
0310     struct go7007 *go = video_drvdata(file);
0311 
0312     fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
0313     fmt->fmt.pix.width = go->width;
0314     fmt->fmt.pix.height = go->height;
0315     fmt->fmt.pix.pixelformat = go->format;
0316     fmt->fmt.pix.field = V4L2_FIELD_NONE;
0317     fmt->fmt.pix.bytesperline = 0;
0318     fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
0319     fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
0320 
0321     return 0;
0322 }
0323 
0324 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
0325             struct v4l2_format *fmt)
0326 {
0327     struct go7007 *go = video_drvdata(file);
0328 
0329     return set_capture_size(go, fmt, 1);
0330 }
0331 
0332 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
0333             struct v4l2_format *fmt)
0334 {
0335     struct go7007 *go = video_drvdata(file);
0336 
0337     if (vb2_is_busy(&go->vidq))
0338         return -EBUSY;
0339 
0340     return set_capture_size(go, fmt, 0);
0341 }
0342 
0343 static int go7007_queue_setup(struct vb2_queue *q,
0344         unsigned int *num_buffers, unsigned int *num_planes,
0345         unsigned int sizes[], struct device *alloc_devs[])
0346 {
0347     sizes[0] = GO7007_BUF_SIZE;
0348     *num_planes = 1;
0349 
0350     if (*num_buffers < 2)
0351         *num_buffers = 2;
0352 
0353     return 0;
0354 }
0355 
0356 static void go7007_buf_queue(struct vb2_buffer *vb)
0357 {
0358     struct vb2_queue *vq = vb->vb2_queue;
0359     struct go7007 *go = vb2_get_drv_priv(vq);
0360     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0361     struct go7007_buffer *go7007_vb =
0362         container_of(vbuf, struct go7007_buffer, vb);
0363     unsigned long flags;
0364 
0365     spin_lock_irqsave(&go->spinlock, flags);
0366     list_add_tail(&go7007_vb->list, &go->vidq_active);
0367     spin_unlock_irqrestore(&go->spinlock, flags);
0368 }
0369 
0370 static int go7007_buf_prepare(struct vb2_buffer *vb)
0371 {
0372     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0373     struct go7007_buffer *go7007_vb =
0374         container_of(vbuf, struct go7007_buffer, vb);
0375 
0376     go7007_vb->modet_active = 0;
0377     go7007_vb->frame_offset = 0;
0378     vb->planes[0].bytesused = 0;
0379     return 0;
0380 }
0381 
0382 static void go7007_buf_finish(struct vb2_buffer *vb)
0383 {
0384     struct vb2_queue *vq = vb->vb2_queue;
0385     struct go7007 *go = vb2_get_drv_priv(vq);
0386     struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
0387     struct go7007_buffer *go7007_vb =
0388         container_of(vbuf, struct go7007_buffer, vb);
0389     u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
0390 
0391     vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
0392             V4L2_BUF_FLAG_PFRAME);
0393     vbuf->flags |= frame_type_flag;
0394     vbuf->field = V4L2_FIELD_NONE;
0395 }
0396 
0397 static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
0398 {
0399     struct go7007 *go = vb2_get_drv_priv(q);
0400     int ret;
0401 
0402     set_formatting(go);
0403     mutex_lock(&go->hw_lock);
0404     go->next_seq = 0;
0405     go->active_buf = NULL;
0406     go->modet_event_status = 0;
0407     q->streaming = 1;
0408     if (go7007_start_encoder(go) < 0)
0409         ret = -EIO;
0410     else
0411         ret = 0;
0412     mutex_unlock(&go->hw_lock);
0413     if (ret) {
0414         q->streaming = 0;
0415         return ret;
0416     }
0417     call_all(&go->v4l2_dev, video, s_stream, 1);
0418     v4l2_ctrl_grab(go->mpeg_video_gop_size, true);
0419     v4l2_ctrl_grab(go->mpeg_video_gop_closure, true);
0420     v4l2_ctrl_grab(go->mpeg_video_bitrate, true);
0421     v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true);
0422     /* Turn on Capture LED */
0423     if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
0424         go7007_write_addr(go, 0x3c82, 0x0005);
0425     return ret;
0426 }
0427 
0428 static void go7007_stop_streaming(struct vb2_queue *q)
0429 {
0430     struct go7007 *go = vb2_get_drv_priv(q);
0431     unsigned long flags;
0432 
0433     q->streaming = 0;
0434     go7007_stream_stop(go);
0435     mutex_lock(&go->hw_lock);
0436     go7007_reset_encoder(go);
0437     mutex_unlock(&go->hw_lock);
0438     call_all(&go->v4l2_dev, video, s_stream, 0);
0439 
0440     spin_lock_irqsave(&go->spinlock, flags);
0441     INIT_LIST_HEAD(&go->vidq_active);
0442     spin_unlock_irqrestore(&go->spinlock, flags);
0443     v4l2_ctrl_grab(go->mpeg_video_gop_size, false);
0444     v4l2_ctrl_grab(go->mpeg_video_gop_closure, false);
0445     v4l2_ctrl_grab(go->mpeg_video_bitrate, false);
0446     v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false);
0447     /* Turn on Capture LED */
0448     if (go->board_id == GO7007_BOARDID_ADS_USBAV_709)
0449         go7007_write_addr(go, 0x3c82, 0x000d);
0450 }
0451 
0452 static const struct vb2_ops go7007_video_qops = {
0453     .queue_setup    = go7007_queue_setup,
0454     .buf_queue      = go7007_buf_queue,
0455     .buf_prepare    = go7007_buf_prepare,
0456     .buf_finish     = go7007_buf_finish,
0457     .start_streaming = go7007_start_streaming,
0458     .stop_streaming = go7007_stop_streaming,
0459     .wait_prepare   = vb2_ops_wait_prepare,
0460     .wait_finish    = vb2_ops_wait_finish,
0461 };
0462 
0463 static int vidioc_g_parm(struct file *filp, void *priv,
0464         struct v4l2_streamparm *parm)
0465 {
0466     struct go7007 *go = video_drvdata(filp);
0467     struct v4l2_fract timeperframe = {
0468         .numerator = 1001 *  go->fps_scale,
0469         .denominator = go->sensor_framerate,
0470     };
0471 
0472     if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
0473         return -EINVAL;
0474 
0475     parm->parm.capture.readbuffers = 2;
0476     parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
0477     parm->parm.capture.timeperframe = timeperframe;
0478 
0479     return 0;
0480 }
0481 
0482 static int vidioc_s_parm(struct file *filp, void *priv,
0483         struct v4l2_streamparm *parm)
0484 {
0485     struct go7007 *go = video_drvdata(filp);
0486     unsigned int n, d;
0487 
0488     if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
0489         return -EINVAL;
0490 
0491     n = go->sensor_framerate *
0492         parm->parm.capture.timeperframe.numerator;
0493     d = 1001 * parm->parm.capture.timeperframe.denominator;
0494     if (n != 0 && d != 0 && n > d)
0495         go->fps_scale = (n + d/2) / d;
0496     else
0497         go->fps_scale = 1;
0498 
0499     return vidioc_g_parm(filp, priv, parm);
0500 }
0501 
0502 /* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and
0503    its resolution, when the device is not connected to TV.
0504    This is were an API abuse, probably used by the lack of specific IOCTL's to
0505    enumerate it, by the time the driver was written.
0506 
0507    However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
0508    and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
0509 
0510    The two functions below implement the newer ioctls
0511 */
0512 static int vidioc_enum_framesizes(struct file *filp, void *priv,
0513                   struct v4l2_frmsizeenum *fsize)
0514 {
0515     struct go7007 *go = video_drvdata(filp);
0516     int width, height;
0517 
0518     if (fsize->index > 2)
0519         return -EINVAL;
0520 
0521     if (!valid_pixelformat(fsize->pixel_format))
0522         return -EINVAL;
0523 
0524     get_resolution(go, &width, &height);
0525     fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
0526     fsize->discrete.width = (width >> fsize->index) & ~0xf;
0527     fsize->discrete.height = (height >> fsize->index) & ~0xf;
0528     return 0;
0529 }
0530 
0531 static int vidioc_enum_frameintervals(struct file *filp, void *priv,
0532                       struct v4l2_frmivalenum *fival)
0533 {
0534     struct go7007 *go = video_drvdata(filp);
0535     int width, height;
0536     int i;
0537 
0538     if (fival->index > 4)
0539         return -EINVAL;
0540 
0541     if (!valid_pixelformat(fival->pixel_format))
0542         return -EINVAL;
0543 
0544     if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) {
0545         get_resolution(go, &width, &height);
0546         for (i = 0; i <= 2; i++)
0547             if (fival->width == ((width >> i) & ~0xf) &&
0548                 fival->height == ((height >> i) & ~0xf))
0549                 break;
0550         if (i > 2)
0551             return -EINVAL;
0552     }
0553     fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
0554     fival->discrete.numerator = 1001 * (fival->index + 1);
0555     fival->discrete.denominator = go->sensor_framerate;
0556     return 0;
0557 }
0558 
0559 static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
0560 {
0561     struct go7007 *go = video_drvdata(file);
0562 
0563     *std = go->std;
0564     return 0;
0565 }
0566 
0567 static int go7007_s_std(struct go7007 *go)
0568 {
0569     if (go->std & V4L2_STD_625_50) {
0570         go->standard = GO7007_STD_PAL;
0571         go->sensor_framerate = 25025;
0572     } else {
0573         go->standard = GO7007_STD_NTSC;
0574         go->sensor_framerate = 30000;
0575     }
0576 
0577     call_all(&go->v4l2_dev, video, s_std, go->std);
0578     set_capture_size(go, NULL, 0);
0579     return 0;
0580 }
0581 
0582 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std)
0583 {
0584     struct go7007 *go = video_drvdata(file);
0585 
0586     if (vb2_is_busy(&go->vidq))
0587         return -EBUSY;
0588 
0589     go->std = std;
0590 
0591     return go7007_s_std(go);
0592 }
0593 
0594 static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
0595 {
0596     struct go7007 *go = video_drvdata(file);
0597 
0598     return call_all(&go->v4l2_dev, video, querystd, std);
0599 }
0600 
0601 static int vidioc_enum_input(struct file *file, void *priv,
0602                 struct v4l2_input *inp)
0603 {
0604     struct go7007 *go = video_drvdata(file);
0605 
0606     if (inp->index >= go->board_info->num_inputs)
0607         return -EINVAL;
0608 
0609     strscpy(inp->name, go->board_info->inputs[inp->index].name,
0610         sizeof(inp->name));
0611 
0612     /* If this board has a tuner, it will be the first input */
0613     if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
0614             inp->index == 0)
0615         inp->type = V4L2_INPUT_TYPE_TUNER;
0616     else
0617         inp->type = V4L2_INPUT_TYPE_CAMERA;
0618 
0619     if (go->board_info->num_aud_inputs)
0620         inp->audioset = (1 << go->board_info->num_aud_inputs) - 1;
0621     else
0622         inp->audioset = 0;
0623     inp->tuner = 0;
0624     if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
0625         inp->std = video_devdata(file)->tvnorms;
0626     else
0627         inp->std = 0;
0628 
0629     return 0;
0630 }
0631 
0632 
0633 static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
0634 {
0635     struct go7007 *go = video_drvdata(file);
0636 
0637     *input = go->input;
0638 
0639     return 0;
0640 }
0641 
0642 static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
0643 {
0644     struct go7007 *go = video_drvdata(file);
0645 
0646     if (a->index >= go->board_info->num_aud_inputs)
0647         return -EINVAL;
0648     strscpy(a->name, go->board_info->aud_inputs[a->index].name,
0649         sizeof(a->name));
0650     a->capability = V4L2_AUDCAP_STEREO;
0651     return 0;
0652 }
0653 
0654 static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
0655 {
0656     struct go7007 *go = video_drvdata(file);
0657 
0658     a->index = go->aud_input;
0659     strscpy(a->name, go->board_info->aud_inputs[go->aud_input].name,
0660         sizeof(a->name));
0661     a->capability = V4L2_AUDCAP_STEREO;
0662     return 0;
0663 }
0664 
0665 static int vidioc_s_audio(struct file *file, void *fh,
0666     const struct v4l2_audio *a)
0667 {
0668     struct go7007 *go = video_drvdata(file);
0669 
0670     if (a->index >= go->board_info->num_aud_inputs)
0671         return -EINVAL;
0672     go->aud_input = a->index;
0673     v4l2_subdev_call(go->sd_audio, audio, s_routing,
0674         go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0);
0675     return 0;
0676 }
0677 
0678 static void go7007_s_input(struct go7007 *go)
0679 {
0680     unsigned int input = go->input;
0681 
0682     v4l2_subdev_call(go->sd_video, video, s_routing,
0683             go->board_info->inputs[input].video_input, 0,
0684             go->board_info->video_config);
0685     if (go->board_info->num_aud_inputs) {
0686         int aud_input = go->board_info->inputs[input].audio_index;
0687 
0688         v4l2_subdev_call(go->sd_audio, audio, s_routing,
0689             go->board_info->aud_inputs[aud_input].audio_input, 0, 0);
0690         go->aud_input = aud_input;
0691     }
0692 }
0693 
0694 static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
0695 {
0696     struct go7007 *go = video_drvdata(file);
0697 
0698     if (input >= go->board_info->num_inputs)
0699         return -EINVAL;
0700     if (vb2_is_busy(&go->vidq))
0701         return -EBUSY;
0702 
0703     go->input = input;
0704     go7007_s_input(go);
0705 
0706     return 0;
0707 }
0708 
0709 static int vidioc_g_tuner(struct file *file, void *priv,
0710                 struct v4l2_tuner *t)
0711 {
0712     struct go7007 *go = video_drvdata(file);
0713 
0714     if (t->index != 0)
0715         return -EINVAL;
0716 
0717     strscpy(t->name, "Tuner", sizeof(t->name));
0718     return call_all(&go->v4l2_dev, tuner, g_tuner, t);
0719 }
0720 
0721 static int vidioc_s_tuner(struct file *file, void *priv,
0722                 const struct v4l2_tuner *t)
0723 {
0724     struct go7007 *go = video_drvdata(file);
0725 
0726     if (t->index != 0)
0727         return -EINVAL;
0728 
0729     return call_all(&go->v4l2_dev, tuner, s_tuner, t);
0730 }
0731 
0732 static int vidioc_g_frequency(struct file *file, void *priv,
0733                 struct v4l2_frequency *f)
0734 {
0735     struct go7007 *go = video_drvdata(file);
0736 
0737     if (f->tuner)
0738         return -EINVAL;
0739 
0740     return call_all(&go->v4l2_dev, tuner, g_frequency, f);
0741 }
0742 
0743 static int vidioc_s_frequency(struct file *file, void *priv,
0744                 const struct v4l2_frequency *f)
0745 {
0746     struct go7007 *go = video_drvdata(file);
0747 
0748     if (f->tuner)
0749         return -EINVAL;
0750 
0751     return call_all(&go->v4l2_dev, tuner, s_frequency, f);
0752 }
0753 
0754 static int vidioc_log_status(struct file *file, void *priv)
0755 {
0756     struct go7007 *go = video_drvdata(file);
0757 
0758     v4l2_ctrl_log_status(file, priv);
0759     return call_all(&go->v4l2_dev, core, log_status);
0760 }
0761 
0762 static int vidioc_subscribe_event(struct v4l2_fh *fh,
0763                 const struct v4l2_event_subscription *sub)
0764 {
0765 
0766     switch (sub->type) {
0767     case V4L2_EVENT_MOTION_DET:
0768         /* Allow for up to 30 events (1 second for NTSC) to be
0769          * stored. */
0770         return v4l2_event_subscribe(fh, sub, 30, NULL);
0771     default:
0772         return v4l2_ctrl_subscribe_event(fh, sub);
0773     }
0774 }
0775 
0776 
0777 static int go7007_s_ctrl(struct v4l2_ctrl *ctrl)
0778 {
0779     struct go7007 *go =
0780         container_of(ctrl->handler, struct go7007, hdl);
0781     unsigned y;
0782     u8 *mt;
0783 
0784     switch (ctrl->id) {
0785     case V4L2_CID_PIXEL_THRESHOLD0:
0786         go->modet[0].pixel_threshold = ctrl->val;
0787         break;
0788     case V4L2_CID_MOTION_THRESHOLD0:
0789         go->modet[0].motion_threshold = ctrl->val;
0790         break;
0791     case V4L2_CID_MB_THRESHOLD0:
0792         go->modet[0].mb_threshold = ctrl->val;
0793         break;
0794     case V4L2_CID_PIXEL_THRESHOLD1:
0795         go->modet[1].pixel_threshold = ctrl->val;
0796         break;
0797     case V4L2_CID_MOTION_THRESHOLD1:
0798         go->modet[1].motion_threshold = ctrl->val;
0799         break;
0800     case V4L2_CID_MB_THRESHOLD1:
0801         go->modet[1].mb_threshold = ctrl->val;
0802         break;
0803     case V4L2_CID_PIXEL_THRESHOLD2:
0804         go->modet[2].pixel_threshold = ctrl->val;
0805         break;
0806     case V4L2_CID_MOTION_THRESHOLD2:
0807         go->modet[2].motion_threshold = ctrl->val;
0808         break;
0809     case V4L2_CID_MB_THRESHOLD2:
0810         go->modet[2].mb_threshold = ctrl->val;
0811         break;
0812     case V4L2_CID_PIXEL_THRESHOLD3:
0813         go->modet[3].pixel_threshold = ctrl->val;
0814         break;
0815     case V4L2_CID_MOTION_THRESHOLD3:
0816         go->modet[3].motion_threshold = ctrl->val;
0817         break;
0818     case V4L2_CID_MB_THRESHOLD3:
0819         go->modet[3].mb_threshold = ctrl->val;
0820         break;
0821     case V4L2_CID_DETECT_MD_REGION_GRID:
0822         mt = go->modet_map;
0823         for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
0824             memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
0825         break;
0826     default:
0827         return -EINVAL;
0828     }
0829     return 0;
0830 }
0831 
0832 static const struct v4l2_file_operations go7007_fops = {
0833     .owner      = THIS_MODULE,
0834     .open       = v4l2_fh_open,
0835     .release    = vb2_fop_release,
0836     .unlocked_ioctl = video_ioctl2,
0837     .read       = vb2_fop_read,
0838     .mmap       = vb2_fop_mmap,
0839     .poll       = vb2_fop_poll,
0840 };
0841 
0842 static const struct v4l2_ioctl_ops video_ioctl_ops = {
0843     .vidioc_querycap          = vidioc_querycap,
0844     .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
0845     .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
0846     .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
0847     .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
0848     .vidioc_reqbufs           = vb2_ioctl_reqbufs,
0849     .vidioc_querybuf          = vb2_ioctl_querybuf,
0850     .vidioc_qbuf              = vb2_ioctl_qbuf,
0851     .vidioc_dqbuf             = vb2_ioctl_dqbuf,
0852     .vidioc_g_std             = vidioc_g_std,
0853     .vidioc_s_std             = vidioc_s_std,
0854     .vidioc_querystd          = vidioc_querystd,
0855     .vidioc_enum_input        = vidioc_enum_input,
0856     .vidioc_g_input           = vidioc_g_input,
0857     .vidioc_s_input           = vidioc_s_input,
0858     .vidioc_enumaudio         = vidioc_enumaudio,
0859     .vidioc_g_audio           = vidioc_g_audio,
0860     .vidioc_s_audio           = vidioc_s_audio,
0861     .vidioc_streamon          = vb2_ioctl_streamon,
0862     .vidioc_streamoff         = vb2_ioctl_streamoff,
0863     .vidioc_g_tuner           = vidioc_g_tuner,
0864     .vidioc_s_tuner           = vidioc_s_tuner,
0865     .vidioc_g_frequency       = vidioc_g_frequency,
0866     .vidioc_s_frequency       = vidioc_s_frequency,
0867     .vidioc_g_parm            = vidioc_g_parm,
0868     .vidioc_s_parm            = vidioc_s_parm,
0869     .vidioc_enum_framesizes   = vidioc_enum_framesizes,
0870     .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
0871     .vidioc_log_status        = vidioc_log_status,
0872     .vidioc_subscribe_event   = vidioc_subscribe_event,
0873     .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
0874 };
0875 
0876 static const struct video_device go7007_template = {
0877     .name       = "go7007",
0878     .fops       = &go7007_fops,
0879     .release    = video_device_release_empty,
0880     .ioctl_ops  = &video_ioctl_ops,
0881     .tvnorms    = V4L2_STD_ALL,
0882 };
0883 
0884 static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
0885     .s_ctrl = go7007_s_ctrl,
0886 };
0887 
0888 static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
0889     .ops = &go7007_ctrl_ops,
0890     .id = V4L2_CID_PIXEL_THRESHOLD0,
0891     .name = "Pixel Threshold Region 0",
0892     .type = V4L2_CTRL_TYPE_INTEGER,
0893     .def = 20,
0894     .max = 32767,
0895     .step = 1,
0896 };
0897 
0898 static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
0899     .ops = &go7007_ctrl_ops,
0900     .id = V4L2_CID_MOTION_THRESHOLD0,
0901     .name = "Motion Threshold Region 0",
0902     .type = V4L2_CTRL_TYPE_INTEGER,
0903     .def = 80,
0904     .max = 32767,
0905     .step = 1,
0906 };
0907 
0908 static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = {
0909     .ops = &go7007_ctrl_ops,
0910     .id = V4L2_CID_MB_THRESHOLD0,
0911     .name = "MB Threshold Region 0",
0912     .type = V4L2_CTRL_TYPE_INTEGER,
0913     .def = 200,
0914     .max = 32767,
0915     .step = 1,
0916 };
0917 
0918 static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = {
0919     .ops = &go7007_ctrl_ops,
0920     .id = V4L2_CID_PIXEL_THRESHOLD1,
0921     .name = "Pixel Threshold Region 1",
0922     .type = V4L2_CTRL_TYPE_INTEGER,
0923     .def = 20,
0924     .max = 32767,
0925     .step = 1,
0926 };
0927 
0928 static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = {
0929     .ops = &go7007_ctrl_ops,
0930     .id = V4L2_CID_MOTION_THRESHOLD1,
0931     .name = "Motion Threshold Region 1",
0932     .type = V4L2_CTRL_TYPE_INTEGER,
0933     .def = 80,
0934     .max = 32767,
0935     .step = 1,
0936 };
0937 
0938 static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = {
0939     .ops = &go7007_ctrl_ops,
0940     .id = V4L2_CID_MB_THRESHOLD1,
0941     .name = "MB Threshold Region 1",
0942     .type = V4L2_CTRL_TYPE_INTEGER,
0943     .def = 200,
0944     .max = 32767,
0945     .step = 1,
0946 };
0947 
0948 static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = {
0949     .ops = &go7007_ctrl_ops,
0950     .id = V4L2_CID_PIXEL_THRESHOLD2,
0951     .name = "Pixel Threshold Region 2",
0952     .type = V4L2_CTRL_TYPE_INTEGER,
0953     .def = 20,
0954     .max = 32767,
0955     .step = 1,
0956 };
0957 
0958 static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = {
0959     .ops = &go7007_ctrl_ops,
0960     .id = V4L2_CID_MOTION_THRESHOLD2,
0961     .name = "Motion Threshold Region 2",
0962     .type = V4L2_CTRL_TYPE_INTEGER,
0963     .def = 80,
0964     .max = 32767,
0965     .step = 1,
0966 };
0967 
0968 static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = {
0969     .ops = &go7007_ctrl_ops,
0970     .id = V4L2_CID_MB_THRESHOLD2,
0971     .name = "MB Threshold Region 2",
0972     .type = V4L2_CTRL_TYPE_INTEGER,
0973     .def = 200,
0974     .max = 32767,
0975     .step = 1,
0976 };
0977 
0978 static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = {
0979     .ops = &go7007_ctrl_ops,
0980     .id = V4L2_CID_PIXEL_THRESHOLD3,
0981     .name = "Pixel Threshold Region 3",
0982     .type = V4L2_CTRL_TYPE_INTEGER,
0983     .def = 20,
0984     .max = 32767,
0985     .step = 1,
0986 };
0987 
0988 static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = {
0989     .ops = &go7007_ctrl_ops,
0990     .id = V4L2_CID_MOTION_THRESHOLD3,
0991     .name = "Motion Threshold Region 3",
0992     .type = V4L2_CTRL_TYPE_INTEGER,
0993     .def = 80,
0994     .max = 32767,
0995     .step = 1,
0996 };
0997 
0998 static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = {
0999     .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 
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 
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 
1150 void go7007_v4l2_remove(struct go7007 *go)
1151 {
1152     v4l2_ctrl_handler_free(&go->hdl);
1153 }