/*
- * $Id: saa7134-empress.c,v 1.3 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
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);
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)
{
ts_reset_encoder(dev);
- saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg);
+ saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL);
+ dev->empress_started = 1;
return 0;
}
return -ENODEV;
dprintk("open minor=%d\n",minor);
- down(&dev->empress_tsq.lock);
err = -EBUSY;
- if (dev->empress_users)
+ if (down_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:
+done_up:
up(&dev->empress_tsq.lock);
+done:
return err;
}
down(&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 */
{
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);
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;
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;
case VIDIOC_S_CTRL:
return saa7134_common_ioctl(dev, cmd, arg);
- case MPEG_SETPARAMS:
- return ts_init_encoder(dev, arg);
+ case VIDIOC_S_MPEGCOMP:
+ saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg);
+ ts_init_encoder(dev);
+ return 0;
+ case VIDIOC_G_MPEGCOMP:
+ saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg);
+ return 0;
default:
return -ENOIOCTLCMD;
.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;
"%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) {
V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf),
dev);
+
+ empress_signal_update(dev);
return 0;
}
if (NULL == dev->empress_dev)
return 0;
+ flush_scheduled_work();
video_unregister_device(dev->empress_dev);
dev->empress_dev = NULL;
return 0;
.type = SAA7134_MPEG_EMPRESS,
.init = empress_init,
.fini = empress_fini,
+ .signal_change = empress_signal_change,
};
static int __init empress_register(void)