cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

go7007-v4l2.c (30670B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2005-2006 Micronas USA Inc.
      4 */
      5
      6#include <linux/module.h>
      7#include <linux/delay.h>
      8#include <linux/sched.h>
      9#include <linux/spinlock.h>
     10#include <linux/slab.h>
     11#include <linux/fs.h>
     12#include <linux/unistd.h>
     13#include <linux/time.h>
     14#include <linux/vmalloc.h>
     15#include <linux/pagemap.h>
     16#include <linux/i2c.h>
     17#include <linux/mutex.h>
     18#include <linux/uaccess.h>
     19#include <linux/videodev2.h>
     20#include <media/v4l2-common.h>
     21#include <media/v4l2-ioctl.h>
     22#include <media/v4l2-subdev.h>
     23#include <media/v4l2-event.h>
     24#include <media/videobuf2-vmalloc.h>
     25#include <media/i2c/saa7115.h>
     26
     27#include "go7007-priv.h"
     28
     29#define call_all(dev, o, f, args...) \
     30	v4l2_device_call_until_err(dev, 0, o, f, ##args)
     31
     32static bool valid_pixelformat(u32 pixelformat)
     33{
     34	switch (pixelformat) {
     35	case V4L2_PIX_FMT_MJPEG:
     36	case V4L2_PIX_FMT_MPEG1:
     37	case V4L2_PIX_FMT_MPEG2:
     38	case V4L2_PIX_FMT_MPEG4:
     39		return true;
     40	default:
     41		return false;
     42	}
     43}
     44
     45static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
     46{
     47	u8 *ptr = vb2_plane_vaddr(&vb->vb.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
     80static void get_resolution(struct go7007 *go, int *width, int *height)
     81{
     82	switch (go->standard) {
     83	case GO7007_STD_NTSC:
     84		*width = 720;
     85		*height = 480;
     86		break;
     87	case GO7007_STD_PAL:
     88		*width = 720;
     89		*height = 576;
     90		break;
     91	case GO7007_STD_OTHER:
     92	default:
     93		*width = go->board_info->sensor_width;
     94		*height = go->board_info->sensor_height;
     95		break;
     96	}
     97}
     98
     99static void set_formatting(struct go7007 *go)
    100{
    101	if (go->format == V4L2_PIX_FMT_MJPEG) {
    102		go->pali = 0;
    103		go->aspect_ratio = GO7007_RATIO_1_1;
    104		go->gop_size = 0;
    105		go->ipb = 0;
    106		go->closed_gop = 0;
    107		go->repeat_seqhead = 0;
    108		go->seq_header_enable = 0;
    109		go->gop_header_enable = 0;
    110		go->dvd_mode = 0;
    111		return;
    112	}
    113
    114	switch (go->format) {
    115	case V4L2_PIX_FMT_MPEG1:
    116		go->pali = 0;
    117		break;
    118	default:
    119	case V4L2_PIX_FMT_MPEG2:
    120		go->pali = 0x48;
    121		break;
    122	case V4L2_PIX_FMT_MPEG4:
    123		/* For future reference: this is the list of MPEG4
    124		 * profiles that are available, although they are
    125		 * untested:
    126		 *
    127		 * Profile		pali
    128		 * --------------	----
    129		 * PROFILE_S_L0		0x08
    130		 * PROFILE_S_L1		0x01
    131		 * PROFILE_S_L2		0x02
    132		 * PROFILE_S_L3		0x03
    133		 * PROFILE_ARTS_L1	0x91
    134		 * PROFILE_ARTS_L2	0x92
    135		 * PROFILE_ARTS_L3	0x93
    136		 * PROFILE_ARTS_L4	0x94
    137		 * PROFILE_AS_L0	0xf0
    138		 * PROFILE_AS_L1	0xf1
    139		 * PROFILE_AS_L2	0xf2
    140		 * PROFILE_AS_L3	0xf3
    141		 * PROFILE_AS_L4	0xf4
    142		 * PROFILE_AS_L5	0xf5
    143		 */
    144		go->pali = 0xf5;
    145		break;
    146	}
    147	go->gop_size = v4l2_ctrl_g_ctrl(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
    176static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
    177{
    178	int sensor_height = 0, sensor_width = 0;
    179	int width, height;
    180
    181	if (fmt != NULL && !valid_pixelformat(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
    274static int vidioc_querycap(struct file *file, void  *priv,
    275					struct v4l2_capability *cap)
    276{
    277	struct go7007 *go = video_drvdata(file);
    278
    279	strscpy(cap->driver, "go7007", sizeof(cap->driver));
    280	strscpy(cap->card, go->name, sizeof(cap->card));
    281	strscpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info));
    282	return 0;
    283}
    284
    285static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
    286					struct v4l2_fmtdesc *fmt)
    287{
    288	switch (fmt->index) {
    289	case 0:
    290		fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
    291		break;
    292	case 1:
    293		fmt->pixelformat = V4L2_PIX_FMT_MPEG1;
    294		break;
    295	case 2:
    296		fmt->pixelformat = V4L2_PIX_FMT_MPEG2;
    297		break;
    298	case 3:
    299		fmt->pixelformat = V4L2_PIX_FMT_MPEG4;
    300		break;
    301	default:
    302		return -EINVAL;
    303	}
    304	return 0;
    305}
    306
    307static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
    308					struct v4l2_format *fmt)
    309{
    310	struct go7007 *go = video_drvdata(file);
    311
    312	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    313	fmt->fmt.pix.width = go->width;
    314	fmt->fmt.pix.height = go->height;
    315	fmt->fmt.pix.pixelformat = go->format;
    316	fmt->fmt.pix.field = V4L2_FIELD_NONE;
    317	fmt->fmt.pix.bytesperline = 0;
    318	fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
    319	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
    320
    321	return 0;
    322}
    323
    324static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
    325			struct v4l2_format *fmt)
    326{
    327	struct go7007 *go = video_drvdata(file);
    328
    329	return set_capture_size(go, fmt, 1);
    330}
    331
    332static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
    333			struct v4l2_format *fmt)
    334{
    335	struct go7007 *go = video_drvdata(file);
    336
    337	if (vb2_is_busy(&go->vidq))
    338		return -EBUSY;
    339
    340	return set_capture_size(go, fmt, 0);
    341}
    342
    343static int go7007_queue_setup(struct vb2_queue *q,
    344		unsigned int *num_buffers, unsigned int *num_planes,
    345		unsigned int sizes[], struct device *alloc_devs[])
    346{
    347	sizes[0] = GO7007_BUF_SIZE;
    348	*num_planes = 1;
    349
    350	if (*num_buffers < 2)
    351		*num_buffers = 2;
    352
    353	return 0;
    354}
    355
    356static void go7007_buf_queue(struct vb2_buffer *vb)
    357{
    358	struct vb2_queue *vq = vb->vb2_queue;
    359	struct go7007 *go = vb2_get_drv_priv(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
    370static int go7007_buf_prepare(struct vb2_buffer *vb)
    371{
    372	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
    373	struct go7007_buffer *go7007_vb =
    374		container_of(vbuf, struct go7007_buffer, vb);
    375
    376	go7007_vb->modet_active = 0;
    377	go7007_vb->frame_offset = 0;
    378	vb->planes[0].bytesused = 0;
    379	return 0;
    380}
    381
    382static void go7007_buf_finish(struct vb2_buffer *vb)
    383{
    384	struct vb2_queue *vq = vb->vb2_queue;
    385	struct go7007 *go = vb2_get_drv_priv(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
    397static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
    398{
    399	struct go7007 *go = vb2_get_drv_priv(q);
    400	int ret;
    401
    402	set_formatting(go);
    403	mutex_lock(&go->hw_lock);
    404	go->next_seq = 0;
    405	go->active_buf = NULL;
    406	go->modet_event_status = 0;
    407	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
    428static 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
    452static 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
    463static 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
    482static 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*/
    512static 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
    531static 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
    559static 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
    567static 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
    582static 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
    594static 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
    601static 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
    633static 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
    642static 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
    654static 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
    665static 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
    678static 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
    694static 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
    709static 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
    721static 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
    732static 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
    743static 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
    754static 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
    762static 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
    777static 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
    832static 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
    842static 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
    876static 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
    884static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
    885	.s_ctrl = go7007_s_ctrl,
    886};
    887
    888static 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
    898static 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
    908static 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
    918static 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
    928static 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
    938static 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
    948static 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
    958static 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
    968static 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
    978static 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
    988static 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
    998static 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
   1008static 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
   1016int 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
   1074int 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
   1150void go7007_v4l2_remove(struct go7007 *go)
   1151{
   1152	v4l2_ctrl_handler_free(&go->hdl);
   1153}