]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/go7007/go7007-v4l2.c
V4L/DVB (13023): go7007: Merge struct gofh and go declarations
[net-next-2.6.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
1113static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
1114{
f4135b69 1115 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1116
1117 if (go->streaming)
1118 return -EBUSY;
1119
1120 if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
1121 *std != 0)
1122 return -EINVAL;
1123
1124 if (*std == 0)
1125 return -EINVAL;
1126
1127 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1128 go->input == go->board_info->num_inputs - 1) {
1129 if (!go->i2c_adapter_online)
1130 return -EIO;
1131 i2c_clients_command(&go->i2c_adapter,
1132 VIDIOC_S_STD, std);
1133 if (!*std) /* hack to indicate EINVAL from tuner */
866b8695 1134 return -EINVAL;
866b8695 1135 }
866b8695 1136
65f9f619
MCC
1137 if (*std & V4L2_STD_NTSC) {
1138 go->standard = GO7007_STD_NTSC;
1139 go->sensor_framerate = 30000;
1140 } else if (*std & V4L2_STD_PAL) {
1141 go->standard = GO7007_STD_PAL;
1142 go->sensor_framerate = 25025;
1143 } else if (*std & V4L2_STD_SECAM) {
1144 go->standard = GO7007_STD_PAL;
1145 go->sensor_framerate = 25025;
1146 } else
1147 return -EINVAL;
866b8695 1148
65f9f619
MCC
1149 if (go->i2c_adapter_online)
1150 i2c_clients_command(&go->i2c_adapter,
1151 VIDIOC_S_STD, std);
1152 set_capture_size(go, NULL, 0);
866b8695 1153
65f9f619
MCC
1154 return 0;
1155}
d73f822c 1156
65f9f619 1157#if 0
866b8695
GKH
1158 case VIDIOC_QUERYSTD:
1159 {
1160 v4l2_std_id *std = arg;
1161
1162 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1163 go->input == go->board_info->num_inputs - 1) {
1164 if (!go->i2c_adapter_online)
1165 return -EIO;
1166 i2c_clients_command(&go->i2c_adapter,
1167 VIDIOC_QUERYSTD, arg);
1168 } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1169 *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
1170 else
1171 *std = 0;
1172 return 0;
1173 }
65f9f619 1174#endif
866b8695 1175
65f9f619
MCC
1176static int vidioc_enum_input(struct file *file, void *priv,
1177 struct v4l2_input *inp)
1178{
f4135b69 1179 struct go7007 *go = ((struct go7007_file *) priv)->go;
866b8695 1180
65f9f619
MCC
1181 if (inp->index >= go->board_info->num_inputs)
1182 return -EINVAL;
866b8695 1183
65f9f619
MCC
1184 strncpy(inp->name, go->board_info->inputs[inp->index].name,
1185 sizeof(inp->name));
866b8695 1186
65f9f619
MCC
1187 /* If this board has a tuner, it will be the last input */
1188 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1189 inp->index == go->board_info->num_inputs - 1)
1190 inp->type = V4L2_INPUT_TYPE_TUNER;
1191 else
1192 inp->type = V4L2_INPUT_TYPE_CAMERA;
866b8695 1193
65f9f619
MCC
1194 inp->audioset = 0;
1195 inp->tuner = 0;
1196 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1197 inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
1198 V4L2_STD_SECAM;
1199 else
1200 inp->std = 0;
866b8695 1201
65f9f619
MCC
1202 return 0;
1203}
866b8695 1204
866b8695 1205
65f9f619
MCC
1206static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
1207{
f4135b69 1208 struct go7007 *go = ((struct go7007_file *) priv)->go;
866b8695 1209
65f9f619 1210 *input = go->input;
866b8695 1211
65f9f619
MCC
1212 return 0;
1213}
1214
1215static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
1216{
f4135b69 1217 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1218
1219 if (input >= go->board_info->num_inputs)
1220 return -EINVAL;
1221 if (go->streaming)
1222 return -EBUSY;
1223
1224 go->input = input;
1225 if (go->i2c_adapter_online) {
1226 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT,
1227 &go->board_info->inputs[input].video_input);
1228 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO,
1229 &go->board_info->inputs[input].audio_input);
866b8695 1230 }
866b8695 1231
65f9f619
MCC
1232 return 0;
1233}
1234
1235static int vidioc_g_tuner(struct file *file, void *priv,
1236 struct v4l2_tuner *t)
1237{
f4135b69 1238 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1239
1240 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1241 return -EINVAL;
1242 if (t->index != 0)
1243 return -EINVAL;
1244 if (!go->i2c_adapter_online)
1245 return -EIO;
1246
1247 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, t);
1248
1249 t->index = 0;
1250 return 0;
1251}
1252
1253static int vidioc_s_tuner(struct file *file, void *priv,
1254 struct v4l2_tuner *t)
1255{
f4135b69 1256 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1257
1258 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1259 return -EINVAL;
1260 if (t->index != 0)
1261 return -EINVAL;
1262 if (!go->i2c_adapter_online)
1263 return -EIO;
1264
1265 switch (go->board_id) {
1266 case GO7007_BOARDID_PX_TV402U_NA:
1267 case GO7007_BOARDID_PX_TV402U_JP:
1268 /* No selectable options currently */
1269 if (t->audmode != V4L2_TUNER_MODE_STEREO)
866b8695 1270 return -EINVAL;
65f9f619 1271 break;
866b8695 1272 }
866b8695 1273
65f9f619 1274 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, t);
866b8695 1275
65f9f619
MCC
1276 return 0;
1277}
1278
1279static int vidioc_g_frequency(struct file *file, void *priv,
1280 struct v4l2_frequency *f)
1281{
f4135b69 1282 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1283
1284 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1285 return -EINVAL;
1286 if (!go->i2c_adapter_online)
1287 return -EIO;
1288
1289 f->type = V4L2_TUNER_ANALOG_TV;
1290 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, f);
1291 return 0;
1292}
1293
1294static int vidioc_s_frequency(struct file *file, void *priv,
1295 struct v4l2_frequency *f)
1296{
f4135b69 1297 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1298
1299 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1300 return -EINVAL;
1301 if (!go->i2c_adapter_online)
1302 return -EIO;
1303
1304 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, f);
1305
1306 return 0;
1307}
1308
1309static int vidioc_cropcap(struct file *file, void *priv,
1310 struct v4l2_cropcap *cropcap)
1311{
f4135b69 1312 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1313
1314 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1315 return -EINVAL;
1316
1317 /* These specify the raw input of the sensor */
1318 switch (go->standard) {
1319 case GO7007_STD_NTSC:
1320 cropcap->bounds.top = 0;
1321 cropcap->bounds.left = 0;
1322 cropcap->bounds.width = 720;
1323 cropcap->bounds.height = 480;
1324 cropcap->defrect.top = 0;
1325 cropcap->defrect.left = 0;
1326 cropcap->defrect.width = 720;
1327 cropcap->defrect.height = 480;
1328 break;
1329 case GO7007_STD_PAL:
1330 cropcap->bounds.top = 0;
1331 cropcap->bounds.left = 0;
1332 cropcap->bounds.width = 720;
1333 cropcap->bounds.height = 576;
1334 cropcap->defrect.top = 0;
1335 cropcap->defrect.left = 0;
1336 cropcap->defrect.width = 720;
1337 cropcap->defrect.height = 576;
1338 break;
1339 case GO7007_STD_OTHER:
1340 cropcap->bounds.top = 0;
1341 cropcap->bounds.left = 0;
1342 cropcap->bounds.width = go->board_info->sensor_width;
1343 cropcap->bounds.height = go->board_info->sensor_height;
1344 cropcap->defrect.top = 0;
1345 cropcap->defrect.left = 0;
1346 cropcap->defrect.width = go->board_info->sensor_width;
1347 cropcap->defrect.height = go->board_info->sensor_height;
1348 break;
866b8695 1349 }
866b8695 1350
65f9f619
MCC
1351 return 0;
1352}
1353
1354static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
1355{
f4135b69 1356 struct go7007 *go = ((struct go7007_file *) priv)->go;
65f9f619
MCC
1357
1358 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1359 return -EINVAL;
1360
1361 crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1362
1363 /* These specify the raw input of the sensor */
1364 switch (go->standard) {
1365 case GO7007_STD_NTSC:
1366 crop->c.top = 0;
1367 crop->c.left = 0;
1368 crop->c.width = 720;
1369 crop->c.height = 480;
1370 break;
1371 case GO7007_STD_PAL:
1372 crop->c.top = 0;
1373 crop->c.left = 0;
1374 crop->c.width = 720;
1375 crop->c.height = 576;
1376 break;
1377 case GO7007_STD_OTHER:
1378 crop->c.top = 0;
1379 crop->c.left = 0;
1380 crop->c.width = go->board_info->sensor_width;
1381 crop->c.height = go->board_info->sensor_height;
1382 break;
866b8695 1383 }
65f9f619
MCC
1384
1385 return 0;
1386}
1387
1388/* FIXME: vidioc_s_crop is not really implemented!!!
1389 */
1390static int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
1391{
1392 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1393 return -EINVAL;
1394
1395 return 0;
1396}
1397
1398static int vidioc_g_jpegcomp(struct file *file, void *priv,
1399 struct v4l2_jpegcompression *params)
1400{
1401 memset(params, 0, sizeof(*params));
1402 params->quality = 50; /* ?? */
1403 params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
1404 V4L2_JPEG_MARKER_DQT;
1405
1406 return 0;
1407}
1408
1409static int vidioc_s_jpegcomp(struct file *file, void *priv,
1410 struct v4l2_jpegcompression *params)
1411{
1412 if (params->quality != 50 ||
1413 params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
1414 V4L2_JPEG_MARKER_DQT))
1415 return -EINVAL;
1416
1417 return 0;
1418}
1419
1420/* FIXME:
1421 Those ioctls are private, and not needed, since several standard
1422 extended controls already provide streaming control.
1423 So, those ioctls should be converted into vidioc_g_ext_ctrls()
1424 and vidioc_s_ext_ctrls()
1425 */
1426
1427#if 0
866b8695
GKH
1428 /* Temporary ioctls for controlling compression characteristics */
1429 case GO7007IOC_S_BITRATE:
1430 {
1431 int *bitrate = arg;
1432
1433 if (go->streaming)
1434 return -EINVAL;
1435 /* Upper bound is kind of arbitrary here */
1436 if (*bitrate < 64000 || *bitrate > 10000000)
1437 return -EINVAL;
1438 go->bitrate = *bitrate;
1439 return 0;
1440 }
1441 case GO7007IOC_G_BITRATE:
1442 {
1443 int *bitrate = arg;
1444
1445 *bitrate = go->bitrate;
1446 return 0;
1447 }
1448 case GO7007IOC_S_COMP_PARAMS:
1449 {
1450 struct go7007_comp_params *comp = arg;
1451
1452 if (go->format == GO7007_FORMAT_MJPEG)
1453 return -EINVAL;
1454 if (comp->gop_size > 0)
1455 go->gop_size = comp->gop_size;
1456 else
1457 go->gop_size = go->sensor_framerate / 1000;
1458 if (go->gop_size != 15)
1459 go->dvd_mode = 0;
1460 /*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */
1461 if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
1462 switch (comp->aspect_ratio) {
1463 case GO7007_ASPECT_RATIO_4_3_NTSC:
1464 case GO7007_ASPECT_RATIO_4_3_PAL:
1465 go->aspect_ratio = GO7007_RATIO_4_3;
1466 break;
1467 case GO7007_ASPECT_RATIO_16_9_NTSC:
1468 case GO7007_ASPECT_RATIO_16_9_PAL:
1469 go->aspect_ratio = GO7007_RATIO_16_9;
1470 break;
1471 default:
1472 go->aspect_ratio = GO7007_RATIO_1_1;
1473 break;
1474 }
1475 }
1476 if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) {
1477 go->dvd_mode = 0;
1478 go->seq_header_enable = 0;
1479 } else {
1480 go->seq_header_enable = 1;
1481 }
1482 /* fall-through */
1483 }
1484 case GO7007IOC_G_COMP_PARAMS:
1485 {
1486 struct go7007_comp_params *comp = arg;
1487
1488 if (go->format == GO7007_FORMAT_MJPEG)
1489 return -EINVAL;
1490 memset(comp, 0, sizeof(*comp));
1491 comp->gop_size = go->gop_size;
1492 comp->max_b_frames = go->ipb ? 2 : 0;
1493 switch (go->aspect_ratio) {
1494 case GO7007_RATIO_4_3:
1495 if (go->standard == GO7007_STD_NTSC)
1496 comp->aspect_ratio =
1497 GO7007_ASPECT_RATIO_4_3_NTSC;
1498 else
1499 comp->aspect_ratio =
1500 GO7007_ASPECT_RATIO_4_3_PAL;
1501 break;
1502 case GO7007_RATIO_16_9:
1503 if (go->standard == GO7007_STD_NTSC)
1504 comp->aspect_ratio =
1505 GO7007_ASPECT_RATIO_16_9_NTSC;
1506 else
1507 comp->aspect_ratio =
1508 GO7007_ASPECT_RATIO_16_9_PAL;
1509 break;
1510 default:
1511 comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1;
1512 break;
1513 }
1514 if (go->closed_gop)
1515 comp->flags |= GO7007_COMP_CLOSED_GOP;
1516 if (!go->seq_header_enable)
1517 comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER;
1518 return 0;
1519 }
1520 case GO7007IOC_S_MPEG_PARAMS:
1521 {
1522 struct go7007_mpeg_params *mpeg = arg;
1523
1524 if (go->format != GO7007_FORMAT_MPEG1 &&
1525 go->format != GO7007_FORMAT_MPEG2 &&
1526 go->format != GO7007_FORMAT_MPEG4)
1527 return -EINVAL;
1528
1529 if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) {
1530 go->format = GO7007_FORMAT_MPEG2;
1531 go->bitrate = 9800000;
1532 go->gop_size = 15;
1533 go->pali = 0x48;
1534 go->closed_gop = 1;
1535 go->repeat_seqhead = 0;
1536 go->seq_header_enable = 1;
1537 go->gop_header_enable = 1;
1538 go->dvd_mode = 1;
1539 } else {
1540 switch (mpeg->mpeg_video_standard) {
1541 case GO7007_MPEG_VIDEO_MPEG1:
1542 go->format = GO7007_FORMAT_MPEG1;
1543 go->pali = 0;
1544 break;
1545 case GO7007_MPEG_VIDEO_MPEG2:
1546 go->format = GO7007_FORMAT_MPEG2;
1547 if (mpeg->pali >> 24 == 2)
1548 go->pali = mpeg->pali & 0xff;
1549 else
1550 go->pali = 0x48;
1551 break;
1552 case GO7007_MPEG_VIDEO_MPEG4:
1553 go->format = GO7007_FORMAT_MPEG4;
1554 if (mpeg->pali >> 24 == 4)
1555 go->pali = mpeg->pali & 0xff;
1556 else
1557 go->pali = 0xf5;
1558 break;
1559 default:
1560 return -EINVAL;
1561 }
1562 go->gop_header_enable =
1563 mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
1564 ? 0 : 1;
1565 if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
1566 go->repeat_seqhead = 1;
1567 else
1568 go->repeat_seqhead = 0;
1569 go->dvd_mode = 0;
1570 }
1571 /* fall-through */
1572 }
1573 case GO7007IOC_G_MPEG_PARAMS:
1574 {
1575 struct go7007_mpeg_params *mpeg = arg;
1576
1577 memset(mpeg, 0, sizeof(*mpeg));
1578 switch (go->format) {
1579 case GO7007_FORMAT_MPEG1:
1580 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1;
1581 mpeg->pali = 0;
1582 break;
1583 case GO7007_FORMAT_MPEG2:
1584 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2;
1585 mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali);
1586 break;
1587 case GO7007_FORMAT_MPEG4:
1588 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4;
1589 mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali);
1590 break;
1591 default:
1592 return -EINVAL;
1593 }
1594 if (!go->gop_header_enable)
1595 mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER;
1596 if (go->repeat_seqhead)
1597 mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER;
1598 if (go->dvd_mode)
1599 mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE;
1600 return 0;
1601 }
1602 case GO7007IOC_S_MD_PARAMS:
1603 {
1604 struct go7007_md_params *mdp = arg;
1605
1606 if (mdp->region > 3)
1607 return -EINVAL;
1608 if (mdp->trigger > 0) {
1609 go->modet[mdp->region].pixel_threshold =
1610 mdp->pixel_threshold >> 1;
1611 go->modet[mdp->region].motion_threshold =
1612 mdp->motion_threshold >> 1;
1613 go->modet[mdp->region].mb_threshold =
1614 mdp->trigger >> 1;
1615 go->modet[mdp->region].enable = 1;
1616 } else
1617 go->modet[mdp->region].enable = 0;
1618 /* fall-through */
1619 }
1620 case GO7007IOC_G_MD_PARAMS:
1621 {
1622 struct go7007_md_params *mdp = arg;
1623 int region = mdp->region;
1624
1625 if (mdp->region > 3)
1626 return -EINVAL;
1627 memset(mdp, 0, sizeof(struct go7007_md_params));
1628 mdp->region = region;
1629 if (!go->modet[region].enable)
1630 return 0;
1631 mdp->pixel_threshold =
1632 (go->modet[region].pixel_threshold << 1) + 1;
1633 mdp->motion_threshold =
1634 (go->modet[region].motion_threshold << 1) + 1;
1635 mdp->trigger =
1636 (go->modet[region].mb_threshold << 1) + 1;
1637 return 0;
1638 }
1639 case GO7007IOC_S_MD_REGION:
1640 {
1641 struct go7007_md_region *region = arg;
1642
1643 if (region->region < 1 || region->region > 3)
1644 return -EINVAL;
1645 return clip_to_modet_map(go, region->region, region->clips);
1646 }
65f9f619 1647#endif
866b8695
GKH
1648
1649static ssize_t go7007_read(struct file *file, char __user *data,
1650 size_t count, loff_t *ppos)
1651{
1652 return -EINVAL;
1653}
1654
1655static void go7007_vm_open(struct vm_area_struct *vma)
1656{
1657 struct go7007_buffer *gobuf = vma->vm_private_data;
1658
1659 ++gobuf->mapped;
1660}
1661
1662static void go7007_vm_close(struct vm_area_struct *vma)
1663{
1664 struct go7007_buffer *gobuf = vma->vm_private_data;
1665 unsigned long flags;
1666
1667 if (--gobuf->mapped == 0) {
1668 spin_lock_irqsave(&gobuf->go->spinlock, flags);
1669 deactivate_buffer(gobuf);
1670 spin_unlock_irqrestore(&gobuf->go->spinlock, flags);
1671 }
1672}
1673
1674/* Copied from videobuf-dma-sg.c */
1675static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1676{
1677 struct page *page;
1678
1679 page = alloc_page(GFP_USER | __GFP_DMA32);
1680 if (!page)
1681 return VM_FAULT_OOM;
c0cd5010 1682 clear_user_highpage(page, (unsigned long)vmf->virtual_address);
866b8695
GKH
1683 vmf->page = page;
1684 return 0;
1685}
1686
1687static struct vm_operations_struct go7007_vm_ops = {
1688 .open = go7007_vm_open,
1689 .close = go7007_vm_close,
1690 .fault = go7007_vm_fault,
1691};
1692
1693static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
1694{
1695 struct go7007_file *gofh = file->private_data;
1696 unsigned int index;
1697
1698 if (gofh->go->status != STATUS_ONLINE)
1699 return -EIO;
1700 if (!(vma->vm_flags & VM_SHARED))
1701 return -EINVAL; /* only support VM_SHARED mapping */
1702 if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE)
1703 return -EINVAL; /* must map exactly one full buffer */
fd9a40da 1704 mutex_lock(&gofh->lock);
866b8695
GKH
1705 index = vma->vm_pgoff / GO7007_BUF_PAGES;
1706 if (index >= gofh->buf_count) {
fd9a40da 1707 mutex_unlock(&gofh->lock);
866b8695
GKH
1708 return -EINVAL; /* trying to map beyond requested buffers */
1709 }
1710 if (index * GO7007_BUF_PAGES != vma->vm_pgoff) {
fd9a40da 1711 mutex_unlock(&gofh->lock);
866b8695
GKH
1712 return -EINVAL; /* offset is not aligned on buffer boundary */
1713 }
1714 if (gofh->bufs[index].mapped > 0) {
fd9a40da 1715 mutex_unlock(&gofh->lock);
866b8695
GKH
1716 return -EBUSY;
1717 }
1718 gofh->bufs[index].mapped = 1;
1719 gofh->bufs[index].user_addr = vma->vm_start;
1720 vma->vm_ops = &go7007_vm_ops;
1721 vma->vm_flags |= VM_DONTEXPAND;
1722 vma->vm_flags &= ~VM_IO;
1723 vma->vm_private_data = &gofh->bufs[index];
fd9a40da 1724 mutex_unlock(&gofh->lock);
866b8695
GKH
1725 return 0;
1726}
1727
1728static unsigned int go7007_poll(struct file *file, poll_table *wait)
1729{
1730 struct go7007_file *gofh = file->private_data;
1731 struct go7007_buffer *gobuf;
1732
1733 if (list_empty(&gofh->go->stream))
1734 return POLLERR;
1735 gobuf = list_entry(gofh->go->stream.next, struct go7007_buffer, stream);
1736 poll_wait(file, &gofh->go->frame_waitq, wait);
1737 if (gobuf->state == BUF_STATE_DONE)
1738 return POLLIN | POLLRDNORM;
1739 return 0;
1740}
1741
1742static void go7007_vfl_release(struct video_device *vfd)
1743{
1744 struct go7007 *go = video_get_drvdata(vfd);
1745
1746 video_device_release(vfd);
1747 if (--go->ref_count == 0)
1748 kfree(go);
1749}
1750
60572c0d 1751static struct v4l2_file_operations go7007_fops = {
866b8695
GKH
1752 .owner = THIS_MODULE,
1753 .open = go7007_open,
1754 .release = go7007_release,
65f9f619 1755 .ioctl = video_ioctl2,
866b8695
GKH
1756 .read = go7007_read,
1757 .mmap = go7007_mmap,
1758 .poll = go7007_poll,
1759};
1760
65f9f619
MCC
1761static const struct v4l2_ioctl_ops video_ioctl_ops = {
1762 .vidioc_querycap = vidioc_querycap,
1763 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1764 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1765 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1766 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1767 .vidioc_reqbufs = vidioc_reqbufs,
1768 .vidioc_querybuf = vidioc_querybuf,
1769 .vidioc_qbuf = vidioc_qbuf,
1770 .vidioc_dqbuf = vidioc_dqbuf,
1771 .vidioc_s_std = vidioc_s_std,
1772 .vidioc_enum_input = vidioc_enum_input,
1773 .vidioc_g_input = vidioc_g_input,
1774 .vidioc_s_input = vidioc_s_input,
1775 .vidioc_queryctrl = vidioc_queryctrl,
1776 .vidioc_g_ctrl = vidioc_g_ctrl,
1777 .vidioc_s_ctrl = vidioc_s_ctrl,
1778 .vidioc_streamon = vidioc_streamon,
1779 .vidioc_streamoff = vidioc_streamoff,
1780 .vidioc_g_tuner = vidioc_g_tuner,
1781 .vidioc_s_tuner = vidioc_s_tuner,
1782 .vidioc_g_frequency = vidioc_g_frequency,
1783 .vidioc_s_frequency = vidioc_s_frequency,
1784 .vidioc_g_parm = vidioc_g_parm,
1785 .vidioc_s_parm = vidioc_s_parm,
65f9f619
MCC
1786 .vidioc_enum_framesizes = vidioc_enum_framesizes,
1787 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
65f9f619
MCC
1788 .vidioc_cropcap = vidioc_cropcap,
1789 .vidioc_g_crop = vidioc_g_crop,
1790 .vidioc_s_crop = vidioc_s_crop,
1791 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1792 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1793};
1794
866b8695
GKH
1795static struct video_device go7007_template = {
1796 .name = "go7007",
1797 .fops = &go7007_fops,
1798 .minor = -1,
1799 .release = go7007_vfl_release,
65f9f619
MCC
1800 .ioctl_ops = &video_ioctl_ops,
1801 .tvnorms = V4L2_STD_ALL,
1802 .current_norm = V4L2_STD_NTSC,
866b8695
GKH
1803};
1804
1805int go7007_v4l2_init(struct go7007 *go)
1806{
1807 int rv;
1808
1809 go->video_dev = video_device_alloc();
1810 if (go->video_dev == NULL)
1811 return -ENOMEM;
1812 memcpy(go->video_dev, &go7007_template, sizeof(go7007_template));
1813 go->video_dev->parent = go->dev;
1814 rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1);
1815 if (rv < 0) {
1816 video_device_release(go->video_dev);
1817 go->video_dev = NULL;
1818 return rv;
1819 }
1820 video_set_drvdata(go->video_dev, go);
1821 ++go->ref_count;
d73f822c
PE
1822 printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
1823 go->video_dev->name, go->video_dev->num);
866b8695
GKH
1824
1825 return 0;
1826}
1827
1828void go7007_v4l2_remove(struct go7007 *go)
1829{
1830 unsigned long flags;
1831
fd9a40da 1832 mutex_lock(&go->hw_lock);
866b8695
GKH
1833 if (go->streaming) {
1834 go->streaming = 0;
1835 go7007_stream_stop(go);
1836 spin_lock_irqsave(&go->spinlock, flags);
1837 abort_queued(go);
1838 spin_unlock_irqrestore(&go->spinlock, flags);
1839 }
fd9a40da 1840 mutex_unlock(&go->hw_lock);
866b8695
GKH
1841 if (go->video_dev)
1842 video_unregister_device(go->video_dev);
1843}