aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Endriss <o.endriss@gmx.de>2006-01-09 15:21:37 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 15:21:37 -0500
commit5b0fa4fff17d944b6a0d4cb35d8e8b5ad0ac3669 (patch)
tree1e31c64267ffabe37c733a00e09b91ba4453651a
parentd312a46e5340be6a89c662ac483230c0737148c9 (diff)
V4L/DVB (3325): WSS output interface for av7110
- Implemented v4l2 api for sliced vbi data output to pass WSS data from userspace to the av7110 Signed-off-by: Oliver Endriss <o.endriss@gmx.de> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
-rw-r--r--drivers/media/common/saa7146_fops.c37
-rw-r--r--drivers/media/dvb/ttpci/av7110.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c116
-rw-r--r--include/media/saa7146_vv.h2
5 files changed, 149 insertions, 12 deletions
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index a9ff5b5af1cf..b614612be7b4 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -253,7 +253,10 @@ static int fops_open(struct inode *inode, struct file *file)
253 253
254 if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 254 if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
255 DEB_S(("initializing vbi...\n")); 255 DEB_S(("initializing vbi...\n"));
256 result = saa7146_vbi_uops.open(dev,file); 256 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
257 result = saa7146_vbi_uops.open(dev,file);
258 if (dev->ext_vv_data->vbi_fops.open)
259 dev->ext_vv_data->vbi_fops.open(inode, file);
257 } else { 260 } else {
258 DEB_S(("initializing video...\n")); 261 DEB_S(("initializing video...\n"));
259 result = saa7146_video_uops.open(dev,file); 262 result = saa7146_video_uops.open(dev,file);
@@ -289,7 +292,10 @@ static int fops_release(struct inode *inode, struct file *file)
289 return -ERESTARTSYS; 292 return -ERESTARTSYS;
290 293
291 if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 294 if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
292 saa7146_vbi_uops.release(dev,file); 295 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
296 saa7146_vbi_uops.release(dev,file);
297 if (dev->ext_vv_data->vbi_fops.release)
298 dev->ext_vv_data->vbi_fops.release(inode, file);
293 } else { 299 } else {
294 saa7146_video_uops.release(dev,file); 300 saa7146_video_uops.release(dev,file);
295 } 301 }
@@ -382,7 +388,10 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
382 } 388 }
383 case V4L2_BUF_TYPE_VBI_CAPTURE: { 389 case V4L2_BUF_TYPE_VBI_CAPTURE: {
384// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count)); 390// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
385 return saa7146_vbi_uops.read(file,data,count,ppos); 391 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
392 return saa7146_vbi_uops.read(file,data,count,ppos);
393 else
394 return -EINVAL;
386 } 395 }
387 break; 396 break;
388 default: 397 default:
@@ -391,12 +400,31 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
391 } 400 }
392} 401}
393 402
403static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
404{
405 struct saa7146_fh *fh = file->private_data;
406
407 switch (fh->type) {
408 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
409 return -EINVAL;
410 case V4L2_BUF_TYPE_VBI_CAPTURE:
411 if (fh->dev->ext_vv_data->vbi_fops.write)
412 return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
413 else
414 return -EINVAL;
415 default:
416 BUG();
417 return -EINVAL;
418 }
419}
420
394static struct file_operations video_fops = 421static struct file_operations video_fops =
395{ 422{
396 .owner = THIS_MODULE, 423 .owner = THIS_MODULE,
397 .open = fops_open, 424 .open = fops_open,
398 .release = fops_release, 425 .release = fops_release,
399 .read = fops_read, 426 .read = fops_read,
427 .write = fops_write,
400 .poll = fops_poll, 428 .poll = fops_poll,
401 .mmap = fops_mmap, 429 .mmap = fops_mmap,
402 .ioctl = fops_ioctl, 430 .ioctl = fops_ioctl,
@@ -468,7 +496,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
468 memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); 496 memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
469 497
470 saa7146_video_uops.init(dev,vv); 498 saa7146_video_uops.init(dev,vv);
471 saa7146_vbi_uops.init(dev,vv); 499 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
500 saa7146_vbi_uops.init(dev,vv);
472 501
473 dev->vv_data = vv; 502 dev->vv_data = vv;
474 dev->vv_callback = &vv_callback; 503 dev->vv_callback = &vv_callback;
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 6cf395e01d34..6ea30df2e823 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -229,6 +229,9 @@ struct av7110 {
229 struct dvb_video_events video_events; 229 struct dvb_video_events video_events;
230 video_size_t video_size; 230 video_size_t video_size;
231 231
232 u16 wssMode;
233 u16 wssData;
234
232 u32 ir_config; 235 u32 ir_config;
233 u32 ir_command; 236 u32 ir_command;
234 void (*ir_handler)(struct av7110 *av7110, u32 ircom); 237 void (*ir_handler)(struct av7110 *av7110, u32 ircom);
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 2a5e87ba1052..84b83299b8be 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -167,7 +167,8 @@ enum av7110_encoder_command {
167 LoadVidCode, 167 LoadVidCode,
168 SetMonitorType, 168 SetMonitorType,
169 SetPanScanType, 169 SetPanScanType,
170 SetFreezeMode 170 SetFreezeMode,
171 SetWSSConfig
171}; 172};
172 173
173enum av7110_rec_play_state { 174enum av7110_rec_play_state {
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index e3296b07caac..94cf38c7e8a8 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -490,6 +490,58 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
490 dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index); 490 dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
491 break; 491 break;
492 } 492 }
493 case VIDIOC_G_SLICED_VBI_CAP:
494 {
495 struct v4l2_sliced_vbi_cap *cap = arg;
496 dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
497 memset(cap, 0, sizeof *cap);
498 if (FW_VERSION(av7110->arm_app) >= 0x2623) {
499 cap->service_set = V4L2_SLICED_WSS_625;
500 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
501 }
502 break;
503 }
504 case VIDIOC_G_FMT:
505 {
506 struct v4l2_format *f = arg;
507 dprintk(2, "VIDIOC_G_FMT:\n");
508 if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
509 FW_VERSION(av7110->arm_app) < 0x2623)
510 return -EAGAIN; /* handled by core driver */
511 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
512 if (av7110->wssMode) {
513 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
514 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
515 f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
516 }
517 break;
518 }
519 case VIDIOC_S_FMT:
520 {
521 struct v4l2_format *f = arg;
522 dprintk(2, "VIDIOC_S_FMT\n");
523 if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
524 FW_VERSION(av7110->arm_app) < 0x2623)
525 return -EAGAIN; /* handled by core driver */
526 if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
527 f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
528 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
529 /* WSS controlled by firmware */
530 av7110->wssMode = 0;
531 av7110->wssData = 0;
532 return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
533 SetWSSConfig, 1, 0);
534 } else {
535 memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
536 f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
537 f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
538 f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
539 /* WSS controlled by userspace */
540 av7110->wssMode = 1;
541 av7110->wssData = 0;
542 }
543 break;
544 }
493 default: 545 default:
494 printk("no such ioctl\n"); 546 printk("no such ioctl\n");
495 return -ENOIOCTLCMD; 547 return -ENOIOCTLCMD;
@@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
497 return 0; 549 return 0;
498} 550}
499 551
552static int av7110_vbi_reset(struct inode *inode, struct file *file)
553{
554 struct saa7146_fh *fh = file->private_data;
555 struct saa7146_dev *dev = fh->dev;
556 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
557
558 dprintk(2, "%s\n", __FUNCTION__);
559 av7110->wssMode = 0;
560 av7110->wssData = 0;
561 if (FW_VERSION(av7110->arm_app) < 0x2623)
562 return 0;
563 else
564 return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
565}
566
567static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
568{
569 struct saa7146_fh *fh = file->private_data;
570 struct saa7146_dev *dev = fh->dev;
571 struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
572 struct v4l2_sliced_vbi_data d;
573 int rc;
574
575 dprintk(2, "%s\n", __FUNCTION__);
576 if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
577 return -EINVAL;
578 if (copy_from_user(&d, data, count))
579 return -EFAULT;
580 if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
581 return -EINVAL;
582 if (d.id) {
583 av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
584 rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig,
585 2, 1, av7110->wssData);
586 } else {
587 av7110->wssData = 0;
588 rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
589 }
590 return (rc < 0) ? rc : count;
591}
500 592
501/**************************************************************************** 593/****************************************************************************
502 * INITIALIZATION 594 * INITIALIZATION
@@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
512 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE }, 604 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
513 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE }, 605 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
514 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE }, 606 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
607 { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
608 { VIDIOC_G_FMT, SAA7146_BEFORE },
609 { VIDIOC_S_FMT, SAA7146_BEFORE },
515 { 0, 0 } 610 { 0, 0 }
516}; 611};
517 612
@@ -692,12 +787,11 @@ int av7110_init_v4l(struct av7110 *av7110)
692 saa7146_vv_release(dev); 787 saa7146_vv_release(dev);
693 return -ENODEV; 788 return -ENODEV;
694 } 789 }
695 if (av7110->analog_tuner_flags) { 790 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
696 if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) { 791 ERR(("cannot register vbi v4l2 device. skipping.\n"));
697 ERR(("cannot register vbi v4l2 device. skipping.\n")); 792 } else {
698 } else { 793 if (av7110->analog_tuner_flags)
699 av7110->analog_tuner_flags |= ANALOG_TUNER_VBI; 794 av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
700 }
701 } 795 }
702 return 0; 796 return 0;
703} 797}
@@ -778,7 +872,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
778static struct saa7146_ext_vv av7110_vv_data_st = { 872static struct saa7146_ext_vv av7110_vv_data_st = {
779 .inputs = 1, 873 .inputs = 1,
780 .audios = 1, 874 .audios = 1,
781 .capabilities = 0, 875 .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
782 .flags = 0, 876 .flags = 0,
783 877
784 .stds = &standard[0], 878 .stds = &standard[0],
@@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
787 881
788 .ioctls = &ioctls[0], 882 .ioctls = &ioctls[0],
789 .ioctl = av7110_ioctl, 883 .ioctl = av7110_ioctl,
884
885 .vbi_fops.open = av7110_vbi_reset,
886 .vbi_fops.release = av7110_vbi_reset,
887 .vbi_fops.write = av7110_vbi_write,
790}; 888};
791 889
792static struct saa7146_ext_vv av7110_vv_data_c = { 890static struct saa7146_ext_vv av7110_vv_data_c = {
793 .inputs = 1, 891 .inputs = 1,
794 .audios = 1, 892 .audios = 1,
795 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, 893 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
796 .flags = SAA7146_USE_PORT_B_FOR_VBI, 894 .flags = SAA7146_USE_PORT_B_FOR_VBI,
797 895
798 .stds = &standard[0], 896 .stds = &standard[0],
@@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
801 899
802 .ioctls = &ioctls[0], 900 .ioctls = &ioctls[0],
803 .ioctl = av7110_ioctl, 901 .ioctl = av7110_ioctl,
902
903 .vbi_fops.open = av7110_vbi_reset,
904 .vbi_fops.release = av7110_vbi_reset,
905 .vbi_fops.write = av7110_vbi_write,
804}; 906};
805 907
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index 16af9299315f..e5e749e984ee 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -178,6 +178,8 @@ struct saa7146_ext_vv
178 178
179 struct saa7146_extension_ioctls *ioctls; 179 struct saa7146_extension_ioctls *ioctls;
180 int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg); 180 int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
181
182 struct file_operations vbi_fops;
181}; 183};
182 184
183struct saa7146_use_ops { 185struct saa7146_use_ops {