aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-01-18 17:59:11 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:24 -0400
commitb960074fec573fb1b226d9e2686ce51be807cdf1 (patch)
treeda58b7afa37b0ccd1c06948ad6497cb801553335 /drivers/media/common
parentc9b8b04b267f9a7e472daa06cdf6d4963d503d1f (diff)
V4L/DVB (10271): saa7146: convert to video_ioctl2.
The conversion to video_ioctl2 is the first phase to converting this driver to the latest v4l2 framework. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/saa7146_fops.c36
-rw-r--r--drivers/media/common/saa7146_video.c1250
2 files changed, 614 insertions, 672 deletions
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index cf06f4d10ad4..4a27d4eda628 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -308,14 +308,6 @@ static int fops_release(struct file *file)
308 return 0; 308 return 0;
309} 309}
310 310
311static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
312{
313/*
314 DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg));
315*/
316 return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
317}
318
319static int fops_mmap(struct file *file, struct vm_area_struct * vma) 311static int fops_mmap(struct file *file, struct vm_area_struct * vma)
320{ 312{
321 struct saa7146_fh *fh = file->private_data; 313 struct saa7146_fh *fh = file->private_data;
@@ -425,7 +417,7 @@ static const struct v4l2_file_operations video_fops =
425 .write = fops_write, 417 .write = fops_write,
426 .poll = fops_poll, 418 .poll = fops_poll,
427 .mmap = fops_mmap, 419 .mmap = fops_mmap,
428 .ioctl = fops_ioctl, 420 .ioctl = video_ioctl2,
429}; 421};
430 422
431static void vv_callback(struct saa7146_dev *dev, unsigned long status) 423static void vv_callback(struct saa7146_dev *dev, unsigned long status)
@@ -452,19 +444,16 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
452 } 444 }
453} 445}
454 446
455static struct video_device device_template =
456{
457 .fops = &video_fops,
458 .minor = -1,
459};
460
461int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) 447int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
462{ 448{
463 struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL); 449 struct saa7146_vv *vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
464 if( NULL == vv ) { 450
451 if (vv == NULL) {
465 ERR(("out of memory. aborting.\n")); 452 ERR(("out of memory. aborting.\n"));
466 return -1; 453 return -1;
467 } 454 }
455 ext_vv->ops = saa7146_video_ioctl_ops;
456 ext_vv->core_ops = &saa7146_video_ioctl_ops;
468 457
469 DEB_EE(("dev:%p\n",dev)); 458 DEB_EE(("dev:%p\n",dev));
470 459
@@ -521,6 +510,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
521{ 510{
522 struct saa7146_vv *vv = dev->vv_data; 511 struct saa7146_vv *vv = dev->vv_data;
523 struct video_device *vfd; 512 struct video_device *vfd;
513 int err;
524 514
525 DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); 515 DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
526 516
@@ -529,16 +519,18 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
529 if (vfd == NULL) 519 if (vfd == NULL)
530 return -ENOMEM; 520 return -ENOMEM;
531 521
532 memcpy(vfd, &device_template, sizeof(struct video_device)); 522 vfd->fops = &video_fops;
533 strlcpy(vfd->name, name, sizeof(vfd->name)); 523 vfd->ioctl_ops = dev->ext_vv_data ? &dev->ext_vv_data->ops :
524 &saa7146_video_ioctl_ops;
534 vfd->release = video_device_release; 525 vfd->release = video_device_release;
526 strlcpy(vfd->name, name, sizeof(vfd->name));
535 video_set_drvdata(vfd, dev); 527 video_set_drvdata(vfd, dev);
536 528
537 // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); 529 err = video_register_device(vfd, type, -1);
538 if (video_register_device(vfd, type, -1) < 0) { 530 if (err < 0) {
539 ERR(("cannot register v4l2 device. skipping.\n")); 531 ERR(("cannot register v4l2 device. skipping.\n"));
540 video_device_release(vfd); 532 video_device_release(vfd);
541 return -1; 533 return err;
542 } 534 }
543 535
544 if( VFL_TYPE_GRABBER == type ) { 536 if( VFL_TYPE_GRABBER == type ) {
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 47fee05eaefb..91b7a4def46c 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -97,172 +97,13 @@ struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
97 return NULL; 97 return NULL;
98} 98}
99 99
100static int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f) 100static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f);
101{
102 struct saa7146_dev *dev = fh->dev;
103 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
104
105 switch (f->type) {
106 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
107 f->fmt.pix = fh->video_fmt;
108 return 0;
109 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
110 f->fmt.win = fh->ov.win;
111 return 0;
112 case V4L2_BUF_TYPE_VBI_CAPTURE:
113 {
114 f->fmt.vbi = fh->vbi_fmt;
115 return 0;
116 }
117 default:
118 DEB_D(("invalid format type '%d'.\n",f->type));
119 return -EINVAL;
120 }
121}
122
123static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
124{
125 struct saa7146_vv *vv = dev->vv_data;
126 enum v4l2_field field;
127 int maxw, maxh;
128
129 DEB_EE(("dev:%p\n",dev));
130
131 if (NULL == vv->ov_fb.base) {
132 DEB_D(("no fb base set.\n"));
133 return -EINVAL;
134 }
135 if (NULL == vv->ov_fmt) {
136 DEB_D(("no fb fmt set.\n"));
137 return -EINVAL;
138 }
139 if (win->w.width < 48 || win->w.height < 32) {
140 DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
141 return -EINVAL;
142 }
143 if (win->clipcount > 16) {
144 DEB_D(("clipcount too big.\n"));
145 return -EINVAL;
146 }
147
148 field = win->field;
149 maxw = vv->standard->h_max_out;
150 maxh = vv->standard->v_max_out;
151
152 if (V4L2_FIELD_ANY == field) {
153 field = (win->w.height > maxh/2)
154 ? V4L2_FIELD_INTERLACED
155 : V4L2_FIELD_TOP;
156 }
157 switch (field) {
158 case V4L2_FIELD_TOP:
159 case V4L2_FIELD_BOTTOM:
160 case V4L2_FIELD_ALTERNATE:
161 maxh = maxh / 2;
162 break;
163 case V4L2_FIELD_INTERLACED:
164 break;
165 default: {
166 DEB_D(("no known field mode '%d'.\n",field));
167 return -EINVAL;
168 }
169 }
170
171 win->field = field;
172 if (win->w.width > maxw)
173 win->w.width = maxw;
174 if (win->w.height > maxh)
175 win->w.height = maxh;
176
177 return 0;
178}
179
180static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
181{
182 struct saa7146_dev *dev = fh->dev;
183 struct saa7146_vv *vv = dev->vv_data;
184 int err;
185
186 switch (f->type) {
187 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
188 {
189 struct saa7146_format *fmt;
190 enum v4l2_field field;
191 int maxw, maxh;
192 int calc_bpl;
193
194 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
195
196 fmt = format_by_fourcc(dev,f->fmt.pix.pixelformat);
197 if (NULL == fmt) {
198 return -EINVAL;
199 }
200
201 field = f->fmt.pix.field;
202 maxw = vv->standard->h_max_out;
203 maxh = vv->standard->v_max_out;
204
205 if (V4L2_FIELD_ANY == field) {
206 field = (f->fmt.pix.height > maxh/2)
207 ? V4L2_FIELD_INTERLACED
208 : V4L2_FIELD_BOTTOM;
209 }
210 switch (field) {
211 case V4L2_FIELD_ALTERNATE: {
212 vv->last_field = V4L2_FIELD_TOP;
213 maxh = maxh / 2;
214 break;
215 }
216 case V4L2_FIELD_TOP:
217 case V4L2_FIELD_BOTTOM:
218 vv->last_field = V4L2_FIELD_INTERLACED;
219 maxh = maxh / 2;
220 break;
221 case V4L2_FIELD_INTERLACED:
222 vv->last_field = V4L2_FIELD_INTERLACED;
223 break;
224 default: {
225 DEB_D(("no known field mode '%d'.\n",field));
226 return -EINVAL;
227 }
228 }
229
230 f->fmt.pix.field = field;
231 if (f->fmt.pix.width > maxw)
232 f->fmt.pix.width = maxw;
233 if (f->fmt.pix.height > maxh)
234 f->fmt.pix.height = maxh;
235
236 calc_bpl = (f->fmt.pix.width * fmt->depth)/8;
237
238 if (f->fmt.pix.bytesperline < calc_bpl)
239 f->fmt.pix.bytesperline = calc_bpl;
240
241 if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */
242 f->fmt.pix.bytesperline = calc_bpl;
243
244 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
245 DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage));
246
247 return 0;
248 }
249 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
250 DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
251 err = try_win(dev,&f->fmt.win);
252 if (0 != err) {
253 return err;
254 }
255 return 0;
256 default:
257 DEB_EE(("unknown format type '%d'\n",f->type));
258 return -EINVAL;
259 }
260}
261 101
262int saa7146_start_preview(struct saa7146_fh *fh) 102int saa7146_start_preview(struct saa7146_fh *fh)
263{ 103{
264 struct saa7146_dev *dev = fh->dev; 104 struct saa7146_dev *dev = fh->dev;
265 struct saa7146_vv *vv = dev->vv_data; 105 struct saa7146_vv *vv = dev->vv_data;
106 struct v4l2_format fmt;
266 int ret = 0, err = 0; 107 int ret = 0, err = 0;
267 108
268 DEB_EE(("dev:%p, fh:%p\n",dev,fh)); 109 DEB_EE(("dev:%p, fh:%p\n",dev,fh));
@@ -294,12 +135,13 @@ int saa7146_start_preview(struct saa7146_fh *fh)
294 return -EBUSY; 135 return -EBUSY;
295 } 136 }
296 137
297 err = try_win(dev,&fh->ov.win); 138 fmt.fmt.win = fh->ov.win;
139 err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt);
298 if (0 != err) { 140 if (0 != err) {
299 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); 141 saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
300 return -EBUSY; 142 return -EBUSY;
301 } 143 }
302 144 fh->ov.win = fmt.fmt.win;
303 vv->ov_data = &fh->ov; 145 vv->ov_data = &fh->ov;
304 146
305 DEB_D(("%dx%d+%d+%d %s field=%s\n", 147 DEB_D(("%dx%d+%d+%d %s field=%s\n",
@@ -355,58 +197,6 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
355} 197}
356EXPORT_SYMBOL_GPL(saa7146_stop_preview); 198EXPORT_SYMBOL_GPL(saa7146_stop_preview);
357 199
358static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
359{
360 struct saa7146_dev *dev = fh->dev;
361 struct saa7146_vv *vv = dev->vv_data;
362
363 int err;
364
365 switch (f->type) {
366 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
367 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
368 if (IS_CAPTURE_ACTIVE(fh) != 0) {
369 DEB_EE(("streaming capture is active\n"));
370 return -EBUSY;
371 }
372 err = try_fmt(fh,f);
373 if (0 != err)
374 return err;
375 fh->video_fmt = f->fmt.pix;
376 DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat));
377 return 0;
378 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
379 DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
380 err = try_win(dev,&f->fmt.win);
381 if (0 != err)
382 return err;
383 mutex_lock(&dev->lock);
384 fh->ov.win = f->fmt.win;
385 fh->ov.nclips = f->fmt.win.clipcount;
386 if (fh->ov.nclips > 16)
387 fh->ov.nclips = 16;
388 if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) {
389 mutex_unlock(&dev->lock);
390 return -EFAULT;
391 }
392
393 /* fh->ov.fh is used to indicate that we have valid overlay informations, too */
394 fh->ov.fh = fh;
395
396 mutex_unlock(&dev->lock);
397
398 /* check if our current overlay is active */
399 if (IS_OVERLAY_ACTIVE(fh) != 0) {
400 saa7146_stop_preview(fh);
401 saa7146_start_preview(fh);
402 }
403 return 0;
404 default:
405 DEB_D(("unknown format type '%d'\n",f->type));
406 return -EINVAL;
407 }
408}
409
410/********************************************************************************/ 200/********************************************************************************/
411/* device controls */ 201/* device controls */
412 202
@@ -463,132 +253,6 @@ static struct v4l2_queryctrl* ctrl_by_id(int id)
463 return NULL; 253 return NULL;
464} 254}
465 255
466static int get_control(struct saa7146_fh *fh, struct v4l2_control *c)
467{
468 struct saa7146_dev *dev = fh->dev;
469 struct saa7146_vv *vv = dev->vv_data;
470
471 const struct v4l2_queryctrl* ctrl;
472 u32 value = 0;
473
474 ctrl = ctrl_by_id(c->id);
475 if (NULL == ctrl)
476 return -EINVAL;
477 switch (c->id) {
478 case V4L2_CID_BRIGHTNESS:
479 value = saa7146_read(dev, BCS_CTRL);
480 c->value = 0xff & (value >> 24);
481 DEB_D(("V4L2_CID_BRIGHTNESS: %d\n",c->value));
482 break;
483 case V4L2_CID_CONTRAST:
484 value = saa7146_read(dev, BCS_CTRL);
485 c->value = 0x7f & (value >> 16);
486 DEB_D(("V4L2_CID_CONTRAST: %d\n",c->value));
487 break;
488 case V4L2_CID_SATURATION:
489 value = saa7146_read(dev, BCS_CTRL);
490 c->value = 0x7f & (value >> 0);
491 DEB_D(("V4L2_CID_SATURATION: %d\n",c->value));
492 break;
493 case V4L2_CID_VFLIP:
494 c->value = vv->vflip;
495 DEB_D(("V4L2_CID_VFLIP: %d\n",c->value));
496 break;
497 case V4L2_CID_HFLIP:
498 c->value = vv->hflip;
499 DEB_D(("V4L2_CID_HFLIP: %d\n",c->value));
500 break;
501 default:
502 return -EINVAL;
503 }
504
505 return 0;
506}
507
508static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
509{
510 struct saa7146_dev *dev = fh->dev;
511 struct saa7146_vv *vv = dev->vv_data;
512
513 const struct v4l2_queryctrl* ctrl;
514
515 ctrl = ctrl_by_id(c->id);
516 if (NULL == ctrl) {
517 DEB_D(("unknown control %d\n",c->id));
518 return -EINVAL;
519 }
520
521 mutex_lock(&dev->lock);
522
523 switch (ctrl->type) {
524 case V4L2_CTRL_TYPE_BOOLEAN:
525 case V4L2_CTRL_TYPE_MENU:
526 case V4L2_CTRL_TYPE_INTEGER:
527 if (c->value < ctrl->minimum)
528 c->value = ctrl->minimum;
529 if (c->value > ctrl->maximum)
530 c->value = ctrl->maximum;
531 break;
532 default:
533 /* nothing */;
534 };
535
536 switch (c->id) {
537 case V4L2_CID_BRIGHTNESS: {
538 u32 value = saa7146_read(dev, BCS_CTRL);
539 value &= 0x00ffffff;
540 value |= (c->value << 24);
541 saa7146_write(dev, BCS_CTRL, value);
542 saa7146_write(dev, MC2, MASK_22 | MASK_06 );
543 break;
544 }
545 case V4L2_CID_CONTRAST: {
546 u32 value = saa7146_read(dev, BCS_CTRL);
547 value &= 0xff00ffff;
548 value |= (c->value << 16);
549 saa7146_write(dev, BCS_CTRL, value);
550 saa7146_write(dev, MC2, MASK_22 | MASK_06 );
551 break;
552 }
553 case V4L2_CID_SATURATION: {
554 u32 value = saa7146_read(dev, BCS_CTRL);
555 value &= 0xffffff00;
556 value |= (c->value << 0);
557 saa7146_write(dev, BCS_CTRL, value);
558 saa7146_write(dev, MC2, MASK_22 | MASK_06 );
559 break;
560 }
561 case V4L2_CID_HFLIP:
562 /* fixme: we can support changing VFLIP and HFLIP here... */
563 if (IS_CAPTURE_ACTIVE(fh) != 0) {
564 DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
565 mutex_unlock(&dev->lock);
566 return -EINVAL;
567 }
568 vv->hflip = c->value;
569 break;
570 case V4L2_CID_VFLIP:
571 if (IS_CAPTURE_ACTIVE(fh) != 0) {
572 DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
573 mutex_unlock(&dev->lock);
574 return -EINVAL;
575 }
576 vv->vflip = c->value;
577 break;
578 default: {
579 mutex_unlock(&dev->lock);
580 return -EINVAL;
581 }
582 }
583 mutex_unlock(&dev->lock);
584
585 if (IS_OVERLAY_ACTIVE(fh) != 0) {
586 saa7146_stop_preview(fh);
587 saa7146_start_preview(fh);
588 }
589 return 0;
590}
591
592/********************************************************************************/ 256/********************************************************************************/
593/* common pagetable functions */ 257/* common pagetable functions */
594 258
@@ -829,231 +493,451 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
829 return 0; 493 return 0;
830} 494}
831 495
832/* 496static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
833 * This function is _not_ called directly, but from 497{
834 * video_generic_ioctl (and maybe others). userspace 498 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
835 * copying is done already, arg is a kernel pointer. 499
836 */ 500 strcpy((char *)cap->driver, "saa7146 v4l2");
501 strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
502 sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
503 cap->version = SAA7146_VERSION_CODE;
504 cap->capabilities =
505 V4L2_CAP_VIDEO_CAPTURE |
506 V4L2_CAP_VIDEO_OVERLAY |
507 V4L2_CAP_READWRITE |
508 V4L2_CAP_STREAMING;
509 cap->capabilities |= dev->ext_vv_data->capabilities;
510 return 0;
511}
837 512
838long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) 513static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
839{ 514{
840 struct saa7146_fh *fh = file->private_data; 515 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
841 struct saa7146_dev *dev = fh->dev;
842 struct saa7146_vv *vv = dev->vv_data; 516 struct saa7146_vv *vv = dev->vv_data;
843 517
844 long err = 0; 518 *fb = vv->ov_fb;
845 int result = 0, ee = 0; 519 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
520 return 0;
521}
522
523static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
524{
525 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
526 struct saa7146_vv *vv = dev->vv_data;
527 struct saa7146_format *fmt;
846 528
847 struct saa7146_use_ops *ops; 529 DEB_EE(("VIDIOC_S_FBUF\n"));
848 struct videobuf_queue *q;
849 530
850 /* check if extension handles the command */ 531 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
851 for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) { 532 return -EPERM;
852 if( cmd == dev->ext_vv_data->ioctls[ee].cmd ) 533
853 break; 534 /* check args */
535 fmt = format_by_fourcc(dev, fb->fmt.pixelformat);
536 if (NULL == fmt)
537 return -EINVAL;
538
539 /* planar formats are not allowed for overlay video, clipping and video dma would clash */
540 if (fmt->flags & FORMAT_IS_PLANAR)
541 DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
542 (char *)&fmt->pixelformat));
543
544 /* check if overlay is running */
545 if (IS_OVERLAY_ACTIVE(fh) != 0) {
546 if (vv->video_fh != fh) {
547 DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
548 return -EBUSY;
549 }
854 } 550 }
855 551
856 if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { 552 mutex_lock(&dev->lock);
857 DEB_D(("extension handles ioctl exclusive.\n")); 553
858 result = dev->ext_vv_data->ioctl(fh, cmd, arg); 554 /* ok, accept it */
859 return result; 555 vv->ov_fb = *fb;
556 vv->ov_fmt = fmt;
557 if (0 == vv->ov_fb.fmt.bytesperline)
558 vv->ov_fb.fmt.bytesperline =
559 vv->ov_fb.fmt.width * fmt->depth / 8;
560
561 mutex_unlock(&dev->lock);
562 return 0;
563}
564
565static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
566{
567 if (f->index >= NUM_FORMATS)
568 return -EINVAL;
569 strlcpy((char *)f->description, formats[f->index].name,
570 sizeof(f->description));
571 f->pixelformat = formats[f->index].pixelformat;
572 return 0;
573}
574
575static int vidioc_enum_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_fmtdesc *f)
576{
577 return vidioc_enum_fmt_vid_cap(file, fh, f);
578}
579
580static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
581{
582 const struct v4l2_queryctrl *ctrl;
583
584 if ((c->id < V4L2_CID_BASE ||
585 c->id >= V4L2_CID_LASTP1) &&
586 (c->id < V4L2_CID_PRIVATE_BASE ||
587 c->id >= V4L2_CID_PRIVATE_LASTP1))
588 return -EINVAL;
589
590 ctrl = ctrl_by_id(c->id);
591 if (ctrl == NULL)
592 return -EINVAL;
593
594 DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
595 *c = *ctrl;
596 return 0;
597}
598
599static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
600{
601 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
602 struct saa7146_vv *vv = dev->vv_data;
603 const struct v4l2_queryctrl *ctrl;
604 u32 value = 0;
605
606 ctrl = ctrl_by_id(c->id);
607 if (NULL == ctrl)
608 return -EINVAL;
609 switch (c->id) {
610 case V4L2_CID_BRIGHTNESS:
611 value = saa7146_read(dev, BCS_CTRL);
612 c->value = 0xff & (value >> 24);
613 DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
614 break;
615 case V4L2_CID_CONTRAST:
616 value = saa7146_read(dev, BCS_CTRL);
617 c->value = 0x7f & (value >> 16);
618 DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
619 break;
620 case V4L2_CID_SATURATION:
621 value = saa7146_read(dev, BCS_CTRL);
622 c->value = 0x7f & (value >> 0);
623 DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
624 break;
625 case V4L2_CID_VFLIP:
626 c->value = vv->vflip;
627 DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
628 break;
629 case V4L2_CID_HFLIP:
630 c->value = vv->hflip;
631 DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
632 break;
633 default:
634 return -EINVAL;
860 } 635 }
861 if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) { 636 return 0;
862 DEB_D(("extension handles ioctl before.\n")); 637}
863 result = dev->ext_vv_data->ioctl(fh, cmd, arg); 638
864 if( -EAGAIN != result ) { 639static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
865 return result; 640{
866 } 641 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
642 struct saa7146_vv *vv = dev->vv_data;
643 const struct v4l2_queryctrl *ctrl;
644
645 ctrl = ctrl_by_id(c->id);
646 if (NULL == ctrl) {
647 DEB_D(("unknown control %d\n", c->id));
648 return -EINVAL;
867 } 649 }
868 650
869 /* fixme: add handle "after" case (is it still needed?) */ 651 mutex_lock(&dev->lock);
652
653 switch (ctrl->type) {
654 case V4L2_CTRL_TYPE_BOOLEAN:
655 case V4L2_CTRL_TYPE_MENU:
656 case V4L2_CTRL_TYPE_INTEGER:
657 if (c->value < ctrl->minimum)
658 c->value = ctrl->minimum;
659 if (c->value > ctrl->maximum)
660 c->value = ctrl->maximum;
661 break;
662 default:
663 /* nothing */;
664 }
870 665
871 switch (fh->type) { 666 switch (c->id) {
872 case V4L2_BUF_TYPE_VIDEO_CAPTURE: { 667 case V4L2_CID_BRIGHTNESS: {
873 ops = &saa7146_video_uops; 668 u32 value = saa7146_read(dev, BCS_CTRL);
874 q = &fh->video_q; 669 value &= 0x00ffffff;
670 value |= (c->value << 24);
671 saa7146_write(dev, BCS_CTRL, value);
672 saa7146_write(dev, MC2, MASK_22 | MASK_06);
673 break;
674 }
675 case V4L2_CID_CONTRAST: {
676 u32 value = saa7146_read(dev, BCS_CTRL);
677 value &= 0xff00ffff;
678 value |= (c->value << 16);
679 saa7146_write(dev, BCS_CTRL, value);
680 saa7146_write(dev, MC2, MASK_22 | MASK_06);
681 break;
682 }
683 case V4L2_CID_SATURATION: {
684 u32 value = saa7146_read(dev, BCS_CTRL);
685 value &= 0xffffff00;
686 value |= (c->value << 0);
687 saa7146_write(dev, BCS_CTRL, value);
688 saa7146_write(dev, MC2, MASK_22 | MASK_06);
875 break; 689 break;
690 }
691 case V4L2_CID_HFLIP:
692 /* fixme: we can support changing VFLIP and HFLIP here... */
693 if (IS_CAPTURE_ACTIVE(fh) != 0) {
694 DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
695 mutex_unlock(&dev->lock);
696 return -EINVAL;
876 } 697 }
877 case V4L2_BUF_TYPE_VBI_CAPTURE: { 698 vv->hflip = c->value;
878 ops = &saa7146_vbi_uops;
879 q = &fh->vbi_q;
880 break; 699 break;
700 case V4L2_CID_VFLIP:
701 if (IS_CAPTURE_ACTIVE(fh) != 0) {
702 DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
703 mutex_unlock(&dev->lock);
704 return -EINVAL;
881 } 705 }
706 vv->vflip = c->value;
707 break;
882 default: 708 default:
883 BUG(); 709 mutex_unlock(&dev->lock);
884 return 0; 710 return -EINVAL;
885 } 711 }
712 mutex_unlock(&dev->lock);
886 713
887 switch (cmd) { 714 if (IS_OVERLAY_ACTIVE(fh) != 0) {
888 case VIDIOC_QUERYCAP: 715 saa7146_stop_preview(fh);
889 { 716 saa7146_start_preview(fh);
890 struct v4l2_capability *cap = arg;
891 memset(cap,0,sizeof(*cap));
892
893 DEB_EE(("VIDIOC_QUERYCAP\n"));
894
895 strcpy((char *)cap->driver, "saa7146 v4l2");
896 strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
897 sprintf((char *)cap->bus_info,"PCI:%s", pci_name(dev->pci));
898 cap->version = SAA7146_VERSION_CODE;
899 cap->capabilities =
900 V4L2_CAP_VIDEO_CAPTURE |
901 V4L2_CAP_VIDEO_OVERLAY |
902 V4L2_CAP_READWRITE |
903 V4L2_CAP_STREAMING;
904 cap->capabilities |= dev->ext_vv_data->capabilities;
905 return 0;
906 } 717 }
907 case VIDIOC_G_FBUF: 718 return 0;
908 { 719}
909 struct v4l2_framebuffer *fb = arg;
910 720
911 DEB_EE(("VIDIOC_G_FBUF\n")); 721static int vidioc_g_parm(struct file *file, void *fh,
722 struct v4l2_streamparm *parm)
723{
724 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
725 return -EINVAL;
726 parm->parm.capture.readbuffers = 1;
727 /* fixme: only for PAL! */
728 parm->parm.capture.timeperframe.numerator = 1;
729 parm->parm.capture.timeperframe.denominator = 25;
730 return 0;
731}
912 732
913 *fb = vv->ov_fb; 733static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
914 fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; 734{
915 return 0; 735 f->fmt.pix = ((struct saa7146_fh *)fh)->video_fmt;
916 } 736 return 0;
917 case VIDIOC_S_FBUF: 737}
918 {
919 struct v4l2_framebuffer *fb = arg;
920 struct saa7146_format *fmt;
921 738
922 DEB_EE(("VIDIOC_S_FBUF\n")); 739static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
740{
741 f->fmt.win = ((struct saa7146_fh *)fh)->ov.win;
742 return 0;
743}
923 744
924 if(!capable(CAP_SYS_ADMIN) && 745static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
925 !capable(CAP_SYS_RAWIO)) 746{
926 return -EPERM; 747 f->fmt.vbi = ((struct saa7146_fh *)fh)->vbi_fmt;
748 return 0;
749}
927 750
928 /* check args */ 751static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
929 fmt = format_by_fourcc(dev,fb->fmt.pixelformat); 752{
930 if (NULL == fmt) { 753 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
931 return -EINVAL; 754 struct saa7146_vv *vv = dev->vv_data;
932 } 755 struct saa7146_format *fmt;
756 enum v4l2_field field;
757 int maxw, maxh;
758 int calc_bpl;
933 759
934 /* planar formats are not allowed for overlay video, clipping and video dma would clash */ 760 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
935 if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
936 DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
937 }
938 761
939 /* check if overlay is running */ 762 fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
940 if (IS_OVERLAY_ACTIVE(fh) != 0) { 763 if (NULL == fmt)
941 if (vv->video_fh != fh) { 764 return -EINVAL;
942 DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
943 return -EBUSY;
944 }
945 }
946 765
947 mutex_lock(&dev->lock); 766 field = f->fmt.pix.field;
767 maxw = vv->standard->h_max_out;
768 maxh = vv->standard->v_max_out;
948 769
949 /* ok, accept it */ 770 if (V4L2_FIELD_ANY == field) {
950 vv->ov_fb = *fb; 771 field = (f->fmt.pix.height > maxh / 2)
951 vv->ov_fmt = fmt; 772 ? V4L2_FIELD_INTERLACED
952 if (0 == vv->ov_fb.fmt.bytesperline) 773 : V4L2_FIELD_BOTTOM;
953 vv->ov_fb.fmt.bytesperline = 774 }
954 vv->ov_fb.fmt.width*fmt->depth/8; 775 switch (field) {
776 case V4L2_FIELD_ALTERNATE:
777 vv->last_field = V4L2_FIELD_TOP;
778 maxh = maxh / 2;
779 break;
780 case V4L2_FIELD_TOP:
781 case V4L2_FIELD_BOTTOM:
782 vv->last_field = V4L2_FIELD_INTERLACED;
783 maxh = maxh / 2;
784 break;
785 case V4L2_FIELD_INTERLACED:
786 vv->last_field = V4L2_FIELD_INTERLACED;
787 break;
788 default:
789 DEB_D(("no known field mode '%d'.\n", field));
790 return -EINVAL;
791 }
955 792
956 mutex_unlock(&dev->lock); 793 f->fmt.pix.field = field;
794 if (f->fmt.pix.width > maxw)
795 f->fmt.pix.width = maxw;
796 if (f->fmt.pix.height > maxh)
797 f->fmt.pix.height = maxh;
957 798
958 return 0; 799 calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
959 }
960 case VIDIOC_ENUM_FMT:
961 {
962 struct v4l2_fmtdesc *f = arg;
963
964 switch (f->type) {
965 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
966 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
967 if (f->index >= NUM_FORMATS)
968 return -EINVAL;
969 strlcpy((char *)f->description, formats[f->index].name,
970 sizeof(f->description));
971 f->pixelformat = formats[f->index].pixelformat;
972 f->flags = 0;
973 memset(f->reserved, 0, sizeof(f->reserved));
974 break;
975 default:
976 return -EINVAL;
977 }
978 800
979 DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index)); 801 if (f->fmt.pix.bytesperline < calc_bpl)
980 return 0; 802 f->fmt.pix.bytesperline = calc_bpl;
981 }
982 case VIDIOC_QUERYCTRL:
983 {
984 const struct v4l2_queryctrl *ctrl;
985 struct v4l2_queryctrl *c = arg;
986 803
987 if ((c->id < V4L2_CID_BASE || 804 if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
988 c->id >= V4L2_CID_LASTP1) && 805 f->fmt.pix.bytesperline = calc_bpl;
989 (c->id < V4L2_CID_PRIVATE_BASE ||
990 c->id >= V4L2_CID_PRIVATE_LASTP1))
991 return -EINVAL;
992 806
993 ctrl = ctrl_by_id(c->id); 807 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
994 if( NULL == ctrl ) { 808 DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
995 return -EINVAL; 809 f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
996/*
997 c->flags = V4L2_CTRL_FLAG_DISABLED;
998 return 0;
999*/
1000 }
1001 810
1002 DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id)); 811 return 0;
1003 *c = *ctrl; 812}
1004 return 0; 813
814
815static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
816{
817 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
818 struct saa7146_vv *vv = dev->vv_data;
819 struct v4l2_window *win = &f->fmt.win;
820 enum v4l2_field field;
821 int maxw, maxh;
822
823 DEB_EE(("dev:%p\n", dev));
824
825 if (NULL == vv->ov_fb.base) {
826 DEB_D(("no fb base set.\n"));
827 return -EINVAL;
1005 } 828 }
1006 case VIDIOC_G_CTRL: { 829 if (NULL == vv->ov_fmt) {
1007 DEB_EE(("VIDIOC_G_CTRL\n")); 830 DEB_D(("no fb fmt set.\n"));
1008 return get_control(fh,arg); 831 return -EINVAL;
1009 } 832 }
1010 case VIDIOC_S_CTRL: 833 if (win->w.width < 48 || win->w.height < 32) {
1011 { 834 DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
1012 DEB_EE(("VIDIOC_S_CTRL\n")); 835 return -EINVAL;
1013 err = set_control(fh,arg);
1014 return err;
1015 } 836 }
1016 case VIDIOC_G_PARM: 837 if (win->clipcount > 16) {
1017 { 838 DEB_D(("clipcount too big.\n"));
1018 struct v4l2_streamparm *parm = arg; 839 return -EINVAL;
1019 if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) {
1020 return -EINVAL;
1021 }
1022 memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm));
1023 parm->parm.capture.readbuffers = 1;
1024 // fixme: only for PAL!
1025 parm->parm.capture.timeperframe.numerator = 1;
1026 parm->parm.capture.timeperframe.denominator = 25;
1027 return 0;
1028 } 840 }
1029 case VIDIOC_G_FMT: 841
1030 { 842 field = win->field;
1031 struct v4l2_format *f = arg; 843 maxw = vv->standard->h_max_out;
1032 DEB_EE(("VIDIOC_G_FMT\n")); 844 maxh = vv->standard->v_max_out;
1033 return g_fmt(fh,f); 845
846 if (V4L2_FIELD_ANY == field) {
847 field = (win->w.height > maxh / 2)
848 ? V4L2_FIELD_INTERLACED
849 : V4L2_FIELD_TOP;
850 }
851 switch (field) {
852 case V4L2_FIELD_TOP:
853 case V4L2_FIELD_BOTTOM:
854 case V4L2_FIELD_ALTERNATE:
855 maxh = maxh / 2;
856 break;
857 case V4L2_FIELD_INTERLACED:
858 break;
859 default:
860 DEB_D(("no known field mode '%d'.\n", field));
861 return -EINVAL;
1034 } 862 }
1035 case VIDIOC_S_FMT: 863
1036 { 864 win->field = field;
1037 struct v4l2_format *f = arg; 865 if (win->w.width > maxw)
1038 DEB_EE(("VIDIOC_S_FMT\n")); 866 win->w.width = maxw;
1039 return s_fmt(fh,f); 867 if (win->w.height > maxh)
868 win->w.height = maxh;
869
870 return 0;
871}
872
873static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
874{
875 struct saa7146_fh *fh = __fh;
876 struct saa7146_dev *dev = fh->dev;
877 struct saa7146_vv *vv = dev->vv_data;
878 int err;
879
880 DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
881 if (IS_CAPTURE_ACTIVE(fh) != 0) {
882 DEB_EE(("streaming capture is active\n"));
883 return -EBUSY;
1040 } 884 }
1041 case VIDIOC_TRY_FMT: 885 err = vidioc_try_fmt_vid_cap(file, fh, f);
1042 { 886 if (0 != err)
1043 struct v4l2_format *f = arg; 887 return err;
1044 DEB_EE(("VIDIOC_TRY_FMT\n")); 888 fh->video_fmt = f->fmt.pix;
1045 return try_fmt(fh,f); 889 DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
890 return 0;
891}
892
893static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
894{
895 struct saa7146_fh *fh = __fh;
896 struct saa7146_dev *dev = fh->dev;
897 struct saa7146_vv *vv = dev->vv_data;
898 int err;
899
900 DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
901 err = vidioc_try_fmt_vid_overlay(file, fh, f);
902 if (0 != err)
903 return err;
904 mutex_lock(&dev->lock);
905 fh->ov.win = f->fmt.win;
906 fh->ov.nclips = f->fmt.win.clipcount;
907 if (fh->ov.nclips > 16)
908 fh->ov.nclips = 16;
909 if (copy_from_user(fh->ov.clips, f->fmt.win.clips,
910 sizeof(struct v4l2_clip) * fh->ov.nclips)) {
911 mutex_unlock(&dev->lock);
912 return -EFAULT;
1046 } 913 }
1047 case VIDIOC_G_STD: 914
1048 { 915 /* fh->ov.fh is used to indicate that we have valid overlay informations, too */
1049 v4l2_std_id *id = arg; 916 fh->ov.fh = fh;
1050 DEB_EE(("VIDIOC_G_STD\n")); 917
1051 *id = vv->standard->id; 918 mutex_unlock(&dev->lock);
1052 return 0; 919
920 /* check if our current overlay is active */
921 if (IS_OVERLAY_ACTIVE(fh) != 0) {
922 saa7146_stop_preview(fh);
923 saa7146_start_preview(fh);
1053 } 924 }
925 return 0;
926}
927
928static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
929{
930 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
931 struct saa7146_vv *vv = dev->vv_data;
932
933 *norm = vv->standard->id;
934 return 0;
935}
936
1054 /* the saa7146 supfhrts (used in conjunction with the saa7111a for example) 937 /* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
1055 PAL / NTSC / SECAM. if your hardware does not (or does more) 938 PAL / NTSC / SECAM. if your hardware does not (or does more)
1056 -- override this function in your extension */ 939 -- override this function in your extension */
940/*
1057 case VIDIOC_ENUMSTD: 941 case VIDIOC_ENUMSTD:
1058 { 942 {
1059 struct v4l2_standard *e = arg; 943 struct v4l2_standard *e = arg;
@@ -1066,162 +950,228 @@ long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
1066 } 950 }
1067 return -EINVAL; 951 return -EINVAL;
1068 } 952 }
1069 case VIDIOC_S_STD: 953 */
1070 {
1071 v4l2_std_id *id = arg;
1072 int found = 0;
1073 int i;
1074
1075 DEB_EE(("VIDIOC_S_STD\n"));
1076 954
1077 if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) { 955static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
1078 DEB_D(("cannot change video standard while streaming capture is active\n")); 956{
1079 return -EBUSY; 957 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
1080 } 958 struct saa7146_vv *vv = dev->vv_data;
959 int found = 0;
960 int err, i;
1081 961
1082 if ((vv->video_status & STATUS_OVERLAY) != 0) { 962 DEB_EE(("VIDIOC_S_STD\n"));
1083 vv->ov_suspend = vv->video_fh;
1084 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
1085 if (0 != err) {
1086 DEB_D(("suspending video failed. aborting\n"));
1087 return err;
1088 }
1089 }
1090 963
1091 mutex_lock(&dev->lock); 964 if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
965 DEB_D(("cannot change video standard while streaming capture is active\n"));
966 return -EBUSY;
967 }
1092 968
1093 for(i = 0; i < dev->ext_vv_data->num_stds; i++) 969 if ((vv->video_status & STATUS_OVERLAY) != 0) {
1094 if (*id & dev->ext_vv_data->stds[i].id) 970 vv->ov_suspend = vv->video_fh;
1095 break; 971 err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
1096 if (i != dev->ext_vv_data->num_stds) { 972 if (0 != err) {
1097 vv->standard = &dev->ext_vv_data->stds[i]; 973 DEB_D(("suspending video failed. aborting\n"));
1098 if( NULL != dev->ext_vv_data->std_callback ) 974 return err;
1099 dev->ext_vv_data->std_callback(dev, vv->standard);
1100 found = 1;
1101 } 975 }
976 }
1102 977
1103 mutex_unlock(&dev->lock); 978 mutex_lock(&dev->lock);
1104 979
1105 if (vv->ov_suspend != NULL) { 980 for (i = 0; i < dev->ext_vv_data->num_stds; i++)
1106 saa7146_start_preview(vv->ov_suspend); 981 if (*id & dev->ext_vv_data->stds[i].id)
1107 vv->ov_suspend = NULL; 982 break;
1108 } 983 if (i != dev->ext_vv_data->num_stds) {
984 vv->standard = &dev->ext_vv_data->stds[i];
985 if (NULL != dev->ext_vv_data->std_callback)
986 dev->ext_vv_data->std_callback(dev, vv->standard);
987 found = 1;
988 }
1109 989
1110 if( 0 == found ) { 990 mutex_unlock(&dev->lock);
1111 DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
1112 return -EINVAL;
1113 }
1114 991
1115 DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name)); 992 if (vv->ov_suspend != NULL) {
1116 return 0; 993 saa7146_start_preview(vv->ov_suspend);
994 vv->ov_suspend = NULL;
1117 } 995 }
1118 case VIDIOC_OVERLAY:
1119 {
1120 int on = *(int *)arg;
1121 996
1122 DEB_D(("VIDIOC_OVERLAY on:%d\n",on)); 997 if (!found) {
1123 if (on != 0) { 998 DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
1124 err = saa7146_start_preview(fh); 999 return -EINVAL;
1125 } else {
1126 err = saa7146_stop_preview(fh);
1127 }
1128 return err;
1129 }
1130 case VIDIOC_REQBUFS: {
1131 struct v4l2_requestbuffers *req = arg;
1132 DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
1133 return videobuf_reqbufs(q,req);
1134 }
1135 case VIDIOC_QUERYBUF: {
1136 struct v4l2_buffer *buf = arg;
1137 DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
1138 return videobuf_querybuf(q,buf);
1139 }
1140 case VIDIOC_QBUF: {
1141 struct v4l2_buffer *buf = arg;
1142 int ret = 0;
1143 ret = videobuf_qbuf(q,buf);
1144 DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
1145 return ret;
1146 }
1147 case VIDIOC_DQBUF: {
1148 struct v4l2_buffer *buf = arg;
1149 int ret = 0;
1150 ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK);
1151 DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
1152 return ret;
1153 } 1000 }
1154 case VIDIOC_STREAMON: {
1155 int *type = arg;
1156 DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
1157 1001
1158 err = video_begin(fh); 1002 DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
1159 if( 0 != err) { 1003 return 0;
1160 return err; 1004}
1161 }
1162 err = videobuf_streamon(q);
1163 return err;
1164 }
1165 case VIDIOC_STREAMOFF: {
1166 int *type = arg;
1167 1005
1168 DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type)); 1006static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
1007{
1008 int err;
1169 1009
1170 /* ugly: we need to copy some checks from video_end(), 1010 DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
1171 because videobuf_streamoff() relies on the capture running. 1011 if (on)
1172 check and fix this */ 1012 err = saa7146_start_preview(fh);
1173 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) { 1013 else
1174 DEB_S(("not capturing.\n")); 1014 err = saa7146_stop_preview(fh);
1175 return 0; 1015 return err;
1176 } 1016}
1177 1017
1178 if (vv->video_fh != fh) { 1018static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
1179 DEB_S(("capturing, but in another open.\n")); 1019{
1180 return -EBUSY; 1020 struct saa7146_fh *fh = __fh;
1181 }
1182 1021
1183 err = videobuf_streamoff(q); 1022 if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1184 if (0 != err) { 1023 return videobuf_reqbufs(&fh->video_q, b);
1185 DEB_D(("warning: videobuf_streamoff() failed.\n")); 1024 if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1186 video_end(fh, file); 1025 return videobuf_reqbufs(&fh->vbi_q, b);
1187 } else { 1026 return -EINVAL;
1188 err = video_end(fh, file); 1027}
1189 } 1028
1190 return err; 1029static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
1191 } 1030{
1192#ifdef CONFIG_VIDEO_V4L1_COMPAT 1031 struct saa7146_fh *fh = __fh;
1193 case VIDIOCGMBUF:
1194 {
1195 struct video_mbuf *mbuf = arg;
1196 int i;
1197 1032
1198 /* fixme: number of capture buffers and sizes for v4l apps */ 1033 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1199 int gbuffers = 2; 1034 return videobuf_querybuf(&fh->video_q, buf);
1200 int gbufsize = 768*576*4; 1035 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1036 return videobuf_querybuf(&fh->vbi_q, buf);
1037 return -EINVAL;
1038}
1201 1039
1202 DEB_D(("VIDIOCGMBUF \n")); 1040static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
1041{
1042 struct saa7146_fh *fh = __fh;
1203 1043
1204 q = &fh->video_q; 1044 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1205 err = videobuf_mmap_setup(q,gbuffers,gbufsize, 1045 return videobuf_qbuf(&fh->video_q, buf);
1206 V4L2_MEMORY_MMAP); 1046 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1207 if (err < 0) 1047 return videobuf_qbuf(&fh->vbi_q, buf);
1208 return err; 1048 return -EINVAL;
1049}
1050
1051static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
1052{
1053 struct saa7146_fh *fh = __fh;
1054
1055 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1056 return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
1057 if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1058 return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
1059 return -EINVAL;
1060}
1061
1062static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
1063{
1064 struct saa7146_fh *fh = __fh;
1065 int err;
1066
1067 DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
1068
1069 err = video_begin(fh);
1070 if (err)
1071 return err;
1072 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1073 return videobuf_streamon(&fh->video_q);
1074 if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
1075 return videobuf_streamon(&fh->vbi_q);
1076 return -EINVAL;
1077}
1078
1079static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
1080{
1081 struct saa7146_fh *fh = __fh;
1082 struct saa7146_dev *dev = fh->dev;
1083 struct saa7146_vv *vv = dev->vv_data;
1084 int err;
1085
1086 DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
1209 1087
1210 gbuffers = err; 1088 /* ugly: we need to copy some checks from video_end(),
1211 memset(mbuf,0,sizeof(*mbuf)); 1089 because videobuf_streamoff() relies on the capture running.
1212 mbuf->frames = gbuffers; 1090 check and fix this */
1213 mbuf->size = gbuffers * gbufsize; 1091 if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
1214 for (i = 0; i < gbuffers; i++) 1092 DEB_S(("not capturing.\n"));
1215 mbuf->offsets[i] = i * gbufsize;
1216 return 0; 1093 return 0;
1217 } 1094 }
1218#endif 1095
1219 default: 1096 if (vv->video_fh != fh) {
1220 return v4l_compat_translate_ioctl(file, cmd, arg, 1097 DEB_S(("capturing, but in another open.\n"));
1221 saa7146_video_do_ioctl); 1098 return -EBUSY;
1222 } 1099 }
1100
1101 err = -EINVAL;
1102 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1103 err = videobuf_streamoff(&fh->video_q);
1104 else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
1105 err = videobuf_streamoff(&fh->vbi_q);
1106 if (0 != err) {
1107 DEB_D(("warning: videobuf_streamoff() failed.\n"));
1108 video_end(fh, file);
1109 } else {
1110 err = video_end(fh, file);
1111 }
1112 return err;
1113}
1114
1115#ifdef CONFIG_VIDEO_V4L1_COMPAT
1116static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf)
1117{
1118 struct saa7146_fh *fh = __fh;
1119 struct videobuf_queue *q = &fh->video_q;
1120 int err, i;
1121
1122 /* fixme: number of capture buffers and sizes for v4l apps */
1123 int gbuffers = 2;
1124 int gbufsize = 768 * 576 * 4;
1125
1126 DEB_D(("VIDIOCGMBUF \n"));
1127
1128 q = &fh->video_q;
1129 err = videobuf_mmap_setup(q, gbuffers, gbufsize,
1130 V4L2_MEMORY_MMAP);
1131 if (err < 0)
1132 return err;
1133
1134 gbuffers = err;
1135 memset(mbuf, 0, sizeof(*mbuf));
1136 mbuf->frames = gbuffers;
1137 mbuf->size = gbuffers * gbufsize;
1138 for (i = 0; i < gbuffers; i++)
1139 mbuf->offsets[i] = i * gbufsize;
1223 return 0; 1140 return 0;
1224} 1141}
1142#endif
1143
1144const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
1145 .vidioc_querycap = vidioc_querycap,
1146 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1147 .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
1148 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1149 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1150 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1151 .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
1152 .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
1153 .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
1154 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
1155
1156 .vidioc_overlay = vidioc_overlay,
1157 .vidioc_g_fbuf = vidioc_g_fbuf,
1158 .vidioc_s_fbuf = vidioc_s_fbuf,
1159 .vidioc_reqbufs = vidioc_reqbufs,
1160 .vidioc_querybuf = vidioc_querybuf,
1161 .vidioc_qbuf = vidioc_qbuf,
1162 .vidioc_dqbuf = vidioc_dqbuf,
1163 .vidioc_g_std = vidioc_g_std,
1164 .vidioc_s_std = vidioc_s_std,
1165 .vidioc_queryctrl = vidioc_queryctrl,
1166 .vidioc_g_ctrl = vidioc_g_ctrl,
1167 .vidioc_s_ctrl = vidioc_s_ctrl,
1168 .vidioc_streamon = vidioc_streamon,
1169 .vidioc_streamoff = vidioc_streamoff,
1170 .vidioc_g_parm = vidioc_g_parm,
1171#ifdef CONFIG_VIDEO_V4L1_COMPAT
1172 .vidiocgmbuf = vidiocgmbuf,
1173#endif
1174};
1225 1175
1226/*********************************************************************************/ 1176/*********************************************************************************/
1227/* buffer handling functions */ 1177/* buffer handling functions */