diff options
author | Gerd Knorr <devnull@localhost> | 2004-10-19 16:02:04 +0000 |
---|---|---|
committer | Gerd Knorr <devnull@localhost> | 2004-10-19 16:02:04 +0000 |
commit | 1978764a333728085febe6606437b586fc2e14d4 (patch) | |
tree | 80d861b548370e3dfc319649d43c956e238587e2 /linux/drivers/media/video/video-buf-dvb.c | |
parent | 005bc8a9298b2eab8e0bdb6d494b5b13c32811f4 (diff) | |
download | mediapointer-dvb-s2-1978764a333728085febe6606437b586fc2e14d4.tar.gz mediapointer-dvb-s2-1978764a333728085febe6606437b586fc2e14d4.tar.bz2 |
- saa7134 reorganiation for modular mpeg2 stuff
- splitted some generic dvb code into the new video-buf-dvb module.
Diffstat (limited to 'linux/drivers/media/video/video-buf-dvb.c')
-rw-r--r-- | linux/drivers/media/video/video-buf-dvb.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/linux/drivers/media/video/video-buf-dvb.c b/linux/drivers/media/video/video-buf-dvb.c new file mode 100644 index 000000000..51afc3ae5 --- /dev/null +++ b/linux/drivers/media/video/video-buf-dvb.c @@ -0,0 +1,208 @@ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/fs.h> +#include <linux/kthread.h> +#include <linux/file.h> +#include <linux/suspend.h> + +#include <media/video-buf.h> +#include <media/video-buf-dvb.h> + +/* ------------------------------------------------------------------ */ + +MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); +MODULE_LICENSE("GPL"); + +static unsigned int debug = 0; +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug,"enable debug messages"); + +#define dprintk(fmt, arg...) if (debug) \ + printk(KERN_DEBUG "%s/dvb: " fmt, dvb->name, ## arg) + +/* ------------------------------------------------------------------ */ + +static int videobuf_dvb_thread(void *data) +{ + struct videobuf_dvb *dvb = data; + struct videobuf_buffer *buf; + unsigned long flags; + int err; + + dprintk("dvb thread started\n"); + videobuf_read_start(dvb->priv, &dvb->dvbq); + + for (;;) { + /* fetch next buffer */ + buf = list_entry(dvb->dvbq.stream.next, + struct videobuf_buffer, stream); + list_del(&buf->stream); + err = videobuf_waiton(buf,0,1); + BUG_ON(0 != err); + + /* no more feeds left or stop_feed() asked us to quit */ + if (0 == dvb->nfeeds) + break; + if (kthread_should_stop()) + break; + if (current->flags & PF_FREEZE) + refrigerator(PF_FREEZE); + + /* feed buffer data to demux */ + if (buf->state == STATE_DONE) + dvb_dmx_swfilter(&dvb->demux, buf->dma.vmalloc, + buf->size); + + /* requeue buffer */ + list_add_tail(&buf->stream,&dvb->dvbq.stream); + spin_lock_irqsave(dvb->dvbq.irqlock,flags); + dvb->dvbq.ops->buf_queue(dvb->priv,buf); + spin_unlock_irqrestore(dvb->dvbq.irqlock,flags); + } + + videobuf_read_stop(dvb, &dvb->dvbq); + dprintk("dvb thread stopped\n"); + + /* Hmm, linux becomes *very* unhappy without this ... */ + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + return 0; +} + +static int videobuf_dvb_start_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct videobuf_dvb *dvb = demux->priv; + int rc; + + if (!demux->dmx.frontend) + return -EINVAL; + + down(&dvb->lock); + dvb->nfeeds++; + rc = dvb->nfeeds; + + if (NULL != dvb->thread) + goto out; + dvb->thread = kthread_run(videobuf_dvb_thread, + dvb, "%s dvb", dvb->name); + if (IS_ERR(dvb->thread)) { + rc = PTR_ERR(dvb->thread); + dvb->thread = NULL; + } + +out: + up(&dvb->lock); + return rc; +} + +static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) +{ + struct dvb_demux *demux = feed->demux; + struct videobuf_dvb *dvb = demux->priv; + int err = 0; + + down(&dvb->lock); + dvb->nfeeds--; + if (0 == dvb->nfeeds && NULL != dvb->thread) { + // FIXME: cx8802_cancel_buffers(dev); + err = kthread_stop(dvb->thread); + dvb->thread = NULL; + } + up(&dvb->lock); + return err; +} + +/* ------------------------------------------------------------------ */ + +int videobuf_dvb_register(struct videobuf_dvb *dvb) +{ + int result; + + init_MUTEX(&dvb->lock); + + dvb->demux.dmx.capabilities = + DMX_TS_FILTERING | DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + dvb->demux.priv = dvb; + dvb->demux.filternum = 256; + dvb->demux.feednum = 256; + dvb->demux.start_feed = videobuf_dvb_start_feed; + dvb->demux.stop_feed = videobuf_dvb_stop_feed; + result = dvb_dmx_init(&dvb->demux); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", + dvb->name, result); + goto fail1; + } + + dvb->dmxdev.filternum = 256; + dvb->dmxdev.demux = &dvb->demux.dmx; + dvb->dmxdev.capabilities = 0; + result = dvb_dmxdev_init(&dvb->dmxdev, dvb->adapter); + if (result < 0) { + printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", + dvb->name, result); + goto fail2; + } + + dvb->fe_hw.source = DMX_FRONTEND_0; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", + dvb->name, result); + goto fail3; + } + + dvb->fe_mem.source = DMX_MEMORY_FE; + result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem); + if (result < 0) { + printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", + dvb->name, result); + goto fail4; + } + + result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw); + if (result < 0) { + printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", + dvb->name, result); + goto fail5; + } + + dvb_net_init(dvb->adapter, &dvb->net, &dvb->demux.dmx); + return 0; + +fail5: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); +fail4: + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); +fail3: + dvb_dmxdev_release(&dvb->dmxdev); +fail2: + dvb_dmx_release(&dvb->demux); +fail1: + return result; +} + +void videobuf_dvb_unregister(struct videobuf_dvb *dvb) +{ + dvb_net_release(&dvb->net); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); + dvb_dmxdev_release(&dvb->dmxdev); + dvb_dmx_release(&dvb->demux); +} + +EXPORT_SYMBOL(videobuf_dvb_register); +EXPORT_SYMBOL(videobuf_dvb_unregister); + +/* ------------------------------------------------------------------ */ +/* + * Local variables: + * c-basic-offset: 8 + * compile-command: "make DVB=1" + * End: + */ |