Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[deliverable/linux.git] / drivers / staging / go7007 / go7007-v4l2.c
CommitLineData
866b8695
GKH
1/*
2 * Copyright (C) 2005-2006 Micronas USA Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/version.h>
21#include <linux/delay.h>
22#include <linux/sched.h>
23#include <linux/spinlock.h>
24#include <linux/fs.h>
25#include <linux/unistd.h>
26#include <linux/time.h>
27#include <linux/vmalloc.h>
28#include <linux/pagemap.h>
df20d69e 29#include <linux/videodev2.h>
866b8695
GKH
30#include <media/v4l2-common.h>
31#include <media/v4l2-ioctl.h>
32#include <linux/i2c.h>
fd9a40da 33#include <linux/mutex.h>
866b8695
GKH
34#include <linux/uaccess.h>
35#include <asm/system.h>
36
37#include "go7007.h"
38#include "go7007-priv.h"
39#include "wis-i2c.h"
40
d73f822c
PE
41/* Temporary defines until accepted in v4l-dvb */
42#ifndef V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
43#define V4L2_MPEG_STREAM_TYPE_MPEG_ELEM 6 /* MPEG elementary stream */
44#endif
45#ifndef V4L2_MPEG_VIDEO_ENCODING_MPEG_4
46#define V4L2_MPEG_VIDEO_ENCODING_MPEG_4 3
47#endif
48
866b8695
GKH
49static void deactivate_buffer(struct go7007_buffer *gobuf)
50{
51 int i;
52
53 if (gobuf->state != BUF_STATE_IDLE) {
54 list_del(&gobuf->stream);
55 gobuf->state = BUF_STATE_IDLE;
56 }
57 if (gobuf->page_count > 0) {
58 for (i = 0; i < gobuf->page_count; ++i)
59 page_cache_release(gobuf->pages[i]);
60 gobuf->page_count = 0;
61 }
62}
63
64static void abort_queued(struct go7007 *go)
65{
66 struct go7007_buffer *gobuf, *next;
67
68 list_for_each_entry_safe(gobuf, next, &go->stream, stream) {
69 deactivate_buffer(gobuf);
70 }
71}
72
73static int go7007_streamoff(struct go7007 *go)
74{
75 int retval = -EINVAL;
76 unsigned long flags;
77
fd9a40da 78 mutex_lock(&go->hw_lock);
866b8695
GKH
79 if (go->streaming) {
80 go->streaming = 0;
81 go7007_stream_stop(go);
82 spin_lock_irqsave(&go->spinlock, flags);
83 abort_queued(go);
84 spin_unlock_irqrestore(&go->spinlock, flags);
85 go7007_reset_encoder(go);
86 retval = 0;
87 }
fd9a40da 88 mutex_unlock(&go->hw_lock);
866b8695
GKH
89 return 0;
90}
91
60572c0d 92static int go7007_open(struct file *file)
866b8695
GKH
93{
94 struct go7007 *go = video_get_drvdata(video_devdata(file));
95 struct go7007_file *gofh;
96
97 if (go->status != STATUS_ONLINE)
98 return -EBUSY;
99 gofh = kmalloc(sizeof(struct go7007_file), GFP_KERNEL);
100 if (gofh == NULL)
101 return -ENOMEM;
102 ++go->ref_count;
103 gofh->go = go;
fd9a40da 104 mutex_init(&gofh->lock);
866b8695
GKH
105 gofh->buf_count = 0;
106 file->private_data = gofh;
107 return 0;
108}
109
60572c0d 110static int go7007_release(struct file *file)
866b8695
GKH
111{
112 struct go7007_file *gofh = file->private_data;
113 struct go7007 *go = gofh->go;
114
115 if (gofh->buf_count > 0) {
116 go7007_streamoff(go);
117 go->in_use = 0;
118 kfree(gofh->bufs);
119 gofh->buf_count = 0;
120 }
121 kfree(gofh);
122 if (--go->ref_count == 0)
123 kfree(go);
124 file->private_data = NULL;
125 return 0;
126}
127
128static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format)
129{
130 u8 *f = page_address(gobuf->pages[0]);
131
132 switch (format) {
133 case GO7007_FORMAT_MJPEG:
134 return V4L2_BUF_FLAG_KEYFRAME;
135 case GO7007_FORMAT_MPEG4:
136 switch ((f[gobuf->frame_offset + 4] >> 6) & 0x3) {
137 case 0:
138 return V4L2_BUF_FLAG_KEYFRAME;
139 case 1:
140 return V4L2_BUF_FLAG_PFRAME;
141 case 2:
142 return V4L2_BUF_FLAG_BFRAME;
143 default:
144 return 0;
145 }
146 case GO7007_FORMAT_MPEG1:
147 case GO7007_FORMAT_MPEG2:
148 switch ((f[gobuf->frame_offset + 5] >> 3) & 0x7) {
149 case 1:
150 return V4L2_BUF_FLAG_KEYFRAME;
151 case 2:
152 return V4L2_BUF_FLAG_PFRAME;
153 case 3:
154 return V4L2_BUF_FLAG_BFRAME;
155 default:
156 return 0;
157 }
158 }
159
160 return 0;
161}
162
163static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
164{
165 int sensor_height = 0, sensor_width = 0;
166 int width, height, i;
167
168 if (fmt != NULL && fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&
169 fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG &&
170 fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG4)
171 return -EINVAL;
172
173 switch (go->standard) {
174 case GO7007_STD_NTSC:
175 sensor_width = 720;
176 sensor_height = 480;
177 break;
178 case GO7007_STD_PAL:
179 sensor_width = 720;
180 sensor_height = 576;
181 break;
182 case GO7007_STD_OTHER:
183 sensor_width = go->board_info->sensor_width;
184 sensor_height = go->board_info->sensor_height;
185 break;
186 }
187
188 if (fmt == NULL) {
189 width = sensor_width;
190 height = sensor_height;
191 } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
192 if (fmt->fmt.pix.width > sensor_width)
193 width = sensor_width;
194 else if (fmt->fmt.pix.width < 144)
195 width = 144;
196 else
197 width = fmt->fmt.pix.width & ~0x0f;
198
199 if (fmt->fmt.pix.height > sensor_height)
200 height = sensor_height;
201 else if (fmt->fmt.pix.height < 96)
202 height = 96;
203 else
204 height = fmt->fmt.pix.height & ~0x0f;
205 } else {
206 int requested_size = fmt->fmt.pix.width * fmt->fmt.pix.height;
207 int sensor_size = sensor_width * sensor_height;
208
209 if (64 * requested_size < 9 * sensor_size) {
210 width = sensor_width / 4;
211 height = sensor_height / 4;
212 } else if (64 * requested_size < 36 * sensor_size) {
213 width = sensor_width / 2;
214 height = sensor_height / 2;
215 } else {
216 width = sensor_width;
217 height = sensor_height;
218 }
219 width &= ~0xf;
220 height &= ~0xf;
221 }
222
223 if (fmt != NULL) {
224 u32 pixelformat = fmt->fmt.pix.pixelformat;
225
226 memset(fmt, 0, sizeof(*fmt));
227 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
228 fmt->fmt.pix.width = width;
229 fmt->fmt.pix.height = height;
230 fmt->fmt.pix.pixelformat = pixelformat;
231 fmt->fmt.pix.field = V4L2_FIELD_NONE;
232 fmt->fmt.pix.bytesperline = 0;
233 fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
234 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */
235 }
236
237 if (try)
238 return 0;
239
240 go->width = width;
241 go->height = height;
242 go->encoder_h_offset = go->board_info->sensor_h_offset;
243 go->encoder_v_offset = go->board_info->sensor_v_offset;
244 for (i = 0; i < 4; ++i)
245 go->modet[i].enable = 0;
246 for (i = 0; i < 1624; ++i)
247 go->modet_map[i] = 0;
248
249 if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
250 struct video_decoder_resolution res;
251
252 res.width = width;
253 if (height > sensor_height / 2) {
254 res.height = height / 2;
255 go->encoder_v_halve = 0;
256 } else {
257 res.height = height;
258 go->encoder_v_halve = 1;
259 }
260 if (go->i2c_adapter_online)
261 i2c_clients_command(&go->i2c_adapter,
262 DECODER_SET_RESOLUTION, &res);
263 } else {
264 if (width <= sensor_width / 4) {
265 go->encoder_h_halve = 1;
266 go->encoder_v_halve = 1;
267 go->encoder_subsample = 1;
268 } else if (width <= sensor_width / 2) {
269 go->encoder_h_halve = 1;
270 go->encoder_v_halve = 1;
271 go->encoder_subsample = 0;
272 } else {
273 go->encoder_h_halve = 0;
274 go->encoder_v_halve = 0;
275 go->encoder_subsample = 0;
276 }
277 }
278
279 if (fmt == NULL)
280 return 0;
281
282 switch (fmt->fmt.pix.pixelformat) {
283 case V4L2_PIX_FMT_MPEG:
284 if (go->format == GO7007_FORMAT_MPEG1 ||
285 go->format == GO7007_FORMAT_MPEG2 ||
286 go->format == GO7007_FORMAT_MPEG4)
287 break;
288 go->format = GO7007_FORMAT_MPEG1;
289 go->pali = 0;
290 go->aspect_ratio = GO7007_RATIO_1_1;
291 go->gop_size = go->sensor_framerate / 1000;
292 go->ipb = 0;
293 go->closed_gop = 1;
294 go->repeat_seqhead = 1;
295 go->seq_header_enable = 1;
296 go->gop_header_enable = 1;
297 go->dvd_mode = 0;
298 break;
299 /* Backwards compatibility only! */
300 case V4L2_PIX_FMT_MPEG4:
301 if (go->format == GO7007_FORMAT_MPEG4)
302 break;
303 go->format = GO7007_FORMAT_MPEG4;
304 go->pali = 0xf5;
305 go->aspect_ratio = GO7007_RATIO_1_1;
306 go->gop_size = go->sensor_framerate / 1000;
307 go->ipb = 0;
308 go->closed_gop = 1;
309 go->repeat_seqhead = 1;
310 go->seq_header_enable = 1;
311 go->gop_header_enable = 1;
312 go->dvd_mode = 0;
313 break;
314 case V4L2_PIX_FMT_MJPEG:
315 go->format = GO7007_FORMAT_MJPEG;
316 go->pali = 0;
317 go->aspect_ratio = GO7007_RATIO_1_1;
318 go->gop_size = 0;
319 go->ipb = 0;
320 go->closed_gop = 0;
321 go->repeat_seqhead = 0;
322 go->seq_header_enable = 0;
323 go->gop_header_enable = 0;
324 go->dvd_mode = 0;
325 break;
326 }
327 return 0;
328}
329
8fca1cb3 330#if 0
866b8695
GKH
331static int clip_to_modet_map(struct go7007 *go, int region,
332 struct v4l2_clip *clip_list)
333{
334 struct v4l2_clip clip, *clip_ptr;
335 int x, y, mbnum;
336
337 /* Check if coordinates are OK and if any macroblocks are already
338 * used by other regions (besides 0) */
339 clip_ptr = clip_list;
340 while (clip_ptr) {
341 if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
342 return -EFAULT;
343 if (clip.c.left < 0 || (clip.c.left & 0xF) ||
344 clip.c.width <= 0 || (clip.c.width & 0xF))
345 return -EINVAL;
346 if (clip.c.left + clip.c.width > go->width)
347 return -EINVAL;
348 if (clip.c.top < 0 || (clip.c.top & 0xF) ||
349 clip.c.height <= 0 || (clip.c.height & 0xF))
350 return -EINVAL;
351 if (clip.c.top + clip.c.height > go->height)
352 return -EINVAL;
353 for (y = 0; y < clip.c.height; y += 16)
354 for (x = 0; x < clip.c.width; x += 16) {
355 mbnum = (go->width >> 4) *
356 ((clip.c.top + y) >> 4) +
357 ((clip.c.left + x) >> 4);
358 if (go->modet_map[mbnum] != 0 &&
359 go->modet_map[mbnum] != region)
360 return -EBUSY;
361 }
362 clip_ptr = clip.next;
363 }
364
365 /* Clear old region macroblocks */
366 for (mbnum = 0; mbnum < 1624; ++mbnum)
367 if (go->modet_map[mbnum] == region)
368 go->modet_map[mbnum] = 0;
369
370 /* Claim macroblocks in this list */
371 clip_ptr = clip_list;
372 while (clip_ptr) {
373 if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
374 return -EFAULT;
375 for (y = 0; y < clip.c.height; y += 16)
376 for (x = 0; x < clip.c.width; x += 16) {
377 mbnum = (go->width >> 4) *
378 ((clip.c.top + y) >> 4) +
379 ((clip.c.left + x) >> 4);
380 go->modet_map[mbnum] = region;
381 }
382 clip_ptr = clip.next;
383 }
384 return 0;
385}
669022a2 386#endif
866b8695 387
669022a2 388static int mpeg_queryctrl(struct v4l2_queryctrl *ctrl)
d73f822c 389{
d73f822c
PE
390 static const u32 mpeg_ctrls[] = {
391 V4L2_CID_MPEG_CLASS,
392 V4L2_CID_MPEG_STREAM_TYPE,
393 V4L2_CID_MPEG_VIDEO_ENCODING,
394 V4L2_CID_MPEG_VIDEO_ASPECT,
395 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
396 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
397 V4L2_CID_MPEG_VIDEO_BITRATE,
398 0
399 };
400 static const u32 *ctrl_classes[] = {
d73f822c
PE
401 mpeg_ctrls,
402 NULL
403 };
404
669022a2 405 ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
d73f822c
PE
406
407 switch (ctrl->id) {
d73f822c 408 case V4L2_CID_MPEG_CLASS:
669022a2 409 return v4l2_ctrl_query_fill(ctrl, 0, 0, 0, 0);
d73f822c
PE
410 case V4L2_CID_MPEG_STREAM_TYPE:
411 return v4l2_ctrl_query_fill(ctrl,
412 V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
413 V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
414 V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
415 case V4L2_CID_MPEG_VIDEO_ENCODING:
416 return v4l2_ctrl_query_fill(ctrl,
417 V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
418 V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1,
419 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
420 case V4L2_CID_MPEG_VIDEO_ASPECT:
421 return v4l2_ctrl_query_fill(ctrl,
422 V4L2_MPEG_VIDEO_ASPECT_1x1,
423 V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
424 V4L2_MPEG_VIDEO_ASPECT_1x1);
425 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
669022a2 426 return v4l2_ctrl_query_fill(ctrl, 0, 34, 1, 15);
d73f822c 427 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
669022a2 428 return v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0);
d73f822c
PE
429 case V4L2_CID_MPEG_VIDEO_BITRATE:
430 return v4l2_ctrl_query_fill(ctrl,
431 64000,
432 10000000, 1,
669022a2 433 1500000);
d73f822c 434 default:
669022a2 435 return -EINVAL;
d73f822c 436 }
669022a2 437 return 0;
d73f822c
PE
438}
439
669022a2 440static int mpeg_s_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
d73f822c
PE
441{
442 /* pretty sure we can't change any of these while streaming */
443 if (go->streaming)
444 return -EBUSY;
445
446 switch (ctrl->id) {
447 case V4L2_CID_MPEG_STREAM_TYPE:
448 switch (ctrl->value) {
449 case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
450 go->format = GO7007_FORMAT_MPEG2;
451 go->bitrate = 9800000;
452 go->gop_size = 15;
453 go->pali = 0x48;
454 go->closed_gop = 1;
455 go->repeat_seqhead = 0;
456 go->seq_header_enable = 1;
457 go->gop_header_enable = 1;
458 go->dvd_mode = 1;
459 break;
460 case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM:
461 /* todo: */
462 break;
463 default:
464 return -EINVAL;
465 }
466 break;
467 case V4L2_CID_MPEG_VIDEO_ENCODING:
468 switch (ctrl->value) {
469 case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
470 go->format = GO7007_FORMAT_MPEG1;
471 go->pali = 0;
472 break;
473 case V4L2_MPEG_VIDEO_ENCODING_MPEG_2:
474 go->format = GO7007_FORMAT_MPEG2;
475 /*if (mpeg->pali >> 24 == 2)
476 go->pali = mpeg->pali & 0xff;
477 else*/
478 go->pali = 0x48;
479 break;
480 case V4L2_MPEG_VIDEO_ENCODING_MPEG_4:
481 go->format = GO7007_FORMAT_MPEG4;
482 /*if (mpeg->pali >> 24 == 4)
483 go->pali = mpeg->pali & 0xff;
484 else*/
485 go->pali = 0xf5;
486 break;
487 default:
488 return -EINVAL;
489 }
490 go->gop_header_enable =
491 /*mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
492 ? 0 :*/ 1;
493 /*if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
494 go->repeat_seqhead = 1;
495 else*/
496 go->repeat_seqhead = 0;
497 go->dvd_mode = 0;
498 break;
499 case V4L2_CID_MPEG_VIDEO_ASPECT:
500 if (go->format == GO7007_FORMAT_MJPEG)
501 return -EINVAL;
502 switch (ctrl->value) {
503 case V4L2_MPEG_VIDEO_ASPECT_1x1:
504 go->aspect_ratio = GO7007_RATIO_1_1;
505 break;
506 case V4L2_MPEG_VIDEO_ASPECT_4x3:
507 go->aspect_ratio = GO7007_RATIO_4_3;
508 break;
509 case V4L2_MPEG_VIDEO_ASPECT_16x9:
510 go->aspect_ratio = GO7007_RATIO_16_9;
511 break;
512 case V4L2_MPEG_VIDEO_ASPECT_221x100:
513 default:
514 return -EINVAL;
515 }
516 break;
517 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
669022a2
PE
518 if (ctrl->value < 0 || ctrl->value > 34)
519 return -EINVAL;
d73f822c
PE
520 go->gop_size = ctrl->value;
521 break;
522 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
523 if (ctrl->value != 0 && ctrl->value != 1)
524 return -EINVAL;
525 go->closed_gop = ctrl->value;
526 break;
527 case V4L2_CID_MPEG_VIDEO_BITRATE:
528 /* Upper bound is kind of arbitrary here */
529 if (ctrl->value < 64000 || ctrl->value > 10000000)
530 return -EINVAL;
531 go->bitrate = ctrl->value;
532 break;
533 default:
534 return -EINVAL;
535 }
536 return 0;
537}
538
669022a2 539static int mpeg_g_ctrl(struct v4l2_control *ctrl, struct go7007 *go)
d73f822c
PE
540{
541 switch (ctrl->id) {
542 case V4L2_CID_MPEG_STREAM_TYPE:
543 if (go->dvd_mode)
544 ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
545 else
546 ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG_ELEM;
547 break;
548 case V4L2_CID_MPEG_VIDEO_ENCODING:
549 switch (go->format) {
550 case GO7007_FORMAT_MPEG1:
551 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
552 break;
553 case GO7007_FORMAT_MPEG2:
554 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
555 break;
556 case GO7007_FORMAT_MPEG4:
557 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
558 break;
559 default:
560 return -EINVAL;
561 }
562 break;
563 case V4L2_CID_MPEG_VIDEO_ASPECT:
564 switch (go->aspect_ratio) {
565 case GO7007_RATIO_1_1:
566 ctrl->value = V4L2_MPEG_VIDEO_ASPECT_1x1;
567 break;
568 case GO7007_RATIO_4_3:
569 ctrl->value = V4L2_MPEG_VIDEO_ASPECT_4x3;
570 break;
571 case GO7007_RATIO_16_9:
572 ctrl->value = V4L2_MPEG_VIDEO_ASPECT_16x9;
573 break;
574 default:
575 return -EINVAL;
576 }
577 break;
578 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
579 ctrl->value = go->gop_size;
580 break;
581 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
582 ctrl->value = go->closed_gop;
583 break;
584 case V4L2_CID_MPEG_VIDEO_BITRATE:
585 ctrl->value = go->bitrate;
586 break;
587 default:
588 return -EINVAL;
589 }
590 return 0;
591}
592
65f9f619
MCC
593static int vidioc_querycap(struct file *file, void *priv,
594 struct v4l2_capability *cap)
866b8695 595{
f4135b69 596 struct go7007 *go = ((struct go7007_file *) priv)->go;
866b8695 597
65f9f619
MCC
598 strlcpy(cap->driver, "go7007", sizeof(cap->driver));
599 strlcpy(cap->card, go->name, sizeof(cap->card));
600#if 0
601 strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
602#endif
866b8695 603
65f9f619 604 cap->version = KERNEL_VERSION(0, 9, 8);
866b8695 605
65f9f619
MCC
606 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
607 V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */
866b8695 608
65f9f619
MCC
609 if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
610 cap->capabilities |= V4L2_CAP_TUNER;
866b8695 611
65f9f619
MCC
612 return 0;
613}
866b8695 614
65f9f619
MCC
615static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
616 struct v4l2_fmtdesc *fmt)
617{
618 char *desc = NULL;
d73f822c 619
65f9f619
MCC
620 switch (fmt->index) {
621 case 0:
622 fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
623 desc = "Motion-JPEG";
624 break;
625 case 1:
626 fmt->pixelformat = V4L2_PIX_FMT_MPEG;
627 desc = "MPEG1/MPEG2/MPEG4";
628 break;
629 default:
866b8695 630 return -EINVAL;
65f9f619
MCC
631 }
632 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
633 fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
866b8695 634
65f9f619 635 strncpy(fmt->description, desc, sizeof(fmt->description));
866b8695 636
65f9f619
MCC
637 return 0;
638}
639
640static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
641 struct v4l2_format *fmt)
642{
f4135b69 643 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
644
645 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
646 fmt->fmt.pix.width = go->width;
647 fmt->fmt.pix.height = go->height;
648 fmt->fmt.pix.pixelformat = (go->format == GO7007_FORMAT_MJPEG) ?
649 V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG;
650 fmt->fmt.pix.field = V4L2_FIELD_NONE;
651 fmt->fmt.pix.bytesperline = 0;
652 fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
653 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
654
655 return 0;
656}
657
658static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
659 struct v4l2_format *fmt)
660{
f4135b69 661 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
662
663 return set_capture_size(go, fmt, 1);
664}
665
666static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
667 struct v4l2_format *fmt)
668{
f4135b69 669 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
670
671 if (go->streaming)
672 return -EBUSY;
673
674 return set_capture_size(go, fmt, 0);
675}
676
677static int vidioc_reqbufs(struct file *file, void *priv,
678 struct v4l2_requestbuffers *req)
679{
680 struct go7007_file *gofh = priv;
681 struct go7007 *go = gofh->go;
682 int retval = -EBUSY;
683 unsigned int count, i;
684
685 if (go->streaming)
686 return retval;
687
688 if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
689 req->memory != V4L2_MEMORY_MMAP)
690 return -EINVAL;
691
fd9a40da 692 mutex_lock(&gofh->lock);
65f9f619
MCC
693 for (i = 0; i < gofh->buf_count; ++i)
694 if (gofh->bufs[i].mapped > 0)
866b8695 695 goto unlock_and_return;
65f9f619 696
fd9a40da 697 mutex_lock(&go->hw_lock);
65f9f619 698 if (go->in_use > 0 && gofh->buf_count == 0) {
fd9a40da 699 mutex_unlock(&go->hw_lock);
65f9f619 700 goto unlock_and_return;
866b8695 701 }
866b8695 702
65f9f619
MCC
703 if (gofh->buf_count > 0)
704 kfree(gofh->bufs);
866b8695 705
65f9f619
MCC
706 retval = -ENOMEM;
707 count = req->count;
708 if (count > 0) {
709 if (count < 2)
710 count = 2;
711 if (count > 32)
712 count = 32;
866b8695 713
65f9f619
MCC
714 gofh->bufs = kmalloc(count * sizeof(struct go7007_buffer),
715 GFP_KERNEL);
716
717 if (!gofh->bufs) {
fd9a40da 718 mutex_unlock(&go->hw_lock);
866b8695
GKH
719 goto unlock_and_return;
720 }
866b8695 721
65f9f619
MCC
722 memset(gofh->bufs, 0, count * sizeof(struct go7007_buffer));
723
724 for (i = 0; i < count; ++i) {
725 gofh->bufs[i].go = go;
726 gofh->bufs[i].index = i;
727 gofh->bufs[i].state = BUF_STATE_IDLE;
728 gofh->bufs[i].mapped = 0;
866b8695 729 }
65f9f619
MCC
730
731 go->in_use = 1;
732 } else {
733 go->in_use = 0;
866b8695 734 }
866b8695 735
65f9f619 736 gofh->buf_count = count;
fd9a40da
MCC
737 mutex_unlock(&go->hw_lock);
738 mutex_unlock(&gofh->lock);
65f9f619
MCC
739
740 memset(req, 0, sizeof(*req));
741
742 req->count = count;
743 req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
744 req->memory = V4L2_MEMORY_MMAP;
745
746 return 0;
747
748unlock_and_return:
fd9a40da 749 mutex_unlock(&gofh->lock);
65f9f619
MCC
750 return retval;
751}
752
753static int vidioc_querybuf(struct file *file, void *priv,
754 struct v4l2_buffer *buf)
755{
756 struct go7007_file *gofh = priv;
757 int retval = -EINVAL;
758 unsigned int index;
759
760 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
866b8695 761 return retval;
866b8695 762
65f9f619 763 index = buf->index;
866b8695 764
fd9a40da 765 mutex_lock(&gofh->lock);
65f9f619
MCC
766 if (index >= gofh->buf_count)
767 goto unlock_and_return;
866b8695 768
65f9f619
MCC
769 memset(buf, 0, sizeof(*buf));
770 buf->index = index;
771 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
772
773 switch (gofh->bufs[index].state) {
774 case BUF_STATE_QUEUED:
775 buf->flags = V4L2_BUF_FLAG_QUEUED;
776 break;
777 case BUF_STATE_DONE:
778 buf->flags = V4L2_BUF_FLAG_DONE;
779 break;
780 default:
781 buf->flags = 0;
866b8695 782 }
866b8695 783
65f9f619
MCC
784 if (gofh->bufs[index].mapped)
785 buf->flags |= V4L2_BUF_FLAG_MAPPED;
786 buf->memory = V4L2_MEMORY_MMAP;
787 buf->m.offset = index * GO7007_BUF_SIZE;
788 buf->length = GO7007_BUF_SIZE;
fd9a40da 789 mutex_unlock(&gofh->lock);
65f9f619
MCC
790
791 return 0;
792
793unlock_and_return:
fd9a40da 794 mutex_unlock(&gofh->lock);
65f9f619
MCC
795 return retval;
796}
797
798static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
799{
800 struct go7007_file *gofh = priv;
801 struct go7007 *go = gofh->go;
802 struct go7007_buffer *gobuf;
803 unsigned long flags;
804 int retval = -EINVAL;
805 int ret;
806
807 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
808 buf->memory != V4L2_MEMORY_MMAP)
809 return retval;
810
fd9a40da 811 mutex_lock(&gofh->lock);
65f9f619
MCC
812 if (buf->index < 0 || buf->index >= gofh->buf_count)
813 goto unlock_and_return;
814
815 gobuf = &gofh->bufs[buf->index];
816 if (!gobuf->mapped)
817 goto unlock_and_return;
818
819 retval = -EBUSY;
820 if (gobuf->state != BUF_STATE_IDLE)
821 goto unlock_and_return;
822
823 /* offset will be 0 until we really support USERPTR streaming */
824 gobuf->offset = gobuf->user_addr & ~PAGE_MASK;
825 gobuf->bytesused = 0;
826 gobuf->frame_offset = 0;
827 gobuf->modet_active = 0;
828 if (gobuf->offset > 0)
829 gobuf->page_count = GO7007_BUF_PAGES + 1;
830 else
831 gobuf->page_count = GO7007_BUF_PAGES;
832
833 retval = -ENOMEM;
834 down_read(&current->mm->mmap_sem);
835 ret = get_user_pages(current, current->mm,
836 gobuf->user_addr & PAGE_MASK, gobuf->page_count,
837 1, 1, gobuf->pages, NULL);
838 up_read(&current->mm->mmap_sem);
839
840 if (ret != gobuf->page_count) {
841 int i;
842 for (i = 0; i < ret; ++i)
843 page_cache_release(gobuf->pages[i]);
844 gobuf->page_count = 0;
845 goto unlock_and_return;
866b8695 846 }
866b8695 847
65f9f619
MCC
848 gobuf->state = BUF_STATE_QUEUED;
849 spin_lock_irqsave(&go->spinlock, flags);
850 list_add_tail(&gobuf->stream, &go->stream);
851 spin_unlock_irqrestore(&go->spinlock, flags);
fd9a40da 852 mutex_unlock(&gofh->lock);
65f9f619
MCC
853
854 return 0;
855
856unlock_and_return:
fd9a40da 857 mutex_unlock(&gofh->lock);
65f9f619
MCC
858 return retval;
859}
860
861
862static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
863{
864 struct go7007_file *gofh = priv;
865 struct go7007 *go = gofh->go;
866 struct go7007_buffer *gobuf;
867 int retval = -EINVAL;
868 unsigned long flags;
869 u32 frame_type_flag;
870 DEFINE_WAIT(wait);
871
872 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
873 return retval;
874 if (buf->memory != V4L2_MEMORY_MMAP)
875 return retval;
876
fd9a40da 877 mutex_lock(&gofh->lock);
65f9f619
MCC
878 if (list_empty(&go->stream))
879 goto unlock_and_return;
880 gobuf = list_entry(go->stream.next,
881 struct go7007_buffer, stream);
882
883 retval = -EAGAIN;
884 if (gobuf->state != BUF_STATE_DONE &&
885 !(file->f_flags & O_NONBLOCK)) {
886 for (;;) {
887 prepare_to_wait(&go->frame_waitq, &wait,
888 TASK_INTERRUPTIBLE);
889 if (gobuf->state == BUF_STATE_DONE)
890 break;
891 if (signal_pending(current)) {
892 retval = -ERESTARTSYS;
893 break;
894 }
895 schedule();
896 }
897 finish_wait(&go->frame_waitq, &wait);
898 }
899 if (gobuf->state != BUF_STATE_DONE)
900 goto unlock_and_return;
901
902 spin_lock_irqsave(&go->spinlock, flags);
903 deactivate_buffer(gobuf);
904 spin_unlock_irqrestore(&go->spinlock, flags);
905 frame_type_flag = get_frame_type_flag(gobuf, go->format);
906 gobuf->state = BUF_STATE_IDLE;
907
908 memset(buf, 0, sizeof(*buf));
909 buf->index = gobuf->index;
910 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
911 buf->bytesused = gobuf->bytesused;
912 buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag;
913 buf->field = V4L2_FIELD_NONE;
914 buf->timestamp = gobuf->timestamp;
915 buf->sequence = gobuf->seq;
916 buf->memory = V4L2_MEMORY_MMAP;
917 buf->m.offset = gobuf->index * GO7007_BUF_SIZE;
918 buf->length = GO7007_BUF_SIZE;
919 buf->reserved = gobuf->modet_active;
920
fd9a40da 921 mutex_unlock(&gofh->lock);
65f9f619
MCC
922 return 0;
923
924unlock_and_return:
fd9a40da 925 mutex_unlock(&gofh->lock);
65f9f619
MCC
926 return retval;
927}
928
929static int vidioc_streamon(struct file *file, void *priv,
930 enum v4l2_buf_type type)
931{
932 struct go7007_file *gofh = priv;
933 struct go7007 *go = gofh->go;
934 int retval = 0;
935
936 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
937 return -EINVAL;
938
fd9a40da
MCC
939 mutex_lock(&gofh->lock);
940 mutex_lock(&go->hw_lock);
65f9f619
MCC
941
942 if (!go->streaming) {
943 go->streaming = 1;
944 go->next_seq = 0;
945 go->active_buf = NULL;
946 if (go7007_start_encoder(go) < 0)
947 retval = -EIO;
948 else
949 retval = 0;
866b8695 950 }
fd9a40da
MCC
951 mutex_unlock(&go->hw_lock);
952 mutex_unlock(&gofh->lock);
866b8695 953
65f9f619
MCC
954 return retval;
955}
956
957static int vidioc_streamoff(struct file *file, void *priv,
958 enum v4l2_buf_type type)
959{
960 struct go7007_file *gofh = priv;
961 struct go7007 *go = gofh->go;
962
963 if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
964 return -EINVAL;
fd9a40da 965 mutex_lock(&gofh->lock);
65f9f619 966 go7007_streamoff(go);
fd9a40da 967 mutex_unlock(&gofh->lock);
65f9f619
MCC
968
969 return 0;
970}
971
972static int vidioc_queryctrl(struct file *file, void *priv,
973 struct v4l2_queryctrl *query)
974{
f4135b69 975 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
976
977 if (!go->i2c_adapter_online)
978 return -EIO;
979
980 i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query);
981
669022a2 982 return (!query->name[0]) ? mpeg_queryctrl(query) : 0;
65f9f619
MCC
983}
984
985static int vidioc_g_ctrl(struct file *file, void *priv,
986 struct v4l2_control *ctrl)
987{
f4135b69 988 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
989 struct v4l2_queryctrl query;
990
991 if (!go->i2c_adapter_online)
992 return -EIO;
993
994 memset(&query, 0, sizeof(query));
995 query.id = ctrl->id;
996 i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
997 if (query.name[0] == 0)
669022a2 998 return mpeg_g_ctrl(ctrl, go);
65f9f619
MCC
999 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl);
1000
1001 return 0;
1002}
1003
1004static int vidioc_s_ctrl(struct file *file, void *priv,
1005 struct v4l2_control *ctrl)
1006{
f4135b69 1007 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1008 struct v4l2_queryctrl query;
1009
1010 if (!go->i2c_adapter_online)
1011 return -EIO;
1012
1013 memset(&query, 0, sizeof(query));
1014 query.id = ctrl->id;
1015 i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
1016 if (query.name[0] == 0)
669022a2 1017 return mpeg_s_ctrl(ctrl, go);
65f9f619
MCC
1018 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl);
1019
1020 return 0;
1021}
1022
1023static int vidioc_g_parm(struct file *filp, void *priv,
1024 struct v4l2_streamparm *parm)
1025{
f4135b69 1026 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1027 struct v4l2_fract timeperframe = {
1028 .numerator = 1001 * go->fps_scale,
1029 .denominator = go->sensor_framerate,
1030 };
1031
1032 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1033 return -EINVAL;
1034
1035 parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
1036 parm->parm.capture.timeperframe = timeperframe;
1037
1038 return 0;
1039}
1040
1041static int vidioc_s_parm(struct file *filp, void *priv,
1042 struct v4l2_streamparm *parm)
1043{
f4135b69 1044 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1045 unsigned int n, d;
1046
1047 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1048 return -EINVAL;
1049 if (parm->parm.capture.capturemode != 0)
1050 return -EINVAL;
1051
1052 n = go->sensor_framerate *
1053 parm->parm.capture.timeperframe.numerator;
1054 d = 1001 * parm->parm.capture.timeperframe.denominator;
1055 if (n != 0 && d != 0 && n > d)
1056 go->fps_scale = (n + d/2) / d;
1057 else
1058 go->fps_scale = 1;
1059
1060 return 0;
1061}
1062
1063/* VIDIOC_ENUMSTD on go7007 were used for enumberating the supported fps and
1064 its resolution, when the device is not connected to TV.
1065 This were an API abuse, probably used by the lack of specific IOCTL's to
1066 enumberate it, by the time the driver were written.
1067
1068 However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
1069 and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
1070
1071 The two functions bellow implements the newer ioctls
1072*/
65f9f619
MCC
1073static int vidioc_enum_framesizes(struct file *filp, void *priv,
1074 struct v4l2_frmsizeenum *fsize)
1075{
f4135b69 1076 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1077
1078 /* Return -EINVAL, if it is a TV board */
1079 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
1080 (go->board_info->sensor_flags & GO7007_SENSOR_TV))
1081 return -EINVAL;
1082
1083 if (fsize->index > 0)
1084 return -EINVAL;
1085
1086 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
1087 fsize->discrete.width = go->board_info->sensor_width;
1088 fsize->discrete.height = go->board_info->sensor_height;
1089
1090 return 0;
1091}
1092
1093static int vidioc_enum_frameintervals(struct file *filp, void *priv,
1094 struct v4l2_frmivalenum *fival)
1095{
f4135b69 1096 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1097
1098 /* Return -EINVAL, if it is a TV board */
1099 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
1100 (go->board_info->sensor_flags & GO7007_SENSOR_TV))
1101 return -EINVAL;
1102
1103 if (fival->index > 0)
1104 return -EINVAL;
1105
1106 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
1107 fival->discrete.numerator = 1001;
1108 fival->discrete.denominator = go->board_info->sensor_framerate;
1109
1110 return 0;
1111}
1112
bb871652
PE
1113static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std)
1114{
1115 struct go7007 *go = ((struct go7007_file *) priv)->go;
1116
1117 switch (go->standard) {
1118 case GO7007_STD_NTSC:
1119 *std = V4L2_STD_NTSC;
1120 break;
1121 case GO7007_STD_PAL:
1122 *std = V4L2_STD_PAL;
1123 break;
1124 default:
1125 return -EINVAL;
1126 }
1127
1128 return 0;
1129}
1130
65f9f619
MCC
1131static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
1132{
f4135b69 1133 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1134
1135 if (go->streaming)
1136 return -EBUSY;
1137
1138 if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
1139 *std != 0)
1140 return -EINVAL;
1141
1142 if (*std == 0)
1143 return -EINVAL;
1144
1145 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1146 go->input == go->board_info->num_inputs - 1) {
1147 if (!go->i2c_adapter_online)
1148 return -EIO;
1149 i2c_clients_command(&go->i2c_adapter,
1150 VIDIOC_S_STD, std);
1151 if (!*std) /* hack to indicate EINVAL from tuner */
866b8695 1152 return -EINVAL;
866b8695 1153 }
866b8695 1154
65f9f619
MCC
1155 if (*std & V4L2_STD_NTSC) {
1156 go->standard = GO7007_STD_NTSC;
1157 go->sensor_framerate = 30000;
1158 } else if (*std & V4L2_STD_PAL) {
1159 go->standard = GO7007_STD_PAL;
1160 go->sensor_framerate = 25025;
1161 } else if (*std & V4L2_STD_SECAM) {
1162 go->standard = GO7007_STD_PAL;
1163 go->sensor_framerate = 25025;
1164 } else
1165 return -EINVAL;
866b8695 1166
65f9f619
MCC
1167 if (go->i2c_adapter_online)
1168 i2c_clients_command(&go->i2c_adapter,
1169 VIDIOC_S_STD, std);
1170 set_capture_size(go, NULL, 0);
866b8695 1171
65f9f619
MCC
1172 return 0;
1173}
d73f822c 1174
bb871652
PE
1175static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std)
1176{
1177 struct go7007 *go = ((struct go7007_file *) priv)->go;
866b8695 1178
bb871652
PE
1179 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1180 go->input == go->board_info->num_inputs - 1) {
1181 if (!go->i2c_adapter_online)
1182 return -EIO;
1183 i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYSTD, std);
1184 } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1185 *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
1186 else
1187 *std = 0;
1188
1189 return 0;
1190}
866b8695 1191
65f9f619
MCC
1192static int vidioc_enum_input(struct file *file, void *priv,
1193 struct v4l2_input *inp)
1194{
f4135b69 1195 struct go7007 *go = ((struct go7007_file *) priv)->go;
866b8695 1196
65f9f619
MCC
1197 if (inp->index >= go->board_info->num_inputs)
1198 return -EINVAL;
866b8695 1199
65f9f619
MCC
1200 strncpy(inp->name, go->board_info->inputs[inp->index].name,
1201 sizeof(inp->name));
866b8695 1202
65f9f619
MCC
1203 /* If this board has a tuner, it will be the last input */
1204 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1205 inp->index == go->board_info->num_inputs - 1)
1206 inp->type = V4L2_INPUT_TYPE_TUNER;
1207 else
1208 inp->type = V4L2_INPUT_TYPE_CAMERA;
866b8695 1209
65f9f619
MCC
1210 inp->audioset = 0;
1211 inp->tuner = 0;
1212 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1213 inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
1214 V4L2_STD_SECAM;
1215 else
1216 inp->std = 0;
866b8695 1217
65f9f619
MCC
1218 return 0;
1219}
866b8695 1220
866b8695 1221
65f9f619
MCC
1222static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
1223{
f4135b69 1224 struct go7007 *go = ((struct go7007_file *) priv)->go;
866b8695 1225
65f9f619 1226 *input = go->input;
866b8695 1227
65f9f619
MCC
1228 return 0;
1229}
1230
1231static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
1232{
f4135b69 1233 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1234
1235 if (input >= go->board_info->num_inputs)
1236 return -EINVAL;
1237 if (go->streaming)
1238 return -EBUSY;
1239
1240 go->input = input;
1241 if (go->i2c_adapter_online) {
1242 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT,
1243 &go->board_info->inputs[input].video_input);
1244 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO,
1245 &go->board_info->inputs[input].audio_input);
866b8695 1246 }
866b8695 1247
65f9f619
MCC
1248 return 0;
1249}
1250
1251static int vidioc_g_tuner(struct file *file, void *priv,
1252 struct v4l2_tuner *t)
1253{
f4135b69 1254 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1255
1256 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1257 return -EINVAL;
1258 if (t->index != 0)
1259 return -EINVAL;
1260 if (!go->i2c_adapter_online)
1261 return -EIO;
1262
1263 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, t);
1264
1265 t->index = 0;
1266 return 0;
1267}
1268
1269static int vidioc_s_tuner(struct file *file, void *priv,
1270 struct v4l2_tuner *t)
1271{
f4135b69 1272 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1273
1274 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1275 return -EINVAL;
1276 if (t->index != 0)
1277 return -EINVAL;
1278 if (!go->i2c_adapter_online)
1279 return -EIO;
1280
1281 switch (go->board_id) {
1282 case GO7007_BOARDID_PX_TV402U_NA:
1283 case GO7007_BOARDID_PX_TV402U_JP:
1284 /* No selectable options currently */
1285 if (t->audmode != V4L2_TUNER_MODE_STEREO)
866b8695 1286 return -EINVAL;
65f9f619 1287 break;
866b8695 1288 }
866b8695 1289
65f9f619 1290 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, t);
866b8695 1291
65f9f619
MCC
1292 return 0;
1293}
1294
1295static int vidioc_g_frequency(struct file *file, void *priv,
1296 struct v4l2_frequency *f)
1297{
f4135b69 1298 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1299
1300 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1301 return -EINVAL;
1302 if (!go->i2c_adapter_online)
1303 return -EIO;
1304
1305 f->type = V4L2_TUNER_ANALOG_TV;
1306 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, f);
1307 return 0;
1308}
1309
1310static int vidioc_s_frequency(struct file *file, void *priv,
1311 struct v4l2_frequency *f)
1312{
f4135b69 1313 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1314
1315 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1316 return -EINVAL;
1317 if (!go->i2c_adapter_online)
1318 return -EIO;
1319
1320 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, f);
1321
1322 return 0;
1323}
1324
1325static int vidioc_cropcap(struct file *file, void *priv,
1326 struct v4l2_cropcap *cropcap)
1327{
f4135b69 1328 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1329
1330 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1331 return -EINVAL;
1332
1333 /* These specify the raw input of the sensor */
1334 switch (go->standard) {
1335 case GO7007_STD_NTSC:
1336 cropcap->bounds.top = 0;
1337 cropcap->bounds.left = 0;
1338 cropcap->bounds.width = 720;
1339 cropcap->bounds.height = 480;
1340 cropcap->defrect.top = 0;
1341 cropcap->defrect.left = 0;
1342 cropcap->defrect.width = 720;
1343 cropcap->defrect.height = 480;
1344 break;
1345 case GO7007_STD_PAL:
1346 cropcap->bounds.top = 0;
1347 cropcap->bounds.left = 0;
1348 cropcap->bounds.width = 720;
1349 cropcap->bounds.height = 576;
1350 cropcap->defrect.top = 0;
1351 cropcap->defrect.left = 0;
1352 cropcap->defrect.width = 720;
1353 cropcap->defrect.height = 576;
1354 break;
1355 case GO7007_STD_OTHER:
1356 cropcap->bounds.top = 0;
1357 cropcap->bounds.left = 0;
1358 cropcap->bounds.width = go->board_info->sensor_width;
1359 cropcap->bounds.height = go->board_info->sensor_height;
1360 cropcap->defrect.top = 0;
1361 cropcap->defrect.left = 0;
1362 cropcap->defrect.width = go->board_info->sensor_width;
1363 cropcap->defrect.height = go->board_info->sensor_height;
1364 break;
866b8695 1365 }
866b8695 1366
65f9f619
MCC
1367 return 0;
1368}
1369
1370static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
1371{
f4135b69 1372 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1373
1374 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1375 return -EINVAL;
1376
1377 crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1378
1379 /* These specify the raw input of the sensor */
1380 switch (go->standard) {
1381 case GO7007_STD_NTSC:
1382 crop->c.top = 0;
1383 crop->c.left = 0;
1384 crop->c.width = 720;
1385 crop->c.height = 480;
1386 break;
1387 case GO7007_STD_PAL:
1388 crop->c.top = 0;
1389 crop->c.left = 0;
1390 crop->c.width = 720;
1391 crop->c.height = 576;
1392 break;
1393 case GO7007_STD_OTHER:
1394 crop->c.top = 0;
1395 crop->c.left = 0;
1396 crop->c.width = go->board_info->sensor_width;
1397 crop->c.height = go->board_info->sensor_height;
1398 break;
866b8695 1399 }
65f9f619
MCC
1400
1401 return 0;
1402}
1403
1404/* FIXME: vidioc_s_crop is not really implemented!!!
1405 */
1406static int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
1407{
1408 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1409 return -EINVAL;
1410
1411 return 0;
1412}
1413
1414static int vidioc_g_jpegcomp(struct file *file, void *priv,
1415 struct v4l2_jpegcompression *params)
1416{
1417 memset(params, 0, sizeof(*params));
1418 params->quality = 50; /* ?? */
1419 params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
1420 V4L2_JPEG_MARKER_DQT;
1421
1422 return 0;
1423}
1424
1425static int vidioc_s_jpegcomp(struct file *file, void *priv,
1426 struct v4l2_jpegcompression *params)
1427{
1428 if (params->quality != 50 ||
1429 params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
1430 V4L2_JPEG_MARKER_DQT))
1431 return -EINVAL;
1432
1433 return 0;
1434}
1435
1436/* FIXME:
1437 Those ioctls are private, and not needed, since several standard
1438 extended controls already provide streaming control.
1439 So, those ioctls should be converted into vidioc_g_ext_ctrls()
1440 and vidioc_s_ext_ctrls()
1441 */
1442
1443#if 0
866b8695
GKH
1444 /* Temporary ioctls for controlling compression characteristics */
1445 case GO7007IOC_S_BITRATE:
1446 {
1447 int *bitrate = arg;
1448
1449 if (go->streaming)
1450 return -EINVAL;
1451 /* Upper bound is kind of arbitrary here */
1452 if (*bitrate < 64000 || *bitrate > 10000000)
1453 return -EINVAL;
1454 go->bitrate = *bitrate;
1455 return 0;
1456 }
1457 case GO7007IOC_G_BITRATE:
1458 {
1459 int *bitrate = arg;
1460
1461 *bitrate = go->bitrate;
1462 return 0;
1463 }
1464 case GO7007IOC_S_COMP_PARAMS:
1465 {
1466 struct go7007_comp_params *comp = arg;
1467
1468 if (go->format == GO7007_FORMAT_MJPEG)
1469 return -EINVAL;
1470 if (comp->gop_size > 0)
1471 go->gop_size = comp->gop_size;
1472 else
1473 go->gop_size = go->sensor_framerate / 1000;
1474 if (go->gop_size != 15)
1475 go->dvd_mode = 0;
1476 /*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */
1477 if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
1478 switch (comp->aspect_ratio) {
1479 case GO7007_ASPECT_RATIO_4_3_NTSC:
1480 case GO7007_ASPECT_RATIO_4_3_PAL:
1481 go->aspect_ratio = GO7007_RATIO_4_3;
1482 break;
1483 case GO7007_ASPECT_RATIO_16_9_NTSC:
1484 case GO7007_ASPECT_RATIO_16_9_PAL:
1485 go->aspect_ratio = GO7007_RATIO_16_9;
1486 break;
1487 default:
1488 go->aspect_ratio = GO7007_RATIO_1_1;
1489 break;
1490 }
1491 }
1492 if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) {
1493 go->dvd_mode = 0;
1494 go->seq_header_enable = 0;
1495 } else {
1496 go->seq_header_enable = 1;
1497 }
1498 /* fall-through */
1499 }
1500 case GO7007IOC_G_COMP_PARAMS:
1501 {
1502 struct go7007_comp_params *comp = arg;
1503
1504 if (go->format == GO7007_FORMAT_MJPEG)
1505 return -EINVAL;
1506 memset(comp, 0, sizeof(*comp));
1507 comp->gop_size = go->gop_size;
1508 comp->max_b_frames = go->ipb ? 2 : 0;
1509 switch (go->aspect_ratio) {
1510 case GO7007_RATIO_4_3:
1511 if (go->standard == GO7007_STD_NTSC)
1512 comp->aspect_ratio =
1513 GO7007_ASPECT_RATIO_4_3_NTSC;
1514 else
1515 comp->aspect_ratio =
1516 GO7007_ASPECT_RATIO_4_3_PAL;
1517 break;
1518 case GO7007_RATIO_16_9:
1519 if (go->standard == GO7007_STD_NTSC)
1520 comp->aspect_ratio =
1521 GO7007_ASPECT_RATIO_16_9_NTSC;
1522 else
1523 comp->aspect_ratio =
1524 GO7007_ASPECT_RATIO_16_9_PAL;
1525 break;
1526 default:
1527 comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1;
1528 break;
1529 }
1530 if (go->closed_gop)
1531 comp->flags |= GO7007_COMP_CLOSED_GOP;
1532 if (!go->seq_header_enable)
1533 comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER;
1534 return 0;
1535 }
1536 case GO7007IOC_S_MPEG_PARAMS:
1537 {
1538 struct go7007_mpeg_params *mpeg = arg;
1539
1540 if (go->format != GO7007_FORMAT_MPEG1 &&
1541 go->format != GO7007_FORMAT_MPEG2 &&
1542 go->format != GO7007_FORMAT_MPEG4)
1543 return -EINVAL;
1544
1545 if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) {
1546 go->format = GO7007_FORMAT_MPEG2;
1547 go->bitrate = 9800000;
1548 go->gop_size = 15;
1549 go->pali = 0x48;
1550 go->closed_gop = 1;
1551 go->repeat_seqhead = 0;
1552 go->seq_header_enable = 1;
1553 go->gop_header_enable = 1;
1554 go->dvd_mode = 1;
1555 } else {
1556 switch (mpeg->mpeg_video_standard) {
1557 case GO7007_MPEG_VIDEO_MPEG1:
1558 go->format = GO7007_FORMAT_MPEG1;
1559 go->pali = 0;
1560 break;
1561 case GO7007_MPEG_VIDEO_MPEG2:
1562 go->format = GO7007_FORMAT_MPEG2;
1563 if (mpeg->pali >> 24 == 2)
1564 go->pali = mpeg->pali & 0xff;
1565 else
1566 go->pali = 0x48;
1567 break;
1568 case GO7007_MPEG_VIDEO_MPEG4:
1569 go->format = GO7007_FORMAT_MPEG4;
1570 if (mpeg->pali >> 24 == 4)
1571 go->pali = mpeg->pali & 0xff;
1572 else
1573 go->pali = 0xf5;
1574 break;
1575 default:
1576 return -EINVAL;
1577 }
1578 go->gop_header_enable =
1579 mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
1580 ? 0 : 1;
1581 if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
1582 go->repeat_seqhead = 1;
1583 else
1584 go->repeat_seqhead = 0;
1585 go->dvd_mode = 0;
1586 }
1587 /* fall-through */
1588 }
1589 case GO7007IOC_G_MPEG_PARAMS:
1590 {
1591 struct go7007_mpeg_params *mpeg = arg;
1592
1593 memset(mpeg, 0, sizeof(*mpeg));
1594 switch (go->format) {
1595 case GO7007_FORMAT_MPEG1:
1596 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1;
1597 mpeg->pali = 0;
1598 break;
1599 case GO7007_FORMAT_MPEG2:
1600 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2;
1601 mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali);
1602 break;
1603 case GO7007_FORMAT_MPEG4:
1604 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4;
1605 mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali);
1606 break;
1607 default:
1608 return -EINVAL;
1609 }
1610 if (!go->gop_header_enable)
1611 mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER;
1612 if (go->repeat_seqhead)
1613 mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER;
1614 if (go->dvd_mode)
1615 mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE;
1616 return 0;
1617 }
1618 case GO7007IOC_S_MD_PARAMS:
1619 {
1620 struct go7007_md_params *mdp = arg;
1621
1622 if (mdp->region > 3)
1623 return -EINVAL;
1624 if (mdp->trigger > 0) {
1625 go->modet[mdp->region].pixel_threshold =
1626 mdp->pixel_threshold >> 1;
1627 go->modet[mdp->region].motion_threshold =
1628 mdp->motion_threshold >> 1;
1629 go->modet[mdp->region].mb_threshold =
1630 mdp->trigger >> 1;
1631 go->modet[mdp->region].enable = 1;
1632 } else
1633 go->modet[mdp->region].enable = 0;
1634 /* fall-through */
1635 }
1636 case GO7007IOC_G_MD_PARAMS:
1637 {
1638 struct go7007_md_params *mdp = arg;
1639 int region = mdp->region;
1640
1641 if (mdp->region > 3)
1642 return -EINVAL;
1643 memset(mdp, 0, sizeof(struct go7007_md_params));
1644 mdp->region = region;
1645 if (!go->modet[region].enable)
1646 return 0;
1647 mdp->pixel_threshold =
1648 (go->modet[region].pixel_threshold << 1) + 1;
1649 mdp->motion_threshold =
1650 (go->modet[region].motion_threshold << 1) + 1;
1651 mdp->trigger =
1652 (go->modet[region].mb_threshold << 1) + 1;
1653 return 0;
1654 }
1655 case GO7007IOC_S_MD_REGION:
1656 {
1657 struct go7007_md_region *region = arg;
1658
1659 if (region->region < 1 || region->region > 3)
1660 return -EINVAL;
1661 return clip_to_modet_map(go, region->region, region->clips);
1662 }
65f9f619 1663#endif
866b8695
GKH
1664
1665static ssize_t go7007_read(struct file *file, char __user *data,
1666 size_t count, loff_t *ppos)
1667{
1668 return -EINVAL;
1669}
1670
1671static void go7007_vm_open(struct vm_area_struct *vma)
1672{
1673 struct go7007_buffer *gobuf = vma->vm_private_data;
1674
1675 ++gobuf->mapped;
1676}
1677
1678static void go7007_vm_close(struct vm_area_struct *vma)
1679{
1680 struct go7007_buffer *gobuf = vma->vm_private_data;
1681 unsigned long flags;
1682
1683 if (--gobuf->mapped == 0) {
1684 spin_lock_irqsave(&gobuf->go->spinlock, flags);
1685 deactivate_buffer(gobuf);
1686 spin_unlock_irqrestore(&gobuf->go->spinlock, flags);
1687 }
1688}
1689
1690/* Copied from videobuf-dma-sg.c */
1691static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1692{
1693 struct page *page;
1694
1695 page = alloc_page(GFP_USER | __GFP_DMA32);
1696 if (!page)
1697 return VM_FAULT_OOM;
c0cd5010 1698 clear_user_highpage(page, (unsigned long)vmf->virtual_address);
866b8695
GKH
1699 vmf->page = page;
1700 return 0;
1701}
1702
1703static struct vm_operations_struct go7007_vm_ops = {
1704 .open = go7007_vm_open,
1705 .close = go7007_vm_close,
1706 .fault = go7007_vm_fault,
1707};
1708
1709static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
1710{
1711 struct go7007_file *gofh = file->private_data;
1712 unsigned int index;
1713
1714 if (gofh->go->status != STATUS_ONLINE)
1715 return -EIO;
1716 if (!(vma->vm_flags & VM_SHARED))
1717 return -EINVAL; /* only support VM_SHARED mapping */
1718 if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE)
1719 return -EINVAL; /* must map exactly one full buffer */
fd9a40da 1720 mutex_lock(&gofh->lock);
866b8695
GKH
1721 index = vma->vm_pgoff / GO7007_BUF_PAGES;
1722 if (index >= gofh->buf_count) {
fd9a40da 1723 mutex_unlock(&gofh->lock);
866b8695
GKH
1724 return -EINVAL; /* trying to map beyond requested buffers */
1725 }
1726 if (index * GO7007_BUF_PAGES != vma->vm_pgoff) {
fd9a40da 1727 mutex_unlock(&gofh->lock);
866b8695
GKH
1728 return -EINVAL; /* offset is not aligned on buffer boundary */
1729 }
1730 if (gofh->bufs[index].mapped > 0) {
fd9a40da 1731 mutex_unlock(&gofh->lock);
866b8695
GKH
1732 return -EBUSY;
1733 }
1734 gofh->bufs[index].mapped = 1;
1735 gofh->bufs[index].user_addr = vma->vm_start;
1736 vma->vm_ops = &go7007_vm_ops;
1737 vma->vm_flags |= VM_DONTEXPAND;
1738 vma->vm_flags &= ~VM_IO;
1739 vma->vm_private_data = &gofh->bufs[index];
fd9a40da 1740 mutex_unlock(&gofh->lock);
866b8695
GKH
1741 return 0;
1742}
1743
1744static unsigned int go7007_poll(struct file *file, poll_table *wait)
1745{
1746 struct go7007_file *gofh = file->private_data;
1747 struct go7007_buffer *gobuf;
1748
1749 if (list_empty(&gofh->go->stream))
1750 return POLLERR;
1751 gobuf = list_entry(gofh->go->stream.next, struct go7007_buffer, stream);
1752 poll_wait(file, &gofh->go->frame_waitq, wait);
1753 if (gobuf->state == BUF_STATE_DONE)
1754 return POLLIN | POLLRDNORM;
1755 return 0;
1756}
1757
1758static void go7007_vfl_release(struct video_device *vfd)
1759{
1760 struct go7007 *go = video_get_drvdata(vfd);
1761
1762 video_device_release(vfd);
1763 if (--go->ref_count == 0)
1764 kfree(go);
1765}
1766
60572c0d 1767static struct v4l2_file_operations go7007_fops = {
866b8695
GKH
1768 .owner = THIS_MODULE,
1769 .open = go7007_open,
1770 .release = go7007_release,
65f9f619 1771 .ioctl = video_ioctl2,
866b8695
GKH
1772 .read = go7007_read,
1773 .mmap = go7007_mmap,
1774 .poll = go7007_poll,
1775};
1776
65f9f619
MCC
1777static const struct v4l2_ioctl_ops video_ioctl_ops = {
1778 .vidioc_querycap = vidioc_querycap,
1779 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1780 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1781 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1782 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1783 .vidioc_reqbufs = vidioc_reqbufs,
1784 .vidioc_querybuf = vidioc_querybuf,
1785 .vidioc_qbuf = vidioc_qbuf,
1786 .vidioc_dqbuf = vidioc_dqbuf,
bb871652 1787 .vidioc_g_std = vidioc_g_std,
65f9f619 1788 .vidioc_s_std = vidioc_s_std,
bb871652 1789 .vidioc_querystd = vidioc_querystd,
65f9f619
MCC
1790 .vidioc_enum_input = vidioc_enum_input,
1791 .vidioc_g_input = vidioc_g_input,
1792 .vidioc_s_input = vidioc_s_input,
1793 .vidioc_queryctrl = vidioc_queryctrl,
1794 .vidioc_g_ctrl = vidioc_g_ctrl,
1795 .vidioc_s_ctrl = vidioc_s_ctrl,
1796 .vidioc_streamon = vidioc_streamon,
1797 .vidioc_streamoff = vidioc_streamoff,
1798 .vidioc_g_tuner = vidioc_g_tuner,
1799 .vidioc_s_tuner = vidioc_s_tuner,
1800 .vidioc_g_frequency = vidioc_g_frequency,
1801 .vidioc_s_frequency = vidioc_s_frequency,
1802 .vidioc_g_parm = vidioc_g_parm,
1803 .vidioc_s_parm = vidioc_s_parm,
65f9f619
MCC
1804 .vidioc_enum_framesizes = vidioc_enum_framesizes,
1805 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
65f9f619
MCC
1806 .vidioc_cropcap = vidioc_cropcap,
1807 .vidioc_g_crop = vidioc_g_crop,
1808 .vidioc_s_crop = vidioc_s_crop,
1809 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1810 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1811};
1812
866b8695
GKH
1813static struct video_device go7007_template = {
1814 .name = "go7007",
1815 .fops = &go7007_fops,
1816 .minor = -1,
1817 .release = go7007_vfl_release,
65f9f619
MCC
1818 .ioctl_ops = &video_ioctl_ops,
1819 .tvnorms = V4L2_STD_ALL,
1820 .current_norm = V4L2_STD_NTSC,
866b8695
GKH
1821};
1822
1823int go7007_v4l2_init(struct go7007 *go)
1824{
1825 int rv;
1826
1827 go->video_dev = video_device_alloc();
1828 if (go->video_dev == NULL)
1829 return -ENOMEM;
1830 memcpy(go->video_dev, &go7007_template, sizeof(go7007_template));
1831 go->video_dev->parent = go->dev;
1832 rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1);
1833 if (rv < 0) {
1834 video_device_release(go->video_dev);
1835 go->video_dev = NULL;
1836 return rv;
1837 }
1838 video_set_drvdata(go->video_dev, go);
1839 ++go->ref_count;
d73f822c
PE
1840 printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
1841 go->video_dev->name, go->video_dev->num);
866b8695
GKH
1842
1843 return 0;
1844}
1845
1846void go7007_v4l2_remove(struct go7007 *go)
1847{
1848 unsigned long flags;
1849
fd9a40da 1850 mutex_lock(&go->hw_lock);
866b8695
GKH
1851 if (go->streaming) {
1852 go->streaming = 0;
1853 go7007_stream_stop(go);
1854 spin_lock_irqsave(&go->spinlock, flags);
1855 abort_queued(go);
1856 spin_unlock_irqrestore(&go->spinlock, flags);
1857 }
fd9a40da 1858 mutex_unlock(&go->hw_lock);
866b8695
GKH
1859 if (go->video_dev)
1860 video_unregister_device(go->video_dev);
1861}
This page took 0.332773 seconds and 5 git commands to generate.