blob: e0b17a0145c8f660ffeeef4bbe5e8a18591da239 [file] [log] [blame]
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001/*
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>
Ross Cohendf20d692008-09-29 22:36:24 -040029#include <linux/videodev2.h>
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -080030#include <media/v4l2-common.h>
31#include <media/v4l2-ioctl.h>
32#include <linux/i2c.h>
33#include <linux/semaphore.h>
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
Pete Eberleind73f8222008-10-30 12:56:33 -070041/* 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
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -080049static 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
78 down(&go->hw_lock);
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 }
88 up(&go->hw_lock);
89 return 0;
90}
91
Greg Kroah-Hartman60572c02009-01-05 10:21:08 -080092static int go7007_open(struct file *file)
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -080093{
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;
104 init_MUTEX(&gofh->lock);
105 gofh->buf_count = 0;
106 file->private_data = gofh;
107 return 0;
108}
109
Greg Kroah-Hartman60572c02009-01-05 10:21:08 -0800110static int go7007_release(struct file *file)
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800111{
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
330static int clip_to_modet_map(struct go7007 *go, int region,
331 struct v4l2_clip *clip_list)
332{
333 struct v4l2_clip clip, *clip_ptr;
334 int x, y, mbnum;
335
336 /* Check if coordinates are OK and if any macroblocks are already
337 * used by other regions (besides 0) */
338 clip_ptr = clip_list;
339 while (clip_ptr) {
340 if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
341 return -EFAULT;
342 if (clip.c.left < 0 || (clip.c.left & 0xF) ||
343 clip.c.width <= 0 || (clip.c.width & 0xF))
344 return -EINVAL;
345 if (clip.c.left + clip.c.width > go->width)
346 return -EINVAL;
347 if (clip.c.top < 0 || (clip.c.top & 0xF) ||
348 clip.c.height <= 0 || (clip.c.height & 0xF))
349 return -EINVAL;
350 if (clip.c.top + clip.c.height > go->height)
351 return -EINVAL;
352 for (y = 0; y < clip.c.height; y += 16)
353 for (x = 0; x < clip.c.width; x += 16) {
354 mbnum = (go->width >> 4) *
355 ((clip.c.top + y) >> 4) +
356 ((clip.c.left + x) >> 4);
357 if (go->modet_map[mbnum] != 0 &&
358 go->modet_map[mbnum] != region)
359 return -EBUSY;
360 }
361 clip_ptr = clip.next;
362 }
363
364 /* Clear old region macroblocks */
365 for (mbnum = 0; mbnum < 1624; ++mbnum)
366 if (go->modet_map[mbnum] == region)
367 go->modet_map[mbnum] = 0;
368
369 /* Claim macroblocks in this list */
370 clip_ptr = clip_list;
371 while (clip_ptr) {
372 if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
373 return -EFAULT;
374 for (y = 0; y < clip.c.height; y += 16)
375 for (x = 0; x < clip.c.width; x += 16) {
376 mbnum = (go->width >> 4) *
377 ((clip.c.top + y) >> 4) +
378 ((clip.c.left + x) >> 4);
379 go->modet_map[mbnum] = region;
380 }
381 clip_ptr = clip.next;
382 }
383 return 0;
384}
385
Pete Eberleind73f8222008-10-30 12:56:33 -0700386static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl)
387{
388 static const u32 user_ctrls[] = {
389 V4L2_CID_USER_CLASS,
390 0
391 };
392 static const u32 mpeg_ctrls[] = {
393 V4L2_CID_MPEG_CLASS,
394 V4L2_CID_MPEG_STREAM_TYPE,
395 V4L2_CID_MPEG_VIDEO_ENCODING,
396 V4L2_CID_MPEG_VIDEO_ASPECT,
397 V4L2_CID_MPEG_VIDEO_GOP_SIZE,
398 V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
399 V4L2_CID_MPEG_VIDEO_BITRATE,
400 0
401 };
402 static const u32 *ctrl_classes[] = {
403 user_ctrls,
404 mpeg_ctrls,
405 NULL
406 };
407
408 /* The ctrl may already contain the queried i2c controls,
409 * query the mpeg controls if the existing ctrl id is
410 * greater than the next mpeg ctrl id.
411 */
412 id = v4l2_ctrl_next(ctrl_classes, id);
413 if (id >= ctrl->id && ctrl->name[0])
414 return 0;
415
416 memset(ctrl, 0, sizeof(*ctrl));
417 ctrl->id = id;
418
419 switch (ctrl->id) {
420 case V4L2_CID_USER_CLASS:
421 case V4L2_CID_MPEG_CLASS:
422 return v4l2_ctrl_query_fill_std(ctrl);
423 case V4L2_CID_MPEG_STREAM_TYPE:
424 return v4l2_ctrl_query_fill(ctrl,
425 V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
426 V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
427 V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
428 case V4L2_CID_MPEG_VIDEO_ENCODING:
429 return v4l2_ctrl_query_fill(ctrl,
430 V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
431 V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1,
432 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
433 case V4L2_CID_MPEG_VIDEO_ASPECT:
434 return v4l2_ctrl_query_fill(ctrl,
435 V4L2_MPEG_VIDEO_ASPECT_1x1,
436 V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
437 V4L2_MPEG_VIDEO_ASPECT_1x1);
438 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
439 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
440 return v4l2_ctrl_query_fill_std(ctrl);
441 case V4L2_CID_MPEG_VIDEO_BITRATE:
442 return v4l2_ctrl_query_fill(ctrl,
443 64000,
444 10000000, 1,
445 9800000);
446 default:
447 break;
448 }
449 return -EINVAL;
450}
451
452static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go)
453{
454 /* pretty sure we can't change any of these while streaming */
455 if (go->streaming)
456 return -EBUSY;
457
458 switch (ctrl->id) {
459 case V4L2_CID_MPEG_STREAM_TYPE:
460 switch (ctrl->value) {
461 case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
462 go->format = GO7007_FORMAT_MPEG2;
463 go->bitrate = 9800000;
464 go->gop_size = 15;
465 go->pali = 0x48;
466 go->closed_gop = 1;
467 go->repeat_seqhead = 0;
468 go->seq_header_enable = 1;
469 go->gop_header_enable = 1;
470 go->dvd_mode = 1;
471 break;
472 case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM:
473 /* todo: */
474 break;
475 default:
476 return -EINVAL;
477 }
478 break;
479 case V4L2_CID_MPEG_VIDEO_ENCODING:
480 switch (ctrl->value) {
481 case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
482 go->format = GO7007_FORMAT_MPEG1;
483 go->pali = 0;
484 break;
485 case V4L2_MPEG_VIDEO_ENCODING_MPEG_2:
486 go->format = GO7007_FORMAT_MPEG2;
487 /*if (mpeg->pali >> 24 == 2)
488 go->pali = mpeg->pali & 0xff;
489 else*/
490 go->pali = 0x48;
491 break;
492 case V4L2_MPEG_VIDEO_ENCODING_MPEG_4:
493 go->format = GO7007_FORMAT_MPEG4;
494 /*if (mpeg->pali >> 24 == 4)
495 go->pali = mpeg->pali & 0xff;
496 else*/
497 go->pali = 0xf5;
498 break;
499 default:
500 return -EINVAL;
501 }
502 go->gop_header_enable =
503 /*mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
504 ? 0 :*/ 1;
505 /*if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
506 go->repeat_seqhead = 1;
507 else*/
508 go->repeat_seqhead = 0;
509 go->dvd_mode = 0;
510 break;
511 case V4L2_CID_MPEG_VIDEO_ASPECT:
512 if (go->format == GO7007_FORMAT_MJPEG)
513 return -EINVAL;
514 switch (ctrl->value) {
515 case V4L2_MPEG_VIDEO_ASPECT_1x1:
516 go->aspect_ratio = GO7007_RATIO_1_1;
517 break;
518 case V4L2_MPEG_VIDEO_ASPECT_4x3:
519 go->aspect_ratio = GO7007_RATIO_4_3;
520 break;
521 case V4L2_MPEG_VIDEO_ASPECT_16x9:
522 go->aspect_ratio = GO7007_RATIO_16_9;
523 break;
524 case V4L2_MPEG_VIDEO_ASPECT_221x100:
525 default:
526 return -EINVAL;
527 }
528 break;
529 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
530 go->gop_size = ctrl->value;
531 break;
532 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
533 if (ctrl->value != 0 && ctrl->value != 1)
534 return -EINVAL;
535 go->closed_gop = ctrl->value;
536 break;
537 case V4L2_CID_MPEG_VIDEO_BITRATE:
538 /* Upper bound is kind of arbitrary here */
539 if (ctrl->value < 64000 || ctrl->value > 10000000)
540 return -EINVAL;
541 go->bitrate = ctrl->value;
542 break;
543 default:
544 return -EINVAL;
545 }
546 return 0;
547}
548
549static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go)
550{
551 switch (ctrl->id) {
552 case V4L2_CID_MPEG_STREAM_TYPE:
553 if (go->dvd_mode)
554 ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
555 else
556 ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG_ELEM;
557 break;
558 case V4L2_CID_MPEG_VIDEO_ENCODING:
559 switch (go->format) {
560 case GO7007_FORMAT_MPEG1:
561 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
562 break;
563 case GO7007_FORMAT_MPEG2:
564 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
565 break;
566 case GO7007_FORMAT_MPEG4:
567 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
568 break;
569 default:
570 return -EINVAL;
571 }
572 break;
573 case V4L2_CID_MPEG_VIDEO_ASPECT:
574 switch (go->aspect_ratio) {
575 case GO7007_RATIO_1_1:
576 ctrl->value = V4L2_MPEG_VIDEO_ASPECT_1x1;
577 break;
578 case GO7007_RATIO_4_3:
579 ctrl->value = V4L2_MPEG_VIDEO_ASPECT_4x3;
580 break;
581 case GO7007_RATIO_16_9:
582 ctrl->value = V4L2_MPEG_VIDEO_ASPECT_16x9;
583 break;
584 default:
585 return -EINVAL;
586 }
587 break;
588 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
589 ctrl->value = go->gop_size;
590 break;
591 case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
592 ctrl->value = go->closed_gop;
593 break;
594 case V4L2_CID_MPEG_VIDEO_BITRATE:
595 ctrl->value = go->bitrate;
596 break;
597 default:
598 return -EINVAL;
599 }
600 return 0;
601}
602
Greg Kroah-Hartman4f7ddec2009-01-05 10:21:08 -0800603static long go7007_do_ioctl(struct file *file, unsigned int cmd, void *arg)
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800604{
605 struct go7007_file *gofh = file->private_data;
606 struct go7007 *go = gofh->go;
607 unsigned long flags;
608 int retval = 0;
609
610 switch (cmd) {
611 case VIDIOC_QUERYCAP:
612 {
613 struct v4l2_capability *cap = arg;
614
615 memset(cap, 0, sizeof(*cap));
616 strcpy(cap->driver, "go7007");
617 strncpy(cap->card, go->name, sizeof(cap->card));
618 cap->version = KERNEL_VERSION(0, 9, 8);
619 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
Pete Eberleind73f8222008-10-30 12:56:33 -0700620 V4L2_CAP_STREAMING | V4L2_CAP_AUDIO;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800621 if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
622 cap->capabilities |= V4L2_CAP_TUNER;
623 return 0;
624 }
625 case VIDIOC_ENUM_FMT:
626 {
627 struct v4l2_fmtdesc *fmt = arg;
628 unsigned int index;
629 char *desc;
630 u32 pixelformat;
631
632 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
633 return -EINVAL;
634 switch (fmt->index) {
635 case 0:
636 pixelformat = V4L2_PIX_FMT_MJPEG;
637 desc = "Motion-JPEG";
638 break;
639 case 1:
640 pixelformat = V4L2_PIX_FMT_MPEG;
641 desc = "MPEG1/MPEG2/MPEG4";
642 break;
643 default:
644 return -EINVAL;
645 }
646 index = fmt->index;
647 memset(fmt, 0, sizeof(*fmt));
648 fmt->index = index;
649 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
650 fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
651 strncpy(fmt->description, desc, sizeof(fmt->description));
652 fmt->pixelformat = pixelformat;
653
654 return 0;
655 }
656 case VIDIOC_TRY_FMT:
657 {
658 struct v4l2_format *fmt = arg;
659
660 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
661 return -EINVAL;
662 return set_capture_size(go, fmt, 1);
663 }
664 case VIDIOC_G_FMT:
665 {
666 struct v4l2_format *fmt = arg;
667
668 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
669 return -EINVAL;
670 memset(fmt, 0, sizeof(*fmt));
671 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
672 fmt->fmt.pix.width = go->width;
673 fmt->fmt.pix.height = go->height;
674 fmt->fmt.pix.pixelformat = go->format == GO7007_FORMAT_MJPEG ?
675 V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG;
676 fmt->fmt.pix.field = V4L2_FIELD_NONE;
677 fmt->fmt.pix.bytesperline = 0;
678 fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
679 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */
680 return 0;
681 }
682 case VIDIOC_S_FMT:
683 {
684 struct v4l2_format *fmt = arg;
685
686 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
687 return -EINVAL;
688 if (go->streaming)
689 return -EBUSY;
690 return set_capture_size(go, fmt, 0);
691 }
Pete Eberleind73f8222008-10-30 12:56:33 -0700692 case VIDIOC_ENUMAUDIO:
693 case VIDIOC_G_AUDIO:
694 case VIDIOC_S_AUDIO:
695 {
696 struct v4l2_audio *audio = arg;
697
698 if (!go->i2c_adapter_online)
699 return -EIO;
700 i2c_clients_command(&go->i2c_adapter, cmd, arg);
701 if (cmd == VIDIOC_ENUMAUDIO && !audio->name[0])
702 return -EINVAL;
703 return 0;
704 }
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800705 case VIDIOC_G_FBUF:
706 case VIDIOC_S_FBUF:
707 return -EINVAL;
708 case VIDIOC_REQBUFS:
709 {
710 struct v4l2_requestbuffers *req = arg;
711 unsigned int count, i;
712
713 if (go->streaming)
714 return -EBUSY;
715 if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
716 req->memory != V4L2_MEMORY_MMAP)
717 return -EINVAL;
718
719 down(&gofh->lock);
720 retval = -EBUSY;
721 for (i = 0; i < gofh->buf_count; ++i)
722 if (gofh->bufs[i].mapped > 0)
723 goto unlock_and_return;
724 down(&go->hw_lock);
725 if (go->in_use > 0 && gofh->buf_count == 0) {
726 up(&go->hw_lock);
727 goto unlock_and_return;
728 }
729 if (gofh->buf_count > 0)
730 kfree(gofh->bufs);
731 retval = -ENOMEM;
732 count = req->count;
733 if (count > 0) {
734 if (count < 2)
735 count = 2;
736 if (count > 32)
737 count = 32;
738 gofh->bufs = kmalloc(count *
739 sizeof(struct go7007_buffer),
740 GFP_KERNEL);
741 if (gofh->bufs == NULL) {
742 up(&go->hw_lock);
743 goto unlock_and_return;
744 }
745 memset(gofh->bufs, 0,
746 count * sizeof(struct go7007_buffer));
747 for (i = 0; i < count; ++i) {
748 gofh->bufs[i].go = go;
749 gofh->bufs[i].index = i;
750 gofh->bufs[i].state = BUF_STATE_IDLE;
751 gofh->bufs[i].mapped = 0;
752 }
753 go->in_use = 1;
754 } else {
755 go->in_use = 0;
756 }
757 gofh->buf_count = count;
758 up(&go->hw_lock);
759 up(&gofh->lock);
760 memset(req, 0, sizeof(*req));
761 req->count = count;
762 req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
763 req->memory = V4L2_MEMORY_MMAP;
764 return 0;
765 }
766 case VIDIOC_QUERYBUF:
767 {
768 struct v4l2_buffer *buf = arg;
769 unsigned int index;
770
771 retval = -EINVAL;
772 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
773 return -EINVAL;
774 index = buf->index;
775 down(&gofh->lock);
776 if (index >= gofh->buf_count)
777 goto unlock_and_return;
778 memset(buf, 0, sizeof(*buf));
779 buf->index = index;
780 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
781 switch (gofh->bufs[index].state) {
782 case BUF_STATE_QUEUED:
783 buf->flags = V4L2_BUF_FLAG_QUEUED;
784 break;
785 case BUF_STATE_DONE:
786 buf->flags = V4L2_BUF_FLAG_DONE;
787 break;
788 default:
789 buf->flags = 0;
790 }
791 if (gofh->bufs[index].mapped)
792 buf->flags |= V4L2_BUF_FLAG_MAPPED;
793 buf->memory = V4L2_MEMORY_MMAP;
794 buf->m.offset = index * GO7007_BUF_SIZE;
795 buf->length = GO7007_BUF_SIZE;
796 up(&gofh->lock);
797
798 return 0;
799 }
800 case VIDIOC_QBUF:
801 {
802 struct v4l2_buffer *buf = arg;
803 struct go7007_buffer *gobuf;
804 int ret;
805
806 retval = -EINVAL;
807 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
808 buf->memory != V4L2_MEMORY_MMAP)
809 return -EINVAL;
810 down(&gofh->lock);
811 if (buf->index < 0 || buf->index >= gofh->buf_count)
812 goto unlock_and_return;
813 gobuf = &gofh->bufs[buf->index];
814 if (gobuf->mapped == 0)
815 goto unlock_and_return;
816 retval = -EBUSY;
817 if (gobuf->state != BUF_STATE_IDLE)
818 goto unlock_and_return;
819 /* offset will be 0 until we really support USERPTR streaming */
820 gobuf->offset = gobuf->user_addr & ~PAGE_MASK;
821 gobuf->bytesused = 0;
822 gobuf->frame_offset = 0;
823 gobuf->modet_active = 0;
824 if (gobuf->offset > 0)
825 gobuf->page_count = GO7007_BUF_PAGES + 1;
826 else
827 gobuf->page_count = GO7007_BUF_PAGES;
828 retval = -ENOMEM;
829 down_read(&current->mm->mmap_sem);
830 ret = get_user_pages(current, current->mm,
831 gobuf->user_addr & PAGE_MASK, gobuf->page_count,
832 1, 1, gobuf->pages, NULL);
833 up_read(&current->mm->mmap_sem);
834 if (ret != gobuf->page_count) {
835 int i;
836 for (i = 0; i < ret; ++i)
837 page_cache_release(gobuf->pages[i]);
838 gobuf->page_count = 0;
839 goto unlock_and_return;
840 }
841 gobuf->state = BUF_STATE_QUEUED;
842 spin_lock_irqsave(&go->spinlock, flags);
843 list_add_tail(&gobuf->stream, &go->stream);
844 spin_unlock_irqrestore(&go->spinlock, flags);
845 up(&gofh->lock);
846 return 0;
847 }
848 case VIDIOC_DQBUF:
849 {
850 struct v4l2_buffer *buf = arg;
851 struct go7007_buffer *gobuf;
852 u32 frame_type_flag;
853 DEFINE_WAIT(wait);
854
855 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
856 return -EINVAL;
857 if (buf->memory != V4L2_MEMORY_MMAP)
858 return -EINVAL;
859 down(&gofh->lock);
860 retval = -EINVAL;
861 if (list_empty(&go->stream))
862 goto unlock_and_return;
863 gobuf = list_entry(go->stream.next,
864 struct go7007_buffer, stream);
865 retval = -EAGAIN;
866 if (gobuf->state != BUF_STATE_DONE &&
867 !(file->f_flags & O_NONBLOCK)) {
868 for (;;) {
869 prepare_to_wait(&go->frame_waitq, &wait,
870 TASK_INTERRUPTIBLE);
871 if (gobuf->state == BUF_STATE_DONE)
872 break;
873 if (signal_pending(current)) {
874 retval = -ERESTARTSYS;
875 break;
876 }
877 schedule();
878 }
879 finish_wait(&go->frame_waitq, &wait);
880 }
881 if (gobuf->state != BUF_STATE_DONE)
882 goto unlock_and_return;
883 spin_lock_irqsave(&go->spinlock, flags);
884 deactivate_buffer(gobuf);
885 spin_unlock_irqrestore(&go->spinlock, flags);
886 frame_type_flag = get_frame_type_flag(gobuf, go->format);
887 gobuf->state = BUF_STATE_IDLE;
888 memset(buf, 0, sizeof(*buf));
889 buf->index = gobuf->index;
890 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
891 buf->bytesused = gobuf->bytesused;
892 buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag;
893 buf->field = V4L2_FIELD_NONE;
894 buf->timestamp = gobuf->timestamp;
895 buf->sequence = gobuf->seq;
896 buf->memory = V4L2_MEMORY_MMAP;
897 buf->m.offset = gobuf->index * GO7007_BUF_SIZE;
898 buf->length = GO7007_BUF_SIZE;
899 buf->reserved = gobuf->modet_active;
900 up(&gofh->lock);
901 return 0;
902 }
903 case VIDIOC_STREAMON:
904 {
905 unsigned int *type = arg;
906
907 if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
908 return -EINVAL;
909 down(&gofh->lock);
910 down(&go->hw_lock);
911 if (!go->streaming) {
912 go->streaming = 1;
913 go->next_seq = 0;
914 go->active_buf = NULL;
915 if (go7007_start_encoder(go) < 0)
916 retval = -EIO;
917 else
918 retval = 0;
919 }
920 up(&go->hw_lock);
921 up(&gofh->lock);
922 return retval;
923 }
924 case VIDIOC_STREAMOFF:
925 {
926 unsigned int *type = arg;
927
928 if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
929 return -EINVAL;
930 down(&gofh->lock);
931 go7007_streamoff(go);
932 up(&gofh->lock);
933 return 0;
934 }
935 case VIDIOC_QUERYCTRL:
936 {
937 struct v4l2_queryctrl *ctrl = arg;
938 u32 id;
939
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800940 id = ctrl->id;
941 memset(ctrl, 0, sizeof(*ctrl));
942 ctrl->id = id;
Pete Eberleind73f8222008-10-30 12:56:33 -0700943 if (go->i2c_adapter_online)
944 i2c_clients_command(&go->i2c_adapter,
945 VIDIOC_QUERYCTRL, arg);
946 else if (go->hpi_ops && go->hpi_ops->send_command)
947 go->hpi_ops->send_command(go, cmd, arg);
948 if (id & V4L2_CTRL_FLAG_NEXT_CTRL || ctrl->name[0] == 0)
949 return mpeg_queryctrl(id, ctrl);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800950 return ctrl->name[0] == 0 ? -EINVAL : 0;
951 }
952 case VIDIOC_G_CTRL:
953 {
954 struct v4l2_control *ctrl = arg;
955 struct v4l2_queryctrl query;
956
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800957 memset(&query, 0, sizeof(query));
958 query.id = ctrl->id;
Pete Eberleind73f8222008-10-30 12:56:33 -0700959 if (go->i2c_adapter_online)
960 i2c_clients_command(&go->i2c_adapter,
961 VIDIOC_QUERYCTRL, &query);
962 else if (go->hpi_ops && go->hpi_ops->send_command)
963 if (0 == go->hpi_ops->send_command(go, cmd, arg))
964 return 0;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800965 if (query.name[0] == 0)
Pete Eberleind73f8222008-10-30 12:56:33 -0700966 return mpeg_g_control(ctrl, go);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800967 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, arg);
968 return 0;
969 }
970 case VIDIOC_S_CTRL:
971 {
972 struct v4l2_control *ctrl = arg;
973 struct v4l2_queryctrl query;
974
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800975 memset(&query, 0, sizeof(query));
976 query.id = ctrl->id;
Pete Eberleind73f8222008-10-30 12:56:33 -0700977 if (go->i2c_adapter_online)
978 i2c_clients_command(&go->i2c_adapter,
979 VIDIOC_QUERYCTRL, &query);
980 else if (go->hpi_ops && go->hpi_ops->send_command)
981 if (0 == go->hpi_ops->send_command(go, cmd, arg))
982 return 0;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800983 if (query.name[0] == 0)
Pete Eberleind73f8222008-10-30 12:56:33 -0700984 return mpeg_s_control(ctrl, go);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -0800985 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, arg);
986 return 0;
987 }
988 case VIDIOC_G_PARM:
989 {
990 struct v4l2_streamparm *parm = arg;
991 struct v4l2_fract timeperframe = {
992 .numerator = 1001 * go->fps_scale,
993 .denominator = go->sensor_framerate,
994 };
995
996 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
997 return -EINVAL;
998 memset(parm, 0, sizeof(*parm));
999 parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1000 parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
1001 parm->parm.capture.timeperframe = timeperframe;
1002 return 0;
1003 }
1004 case VIDIOC_S_PARM:
1005 {
1006 struct v4l2_streamparm *parm = arg;
1007 unsigned int n, d;
1008
1009 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1010 return -EINVAL;
1011 if (parm->parm.capture.capturemode != 0)
1012 return -EINVAL;
1013 n = go->sensor_framerate *
1014 parm->parm.capture.timeperframe.numerator;
1015 d = 1001 * parm->parm.capture.timeperframe.denominator;
1016 if (n != 0 && d != 0 && n > d)
1017 go->fps_scale = (n + d/2) / d;
1018 else
1019 go->fps_scale = 1;
1020 return 0;
1021 }
1022 case VIDIOC_ENUMSTD:
1023 {
1024 struct v4l2_standard *std = arg;
1025
1026 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1027 go->input == go->board_info->num_inputs - 1) {
1028 if (!go->i2c_adapter_online)
1029 return -EIO;
1030 i2c_clients_command(&go->i2c_adapter,
1031 VIDIOC_ENUMSTD, arg);
1032 if (!std->id) /* hack to indicate EINVAL from tuner */
1033 return -EINVAL;
1034 } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
1035 switch (std->index) {
1036 case 0:
1037 v4l2_video_std_construct(std,
1038 V4L2_STD_NTSC, "NTSC");
1039 break;
1040 case 1:
1041 v4l2_video_std_construct(std,
1042 V4L2_STD_PAL | V4L2_STD_SECAM,
1043 "PAL/SECAM");
1044 break;
1045 default:
1046 return -EINVAL;
1047 }
1048 } else {
1049 if (std->index != 0)
1050 return -EINVAL;
1051 memset(std, 0, sizeof(*std));
1052 snprintf(std->name, sizeof(std->name), "%dx%d, %dfps",
1053 go->board_info->sensor_width,
1054 go->board_info->sensor_height,
1055 go->board_info->sensor_framerate / 1000);
1056 std->frameperiod.numerator = 1001;
1057 std->frameperiod.denominator =
1058 go->board_info->sensor_framerate;
1059 }
1060 return 0;
1061 }
1062 case VIDIOC_G_STD:
1063 {
1064 v4l2_std_id *std = arg;
1065
1066 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1067 go->input == go->board_info->num_inputs - 1) {
1068 if (!go->i2c_adapter_online)
1069 return -EIO;
1070 i2c_clients_command(&go->i2c_adapter,
1071 VIDIOC_G_STD, arg);
1072 } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
1073 if (go->standard == GO7007_STD_NTSC)
1074 *std = V4L2_STD_NTSC;
1075 else
1076 *std = V4L2_STD_PAL | V4L2_STD_SECAM;
Pete Eberleind73f8222008-10-30 12:56:33 -07001077 } else if (go->hpi_ops && go->hpi_ops->send_command) {
1078 go->hpi_ops->send_command(go, cmd, arg);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001079 } else
1080 *std = 0;
1081 return 0;
1082 }
1083 case VIDIOC_S_STD:
1084 {
1085 v4l2_std_id *std = arg;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001086
1087 if (go->streaming)
1088 return -EBUSY;
1089 if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
1090 *std != 0)
1091 return -EINVAL;
1092 if (*std == 0)
1093 return -EINVAL;
1094 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1095 go->input == go->board_info->num_inputs - 1) {
1096 if (!go->i2c_adapter_online)
1097 return -EIO;
1098 i2c_clients_command(&go->i2c_adapter,
1099 VIDIOC_S_STD, arg);
1100 if (!*std) /* hack to indicate EINVAL from tuner */
1101 return -EINVAL;
1102 }
1103 if (*std & V4L2_STD_NTSC) {
1104 go->standard = GO7007_STD_NTSC;
1105 go->sensor_framerate = 30000;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001106 } else if (*std & V4L2_STD_PAL) {
1107 go->standard = GO7007_STD_PAL;
1108 go->sensor_framerate = 25025;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001109 } else if (*std & V4L2_STD_SECAM) {
1110 go->standard = GO7007_STD_PAL;
1111 go->sensor_framerate = 25025;
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001112 } else
1113 return -EINVAL;
1114 if (go->i2c_adapter_online)
1115 i2c_clients_command(&go->i2c_adapter,
Ross Cohendf20d692008-09-29 22:36:24 -04001116 VIDIOC_S_STD, std);
Pete Eberleind73f8222008-10-30 12:56:33 -07001117 if (go->hpi_ops && go->hpi_ops->send_command)
1118 go->hpi_ops->send_command(go, cmd, arg);
1119
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001120 set_capture_size(go, NULL, 0);
1121 return 0;
1122 }
1123 case VIDIOC_QUERYSTD:
1124 {
1125 v4l2_std_id *std = arg;
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_QUERYSTD, arg);
1133 } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1134 *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
1135 else
1136 *std = 0;
1137 return 0;
1138 }
1139 case VIDIOC_ENUMINPUT:
1140 {
1141 struct v4l2_input *inp = arg;
1142 int index;
1143
1144 if (inp->index >= go->board_info->num_inputs)
1145 return -EINVAL;
1146 index = inp->index;
1147 memset(inp, 0, sizeof(*inp));
1148 inp->index = index;
1149 strncpy(inp->name, go->board_info->inputs[index].name,
1150 sizeof(inp->name));
1151 /* If this board has a tuner, it will be the last input */
1152 if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
1153 index == go->board_info->num_inputs - 1)
1154 inp->type = V4L2_INPUT_TYPE_TUNER;
1155 else
1156 inp->type = V4L2_INPUT_TYPE_CAMERA;
1157 inp->audioset = 0;
1158 inp->tuner = 0;
1159 if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1160 inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
1161 V4L2_STD_SECAM;
1162 else
1163 inp->std = 0;
1164 return 0;
1165 }
1166 case VIDIOC_G_INPUT:
1167 {
1168 int *input = arg;
1169
1170 *input = go->input;
1171 return 0;
1172 }
1173 case VIDIOC_S_INPUT:
1174 {
1175 int *input = arg;
1176
1177 if (*input >= go->board_info->num_inputs)
1178 return -EINVAL;
1179 if (go->streaming)
1180 return -EBUSY;
1181 go->input = *input;
1182 if (go->i2c_adapter_online) {
Ross Cohendf20d692008-09-29 22:36:24 -04001183 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT,
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001184 &go->board_info->inputs[*input].video_input);
1185 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO,
1186 &go->board_info->inputs[*input].audio_input);
1187 }
1188 return 0;
1189 }
1190 case VIDIOC_G_TUNER:
1191 {
1192 struct v4l2_tuner *t = arg;
1193
1194 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1195 return -EINVAL;
1196 if (t->index != 0)
1197 return -EINVAL;
1198 if (!go->i2c_adapter_online)
1199 return -EIO;
1200 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, arg);
1201 t->index = 0;
1202 return 0;
1203 }
1204 case VIDIOC_S_TUNER:
1205 {
1206 struct v4l2_tuner *t = arg;
1207
1208 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1209 return -EINVAL;
1210 if (t->index != 0)
1211 return -EINVAL;
1212 if (!go->i2c_adapter_online)
1213 return -EIO;
1214 switch (go->board_id) {
1215 case GO7007_BOARDID_PX_TV402U_NA:
1216 case GO7007_BOARDID_PX_TV402U_JP:
1217 /* No selectable options currently */
1218 if (t->audmode != V4L2_TUNER_MODE_STEREO)
1219 return -EINVAL;
1220 break;
1221 }
1222 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, arg);
1223 return 0;
1224 }
1225 case VIDIOC_G_FREQUENCY:
1226 {
1227 struct v4l2_frequency *f = arg;
1228
1229 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1230 return -EINVAL;
1231 if (!go->i2c_adapter_online)
1232 return -EIO;
1233 memset(f, 0, sizeof(*f));
1234 f->type = V4L2_TUNER_ANALOG_TV;
1235 i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, arg);
1236 return 0;
1237 }
1238 case VIDIOC_S_FREQUENCY:
1239 {
1240 if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
1241 return -EINVAL;
1242 if (!go->i2c_adapter_online)
1243 return -EIO;
1244 i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, arg);
1245 return 0;
1246 }
1247 case VIDIOC_CROPCAP:
1248 {
1249 struct v4l2_cropcap *cropcap = arg;
1250
1251 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1252 return -EINVAL;
1253 memset(cropcap, 0, sizeof(*cropcap));
1254 cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1255 /* These specify the raw input of the sensor */
1256 switch (go->standard) {
1257 case GO7007_STD_NTSC:
1258 cropcap->bounds.top = 0;
1259 cropcap->bounds.left = 0;
1260 cropcap->bounds.width = 720;
1261 cropcap->bounds.height = 480;
1262 cropcap->defrect.top = 0;
1263 cropcap->defrect.left = 0;
1264 cropcap->defrect.width = 720;
1265 cropcap->defrect.height = 480;
1266 break;
1267 case GO7007_STD_PAL:
1268 cropcap->bounds.top = 0;
1269 cropcap->bounds.left = 0;
1270 cropcap->bounds.width = 720;
1271 cropcap->bounds.height = 576;
1272 cropcap->defrect.top = 0;
1273 cropcap->defrect.left = 0;
1274 cropcap->defrect.width = 720;
1275 cropcap->defrect.height = 576;
1276 break;
1277 case GO7007_STD_OTHER:
1278 cropcap->bounds.top = 0;
1279 cropcap->bounds.left = 0;
1280 cropcap->bounds.width = go->board_info->sensor_width;
1281 cropcap->bounds.height = go->board_info->sensor_height;
1282 cropcap->defrect.top = 0;
1283 cropcap->defrect.left = 0;
1284 cropcap->defrect.width = go->board_info->sensor_width;
1285 cropcap->defrect.height = go->board_info->sensor_height;
1286 break;
1287 }
1288
1289 return 0;
1290 }
1291 case VIDIOC_G_CROP:
1292 {
1293 struct v4l2_crop *crop = arg;
1294
1295 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1296 return -EINVAL;
1297 memset(crop, 0, sizeof(*crop));
1298 crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1299 /* These specify the raw input of the sensor */
1300 switch (go->standard) {
1301 case GO7007_STD_NTSC:
1302 crop->c.top = 0;
1303 crop->c.left = 0;
1304 crop->c.width = 720;
1305 crop->c.height = 480;
1306 break;
1307 case GO7007_STD_PAL:
1308 crop->c.top = 0;
1309 crop->c.left = 0;
1310 crop->c.width = 720;
1311 crop->c.height = 576;
1312 break;
1313 case GO7007_STD_OTHER:
1314 crop->c.top = 0;
1315 crop->c.left = 0;
1316 crop->c.width = go->board_info->sensor_width;
1317 crop->c.height = go->board_info->sensor_height;
1318 break;
1319 }
1320
1321 return 0;
1322 }
1323 case VIDIOC_S_CROP:
1324 {
1325 struct v4l2_crop *crop = arg;
1326
1327 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1328 return -EINVAL;
1329 return 0;
1330 }
1331 case VIDIOC_G_JPEGCOMP:
1332 {
1333 struct v4l2_jpegcompression *params = arg;
1334
1335 memset(params, 0, sizeof(*params));
1336 params->quality = 50; /* ?? */
1337 params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
1338 V4L2_JPEG_MARKER_DQT;
1339
1340 return 0;
1341 }
1342 case VIDIOC_S_JPEGCOMP:
1343 {
1344 struct v4l2_jpegcompression *params = arg;
1345
1346 if (params->quality != 50 ||
1347 params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
1348 V4L2_JPEG_MARKER_DQT))
1349 return -EINVAL;
1350 return 0;
1351 }
1352 /* Temporary ioctls for controlling compression characteristics */
1353 case GO7007IOC_S_BITRATE:
1354 {
1355 int *bitrate = arg;
1356
1357 if (go->streaming)
1358 return -EINVAL;
1359 /* Upper bound is kind of arbitrary here */
1360 if (*bitrate < 64000 || *bitrate > 10000000)
1361 return -EINVAL;
1362 go->bitrate = *bitrate;
1363 return 0;
1364 }
1365 case GO7007IOC_G_BITRATE:
1366 {
1367 int *bitrate = arg;
1368
1369 *bitrate = go->bitrate;
1370 return 0;
1371 }
1372 case GO7007IOC_S_COMP_PARAMS:
1373 {
1374 struct go7007_comp_params *comp = arg;
1375
1376 if (go->format == GO7007_FORMAT_MJPEG)
1377 return -EINVAL;
1378 if (comp->gop_size > 0)
1379 go->gop_size = comp->gop_size;
1380 else
1381 go->gop_size = go->sensor_framerate / 1000;
1382 if (go->gop_size != 15)
1383 go->dvd_mode = 0;
1384 /*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */
1385 if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
1386 switch (comp->aspect_ratio) {
1387 case GO7007_ASPECT_RATIO_4_3_NTSC:
1388 case GO7007_ASPECT_RATIO_4_3_PAL:
1389 go->aspect_ratio = GO7007_RATIO_4_3;
1390 break;
1391 case GO7007_ASPECT_RATIO_16_9_NTSC:
1392 case GO7007_ASPECT_RATIO_16_9_PAL:
1393 go->aspect_ratio = GO7007_RATIO_16_9;
1394 break;
1395 default:
1396 go->aspect_ratio = GO7007_RATIO_1_1;
1397 break;
1398 }
1399 }
1400 if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) {
1401 go->dvd_mode = 0;
1402 go->seq_header_enable = 0;
1403 } else {
1404 go->seq_header_enable = 1;
1405 }
1406 /* fall-through */
1407 }
1408 case GO7007IOC_G_COMP_PARAMS:
1409 {
1410 struct go7007_comp_params *comp = arg;
1411
1412 if (go->format == GO7007_FORMAT_MJPEG)
1413 return -EINVAL;
1414 memset(comp, 0, sizeof(*comp));
1415 comp->gop_size = go->gop_size;
1416 comp->max_b_frames = go->ipb ? 2 : 0;
1417 switch (go->aspect_ratio) {
1418 case GO7007_RATIO_4_3:
1419 if (go->standard == GO7007_STD_NTSC)
1420 comp->aspect_ratio =
1421 GO7007_ASPECT_RATIO_4_3_NTSC;
1422 else
1423 comp->aspect_ratio =
1424 GO7007_ASPECT_RATIO_4_3_PAL;
1425 break;
1426 case GO7007_RATIO_16_9:
1427 if (go->standard == GO7007_STD_NTSC)
1428 comp->aspect_ratio =
1429 GO7007_ASPECT_RATIO_16_9_NTSC;
1430 else
1431 comp->aspect_ratio =
1432 GO7007_ASPECT_RATIO_16_9_PAL;
1433 break;
1434 default:
1435 comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1;
1436 break;
1437 }
1438 if (go->closed_gop)
1439 comp->flags |= GO7007_COMP_CLOSED_GOP;
1440 if (!go->seq_header_enable)
1441 comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER;
1442 return 0;
1443 }
1444 case GO7007IOC_S_MPEG_PARAMS:
1445 {
1446 struct go7007_mpeg_params *mpeg = arg;
1447
1448 if (go->format != GO7007_FORMAT_MPEG1 &&
1449 go->format != GO7007_FORMAT_MPEG2 &&
1450 go->format != GO7007_FORMAT_MPEG4)
1451 return -EINVAL;
1452
1453 if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) {
1454 go->format = GO7007_FORMAT_MPEG2;
1455 go->bitrate = 9800000;
1456 go->gop_size = 15;
1457 go->pali = 0x48;
1458 go->closed_gop = 1;
1459 go->repeat_seqhead = 0;
1460 go->seq_header_enable = 1;
1461 go->gop_header_enable = 1;
1462 go->dvd_mode = 1;
1463 } else {
1464 switch (mpeg->mpeg_video_standard) {
1465 case GO7007_MPEG_VIDEO_MPEG1:
1466 go->format = GO7007_FORMAT_MPEG1;
1467 go->pali = 0;
1468 break;
1469 case GO7007_MPEG_VIDEO_MPEG2:
1470 go->format = GO7007_FORMAT_MPEG2;
1471 if (mpeg->pali >> 24 == 2)
1472 go->pali = mpeg->pali & 0xff;
1473 else
1474 go->pali = 0x48;
1475 break;
1476 case GO7007_MPEG_VIDEO_MPEG4:
1477 go->format = GO7007_FORMAT_MPEG4;
1478 if (mpeg->pali >> 24 == 4)
1479 go->pali = mpeg->pali & 0xff;
1480 else
1481 go->pali = 0xf5;
1482 break;
1483 default:
1484 return -EINVAL;
1485 }
1486 go->gop_header_enable =
1487 mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
1488 ? 0 : 1;
1489 if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
1490 go->repeat_seqhead = 1;
1491 else
1492 go->repeat_seqhead = 0;
1493 go->dvd_mode = 0;
1494 }
1495 /* fall-through */
1496 }
1497 case GO7007IOC_G_MPEG_PARAMS:
1498 {
1499 struct go7007_mpeg_params *mpeg = arg;
1500
1501 memset(mpeg, 0, sizeof(*mpeg));
1502 switch (go->format) {
1503 case GO7007_FORMAT_MPEG1:
1504 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1;
1505 mpeg->pali = 0;
1506 break;
1507 case GO7007_FORMAT_MPEG2:
1508 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2;
1509 mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali);
1510 break;
1511 case GO7007_FORMAT_MPEG4:
1512 mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4;
1513 mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali);
1514 break;
1515 default:
1516 return -EINVAL;
1517 }
1518 if (!go->gop_header_enable)
1519 mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER;
1520 if (go->repeat_seqhead)
1521 mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER;
1522 if (go->dvd_mode)
1523 mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE;
1524 return 0;
1525 }
1526 case GO7007IOC_S_MD_PARAMS:
1527 {
1528 struct go7007_md_params *mdp = arg;
1529
1530 if (mdp->region > 3)
1531 return -EINVAL;
1532 if (mdp->trigger > 0) {
1533 go->modet[mdp->region].pixel_threshold =
1534 mdp->pixel_threshold >> 1;
1535 go->modet[mdp->region].motion_threshold =
1536 mdp->motion_threshold >> 1;
1537 go->modet[mdp->region].mb_threshold =
1538 mdp->trigger >> 1;
1539 go->modet[mdp->region].enable = 1;
1540 } else
1541 go->modet[mdp->region].enable = 0;
1542 /* fall-through */
1543 }
1544 case GO7007IOC_G_MD_PARAMS:
1545 {
1546 struct go7007_md_params *mdp = arg;
1547 int region = mdp->region;
1548
1549 if (mdp->region > 3)
1550 return -EINVAL;
1551 memset(mdp, 0, sizeof(struct go7007_md_params));
1552 mdp->region = region;
1553 if (!go->modet[region].enable)
1554 return 0;
1555 mdp->pixel_threshold =
1556 (go->modet[region].pixel_threshold << 1) + 1;
1557 mdp->motion_threshold =
1558 (go->modet[region].motion_threshold << 1) + 1;
1559 mdp->trigger =
1560 (go->modet[region].mb_threshold << 1) + 1;
1561 return 0;
1562 }
1563 case GO7007IOC_S_MD_REGION:
1564 {
1565 struct go7007_md_region *region = arg;
1566
1567 if (region->region < 1 || region->region > 3)
1568 return -EINVAL;
1569 return clip_to_modet_map(go, region->region, region->clips);
1570 }
1571 default:
Pete Eberleind73f8222008-10-30 12:56:33 -07001572 printk(KERN_INFO "go7007-v4l2: unsupported ioctl %d\n", cmd);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001573 return -ENOIOCTLCMD;
1574 }
1575 return 0;
1576
1577unlock_and_return:
1578 up(&gofh->lock);
1579 return retval;
1580}
1581
Greg Kroah-Hartman60572c02009-01-05 10:21:08 -08001582static long go7007_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001583{
1584 struct go7007_file *gofh = file->private_data;
1585
1586 if (gofh->go->status != STATUS_ONLINE)
1587 return -EIO;
1588
Greg Kroah-Hartman4f7ddec2009-01-05 10:21:08 -08001589 return video_usercopy(file, cmd, arg, go7007_do_ioctl);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001590}
1591
1592static ssize_t go7007_read(struct file *file, char __user *data,
1593 size_t count, loff_t *ppos)
1594{
1595 return -EINVAL;
1596}
1597
1598static void go7007_vm_open(struct vm_area_struct *vma)
1599{
1600 struct go7007_buffer *gobuf = vma->vm_private_data;
1601
1602 ++gobuf->mapped;
1603}
1604
1605static void go7007_vm_close(struct vm_area_struct *vma)
1606{
1607 struct go7007_buffer *gobuf = vma->vm_private_data;
1608 unsigned long flags;
1609
1610 if (--gobuf->mapped == 0) {
1611 spin_lock_irqsave(&gobuf->go->spinlock, flags);
1612 deactivate_buffer(gobuf);
1613 spin_unlock_irqrestore(&gobuf->go->spinlock, flags);
1614 }
1615}
1616
1617/* Copied from videobuf-dma-sg.c */
1618static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1619{
1620 struct page *page;
1621
1622 page = alloc_page(GFP_USER | __GFP_DMA32);
1623 if (!page)
1624 return VM_FAULT_OOM;
1625 clear_user_page(page_address(page), (unsigned long)vmf->virtual_address,
1626 page);
1627 vmf->page = page;
1628 return 0;
1629}
1630
1631static struct vm_operations_struct go7007_vm_ops = {
1632 .open = go7007_vm_open,
1633 .close = go7007_vm_close,
1634 .fault = go7007_vm_fault,
1635};
1636
1637static int go7007_mmap(struct file *file, struct vm_area_struct *vma)
1638{
1639 struct go7007_file *gofh = file->private_data;
1640 unsigned int index;
1641
1642 if (gofh->go->status != STATUS_ONLINE)
1643 return -EIO;
1644 if (!(vma->vm_flags & VM_SHARED))
1645 return -EINVAL; /* only support VM_SHARED mapping */
1646 if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE)
1647 return -EINVAL; /* must map exactly one full buffer */
1648 down(&gofh->lock);
1649 index = vma->vm_pgoff / GO7007_BUF_PAGES;
1650 if (index >= gofh->buf_count) {
1651 up(&gofh->lock);
1652 return -EINVAL; /* trying to map beyond requested buffers */
1653 }
1654 if (index * GO7007_BUF_PAGES != vma->vm_pgoff) {
1655 up(&gofh->lock);
1656 return -EINVAL; /* offset is not aligned on buffer boundary */
1657 }
1658 if (gofh->bufs[index].mapped > 0) {
1659 up(&gofh->lock);
1660 return -EBUSY;
1661 }
1662 gofh->bufs[index].mapped = 1;
1663 gofh->bufs[index].user_addr = vma->vm_start;
1664 vma->vm_ops = &go7007_vm_ops;
1665 vma->vm_flags |= VM_DONTEXPAND;
1666 vma->vm_flags &= ~VM_IO;
1667 vma->vm_private_data = &gofh->bufs[index];
1668 up(&gofh->lock);
1669 return 0;
1670}
1671
1672static unsigned int go7007_poll(struct file *file, poll_table *wait)
1673{
1674 struct go7007_file *gofh = file->private_data;
1675 struct go7007_buffer *gobuf;
1676
1677 if (list_empty(&gofh->go->stream))
1678 return POLLERR;
1679 gobuf = list_entry(gofh->go->stream.next, struct go7007_buffer, stream);
1680 poll_wait(file, &gofh->go->frame_waitq, wait);
1681 if (gobuf->state == BUF_STATE_DONE)
1682 return POLLIN | POLLRDNORM;
1683 return 0;
1684}
1685
1686static void go7007_vfl_release(struct video_device *vfd)
1687{
1688 struct go7007 *go = video_get_drvdata(vfd);
1689
1690 video_device_release(vfd);
1691 if (--go->ref_count == 0)
1692 kfree(go);
1693}
1694
Greg Kroah-Hartman60572c02009-01-05 10:21:08 -08001695static struct v4l2_file_operations go7007_fops = {
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001696 .owner = THIS_MODULE,
1697 .open = go7007_open,
1698 .release = go7007_release,
1699 .ioctl = go7007_ioctl,
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001700 .read = go7007_read,
1701 .mmap = go7007_mmap,
1702 .poll = go7007_poll,
1703};
1704
1705static struct video_device go7007_template = {
1706 .name = "go7007",
Ross Cohendf20d692008-09-29 22:36:24 -04001707 .vfl_type = VID_TYPE_CAPTURE,
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001708 .fops = &go7007_fops,
1709 .minor = -1,
1710 .release = go7007_vfl_release,
1711};
1712
1713int go7007_v4l2_init(struct go7007 *go)
1714{
1715 int rv;
1716
1717 go->video_dev = video_device_alloc();
1718 if (go->video_dev == NULL)
1719 return -ENOMEM;
1720 memcpy(go->video_dev, &go7007_template, sizeof(go7007_template));
1721 go->video_dev->parent = go->dev;
1722 rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1);
1723 if (rv < 0) {
1724 video_device_release(go->video_dev);
1725 go->video_dev = NULL;
1726 return rv;
1727 }
1728 video_set_drvdata(go->video_dev, go);
1729 ++go->ref_count;
Pete Eberleind73f8222008-10-30 12:56:33 -07001730 printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
1731 go->video_dev->name, go->video_dev->num);
Greg Kroah-Hartman866b8692008-02-15 16:53:09 -08001732
1733 return 0;
1734}
1735
1736void go7007_v4l2_remove(struct go7007 *go)
1737{
1738 unsigned long flags;
1739
1740 down(&go->hw_lock);
1741 if (go->streaming) {
1742 go->streaming = 0;
1743 go7007_stream_stop(go);
1744 spin_lock_irqsave(&go->spinlock, flags);
1745 abort_queued(go);
1746 spin_unlock_irqrestore(&go->spinlock, flags);
1747 }
1748 up(&go->hw_lock);
1749 if (go->video_dev)
1750 video_unregister_device(go->video_dev);
1751}