X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fsaa7134%2Fsaa7134-empress.c;h=65d044086ce953b9459b377b53c880aef657f29c;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=c2bca399800c1b91e28885d2988b53184928be24;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index c2bca3998..65d044086 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -1,5 +1,4 @@ /* - * $Id: saa7134-empress.c,v 1.3 2004/11/07 13:17:15 kraxel Exp $ * * (c) 2004 Gerd Knorr [SuSE Labs] * @@ -21,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +29,7 @@ #include "saa7134.h" #include +#include /* ------------------------------------------------------------------ */ @@ -36,6 +37,7 @@ MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; + module_param_array(empress_nr, int, NULL, 0444); MODULE_PARM_DESC(empress_nr,"ts device number"); @@ -50,17 +52,24 @@ MODULE_PARM_DESC(debug,"enable debug messages"); static void ts_reset_encoder(struct saa7134_dev* dev) { + if (!dev->empress_started) + return; + saa_writeb(SAA7134_SPECIAL_MODE, 0x00); msleep(10); - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); msleep(100); + dev->empress_started = 0; } -static int ts_init_encoder(struct saa7134_dev* dev, void* arg) +static int ts_init_encoder(struct saa7134_dev* dev) { + struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 }; + ts_reset_encoder(dev); - saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg); - return 0; + saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls); + dev->empress_started = 1; + return 0; } /* ------------------------------------------------------------------ */ @@ -81,18 +90,19 @@ static int ts_open(struct inode *inode, struct file *file) return -ENODEV; dprintk("open minor=%d\n",minor); - down(&dev->empress_tsq.lock); err = -EBUSY; - if (dev->empress_users) + if (!mutex_trylock(&dev->empress_tsq.lock)) goto done; + if (dev->empress_users) + goto done_up; dev->empress_users++; file->private_data = dev; - ts_init_encoder(dev, NULL); err = 0; - done: - up(&dev->empress_tsq.lock); +done_up: + mutex_unlock(&dev->empress_tsq.lock); +done: return err; } @@ -102,15 +112,16 @@ static int ts_release(struct inode *inode, struct file *file) if (dev->empress_tsq.streaming) videobuf_streamoff(&dev->empress_tsq); - down(&dev->empress_tsq.lock); + mutex_lock(&dev->empress_tsq.lock); if (dev->empress_tsq.reading) videobuf_read_stop(&dev->empress_tsq); + videobuf_mmap_free(&dev->empress_tsq); dev->empress_users--; /* stop the encoder */ ts_reset_encoder(dev); - up(&dev->empress_tsq.lock); + mutex_unlock(&dev->empress_tsq.lock); return 0; } @@ -119,6 +130,9 @@ ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { struct saa7134_dev *dev = file->private_data; + if (!dev->empress_started) + ts_init_encoder(dev); + return videobuf_read_stream(&dev->empress_tsq, data, count, ppos, 0, file->f_flags & O_NONBLOCK); @@ -150,16 +164,17 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct saa7134_dev *dev = file->private_data; + struct v4l2_ext_controls *ctrls = arg; if (debug > 1) - saa7134_print_ioctl(dev->name,cmd); + v4l_print_ioctl(dev->name,cmd); switch (cmd) { case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -222,10 +237,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, memset(f,0,sizeof(*f)); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - /* FIXME: translate subsampling type EMPRESS into - * width/height: */ - f->fmt.pix.width = 720; /* D1 */ - f->fmt.pix.height = 576; + saa7134_i2c_call_clients(dev, cmd, arg); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; return 0; @@ -238,20 +250,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - /* - FIXME: translate and round width/height into EMPRESS - subsample type: - - type | PAL | NTSC - --------------------------- - SIF | 352x288 | 352x240 - 1/2 D1 | 352x576 | 352x480 - 2/3 D1 | 480x576 | 480x480 - D1 | 720x576 | 720x480 - */ - - f->fmt.pix.width = 720; /* D1 */ - f->fmt.pix.height = 576; + saa7134_i2c_call_clients(dev, cmd, arg); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE* dev->ts.nr_packets; return 0; @@ -281,8 +280,32 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_CTRL: return saa7134_common_ioctl(dev, cmd, arg); - case MPEG_SETPARAMS: - return ts_init_encoder(dev, arg); + case VIDIOC_S_MPEGCOMP: + printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. " + "Replace with VIDIOC_S_EXT_CTRLS!"); + saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg); + ts_init_encoder(dev); + return 0; + case VIDIOC_G_MPEGCOMP: + printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. " + "Replace with VIDIOC_G_EXT_CTRLS!"); + saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg); + return 0; + case VIDIOC_S_EXT_CTRLS: + /* count == 0 is abused in saa6752hs.c, so that special + case is handled here explicitly. */ + if (ctrls->count == 0) + return 0; + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, arg); + ts_init_encoder(dev); + return 0; + case VIDIOC_G_EXT_CTRLS: + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) + return -EINVAL; + saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, arg); + return 0; default: return -ENOIOCTLCMD; @@ -320,6 +343,26 @@ static struct video_device saa7134_empress_template = .minor = -1, }; +static void empress_signal_update(void* data) +{ + struct saa7134_dev* dev = (struct saa7134_dev*) data; + + if (dev->nosignal) { + dprintk("no video signal\n"); + ts_reset_encoder(dev); + } else { + dprintk("video signal acquired\n"); + if (dev->empress_users) + ts_init_encoder(dev); + } +} + +static void empress_signal_change(struct saa7134_dev *dev) +{ + schedule_work(&dev->empress_workqueue); +} + + static int empress_init(struct saa7134_dev *dev) { int err; @@ -335,6 +378,8 @@ static int empress_init(struct saa7134_dev *dev) "%s empress (%s)", dev->name, saa7134_boards[dev->board].name); + INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev); + err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, empress_nr[dev->nr]); if (err < 0) { @@ -353,6 +398,8 @@ static int empress_init(struct saa7134_dev *dev) V4L2_FIELD_ALTERNATE, sizeof(struct saa7134_buf), dev); + + empress_signal_update(dev); return 0; } @@ -362,6 +409,7 @@ static int empress_fini(struct saa7134_dev *dev) if (NULL == dev->empress_dev) return 0; + flush_scheduled_work(); video_unregister_device(dev->empress_dev); dev->empress_dev = NULL; return 0; @@ -371,6 +419,7 @@ static struct saa7134_mpeg_ops empress_ops = { .type = SAA7134_MPEG_EMPRESS, .init = empress_init, .fini = empress_fini, + .signal_change = empress_signal_change, }; static int __init empress_register(void)