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 | |
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')
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-blackbird.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-cards.c | 12 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-dvb.c | 211 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-mpeg.c | 5 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-video.c | 6 | ||||
-rw-r--r-- | linux/drivers/media/video/cx88/cx88.h | 33 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-cards.c | 18 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-core.c | 167 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-dvb.c | 113 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-empress.c | 406 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-ts.c | 331 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-tvaudio.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134-video.c | 3 | ||||
-rw-r--r-- | linux/drivers/media/video/saa7134/saa7134.h | 75 | ||||
-rw-r--r-- | linux/drivers/media/video/video-buf-dvb.c | 208 |
15 files changed, 976 insertions, 620 deletions
diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 3434952cf..6c4fe5199 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-blackbird.c,v 1.15 2004/10/13 10:39:00 kraxel Exp $ + * $Id: cx88-blackbird.c,v 1.16 2004/10/19 16:02:04 kraxel Exp $ * * Support for a cx23416 mpeg encoder via cx2388x host port. * "blackbird" reference design. @@ -871,7 +871,7 @@ static struct pci_driver blackbird_pci_driver = { .name = "cx88-blackbird", .id_table = cx8802_pci_tbl, .probe = blackbird_probe, - .remove = blackbird_remove, + .remove = __devexit_p(blackbird_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 26646fff1..8478d28b2 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-cards.c,v 1.45 2004/10/13 10:39:00 kraxel Exp $ + * $Id: cx88-cards.c,v 1.46 2004/10/19 16:02:04 kraxel Exp $ * * device driver for Conexant 2388x based TV cards * card-specific stuff. @@ -26,8 +26,14 @@ #include <linux/pci.h> #include <linux/delay.h> +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) +# define WITH_DVB 1 +#endif + #include "cx88.h" +#ifdef WITH_DVB #include "cx22702.h" +#endif /* ------------------------------------------------------------------ */ /* board config info */ @@ -641,6 +647,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) core->tuner_type, radio ? "yes" : "no"); } +#ifdef WITH_DVB static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee) { int model; @@ -683,6 +690,7 @@ static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee) core->pll_addr = 0x61; core->demod_addr = 0x43; } +#endif /* ----------------------------------------------------------------------- */ /* some GDI (was: Modular Technology) specific stuff */ @@ -820,6 +828,7 @@ void cx88_card_setup(struct cx88_core *core) msleep(1); cx_set(MO_GP0_IO, 0x00000101); break; +#ifdef WITH_DVB case CX88_BOARD_HAUPPAUGE_DVB_T1: if (0 == core->i2c_rc) i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom)); @@ -830,6 +839,7 @@ void cx88_card_setup(struct cx88_core *core) core->pll_addr = 0x60; core->demod_addr = 0x43; break; +#endif } if (cx88_boards[core->board].radio.type == CX88_RADIO) core->has_radio = 1; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 29a35e876..878d7c19d 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-dvb.c,v 1.13 2004/10/13 10:39:00 kraxel Exp $ + * $Id: cx88-dvb.c,v 1.14 2004/10/19 16:02:04 kraxel Exp $ * * device driver for Conexant 2388x based TV cards * MPEG Transport Stream (DVB) routines @@ -85,136 +85,14 @@ struct videobuf_queue_ops dvb_qops = { .buf_release = dvb_buf_release, }; -static int dvb_thread(void *data) -{ - struct cx8802_dev *dev = data; - struct videobuf_buffer *buf; - unsigned long flags; - int err; - - dprintk(1,"dvb thread started\n"); - videobuf_read_start(dev, &dev->dvbq); - - for (;;) { - /* fetch next buffer */ - buf = list_entry(dev->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 == dev->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(&dev->demux, buf->dma.vmalloc, - buf->size); - - /* requeue buffer */ - list_add_tail(&buf->stream,&dev->dvbq.stream); - spin_lock_irqsave(dev->dvbq.irqlock,flags); - dev->dvbq.ops->buf_queue(dev,buf); - spin_unlock_irqrestore(dev->dvbq.irqlock,flags); - - /* log errors if any */ - if (dev->error_count || dev->stopper_count) { - printk("%s: error=%d stopper=%d\n", - dev->core->name, dev->error_count, - dev->stopper_count); - dev->error_count = 0; - dev->stopper_count = 0; - } - if (debug && dev->timeout_count) { - printk("%s: timeout=%d (FE not locked?)\n", - dev->core->name, dev->timeout_count); - dev->timeout_count = 0; - } - } - - videobuf_read_stop(dev, &dev->dvbq); - dprintk(1,"dvb thread stopped\n"); - - /* Hmm, linux becomes *very* unhappy without this ... */ - while (!kthread_should_stop()) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule(); - } - return 0; -} - -/* ---------------------------------------------------------------------------- */ - -static int dvb_start_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct cx8802_dev *dev = demux->priv; - int rc; - - if (!demux->dmx.frontend) - return -EINVAL; - - down(&dev->lock); - dev->nfeeds++; - rc = dev->nfeeds; - - if (NULL != dev->dvb_thread) - goto out; - dev->dvb_thread = kthread_run(dvb_thread, dev, "%s dvb", dev->core->name); - if (IS_ERR(dev->dvb_thread)) { - rc = PTR_ERR(dev->dvb_thread); - dev->dvb_thread = NULL; - } - -out: - up(&dev->lock); - dprintk(2, "%s rc=%d\n",__FUNCTION__,rc); - return rc; -} - -static int dvb_stop_feed(struct dvb_demux_feed *feed) -{ - struct dvb_demux *demux = feed->demux; - struct cx8802_dev *dev = demux->priv; - int err = 0; - - dprintk(2, "%s\n",__FUNCTION__); - - down(&dev->lock); - dev->nfeeds--; - if (0 == dev->nfeeds && NULL != dev->dvb_thread) { - cx8802_cancel_buffers(dev); - err = kthread_stop(dev->dvb_thread); - dev->dvb_thread = NULL; - } - up(&dev->lock); - return err; -} +/* ------------------------------------------------------------------ */ static void dvb_unregister(struct cx8802_dev *dev) { -#if 1 /* really needed? */ - down(&dev->lock); - if (NULL != dev->dvb_thread) { - kthread_stop(dev->dvb_thread); - BUG(); - } - up(&dev->lock); -#endif - - dvb_net_release(&dev->dvbnet); - dev->demux.dmx.remove_frontend(&dev->demux.dmx, &dev->fe_mem); - dev->demux.dmx.remove_frontend(&dev->demux.dmx, &dev->fe_hw); - dvb_dmxdev_release(&dev->dmxdev); - dvb_dmx_release(&dev->demux); + videobuf_dvb_unregister(&dev->dvb); if (dev->fe_handle) dev->fe_release(dev->fe_handle); - dvb_unregister_adapter(dev->dvb_adapter); + dvb_unregister_adapter(dev->dvb.adapter); return; } @@ -222,8 +100,12 @@ static int dvb_register(struct cx8802_dev *dev) { int result; - /* adapter */ - result = dvb_register_adapter(&dev->dvb_adapter, dev->core->name, + /* init struct videobuf_dvb */ + dev->dvb.priv = dev; + dev->dvb.name = dev->core->name; + + /* register adapter */ + result = dvb_register_adapter(&dev->dvb.adapter, dev->core->name, THIS_MODULE); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", @@ -231,12 +113,12 @@ static int dvb_register(struct cx8802_dev *dev) goto fail1; } - /* frontend */ + /* init + register frontend */ switch (dev->core->board) { case CX88_BOARD_HAUPPAUGE_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: dev->fe_handle = cx22702_create(&dev->core->i2c_adap, - dev->dvb_adapter, + dev->dvb.adapter, dev->core->pll_addr, dev->core->pll_type, dev->core->demod_addr); @@ -248,68 +130,14 @@ static int dvb_register(struct cx8802_dev *dev) break; } - /* demux */ - dev->demux.dmx.capabilities = - DMX_TS_FILTERING | DMX_SECTION_FILTERING | - DMX_MEMORY_BASED_FILTERING; - dev->demux.priv = dev; - dev->demux.filternum = 256; - dev->demux.feednum = 256; - dev->demux.start_feed = dvb_start_feed; - dev->demux.stop_feed = dvb_stop_feed; - result = dvb_dmx_init(&dev->demux); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n", - dev->core->name, result); + /* register everything else */ + result = videobuf_dvb_register(&dev->dvb); + if (0 != result) goto fail2; - } - - dev->dmxdev.filternum = 256; - dev->dmxdev.demux = &dev->demux.dmx; - dev->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dev->dmxdev, dev->dvb_adapter); - if (result < 0) { - printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", - dev->core->name, result); - goto fail3; - } - - dev->fe_hw.source = DMX_FRONTEND_0; - result = dev->demux.dmx.add_frontend(&dev->demux.dmx, &dev->fe_hw); - if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n", - dev->core->name, result); - goto fail4; - } - - dev->fe_mem.source = DMX_MEMORY_FE; - result = dev->demux.dmx.add_frontend(&dev->demux.dmx, &dev->fe_mem); - if (result < 0) { - printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n", - dev->core->name, result); - goto fail5; - } - - result = dev->demux.dmx.connect_frontend(&dev->demux.dmx, &dev->fe_hw); - if (result < 0) { - printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n", - dev->core->name, result); - goto fail6; - } - - dvb_net_init(dev->dvb_adapter, &dev->dvbnet, &dev->demux.dmx); return 0; -fail6: - dev->demux.dmx.remove_frontend(&dev->demux.dmx, &dev->fe_mem); -fail5: - dev->demux.dmx.remove_frontend(&dev->demux.dmx, &dev->fe_hw); -fail4: - dvb_dmxdev_release(&dev->dmxdev); -fail3: - dvb_dmx_release(&dev->demux); fail2: - dvb_unregister_adapter(dev->dvb_adapter); + dvb_unregister_adapter(dev->dvb.adapter); fail1: return result; } @@ -346,12 +174,12 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, /* dvb stuff */ printk("%s/2: cx2388x based dvb card\n", core->name); - videobuf_queue_init(&dev->dvbq, &dvb_qops, + videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer)); - init_MUTEX(&dev->dvbq.lock); + init_MUTEX(&dev->dvb.dvbq.lock); err = dvb_register(dev); if (0 != err) @@ -394,7 +222,7 @@ static struct pci_driver dvb_pci_driver = { .name = "cx88-dvb", .id_table = cx8802_pci_tbl, .probe = dvb_probe, - .remove = dvb_remove, + .remove = __devexit_p(dvb_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; @@ -423,5 +251,6 @@ module_exit(dvb_fini); /* * Local variables: * c-basic-offset: 8 + * compile-command: "make DVB=1" * End: */ diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 7df7bd412..7b45b5d8a 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-mpeg.c,v 1.12 2004/10/13 10:39:00 kraxel Exp $ + * $Id: cx88-mpeg.c,v 1.13 2004/10/19 16:02:04 kraxel Exp $ * * Support for the mpeg transport stream transfers * PCI function #2 of the cx2388x. @@ -239,7 +239,6 @@ static void cx8802_timeout(unsigned long data) if (debug) cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); cx8802_stop_dma(dev); - dev->timeout_count++; do_cancel_buffers(dev,"timeout",1); } @@ -276,7 +275,6 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) /* risc2 y */ if (status & 0x10) { spin_lock(&dev->slock); - dev->stopper_count++; cx8802_restart_queue(dev,&dev->mpegq); spin_unlock(&dev->slock); } @@ -284,7 +282,6 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) /* other general errors */ if (status & 0x1f0100) { spin_lock(&dev->slock); - dev->error_count++; cx8802_stop_dma(dev); cx8802_restart_queue(dev,&dev->mpegq); spin_unlock(&dev->slock); diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index 31137f14e..c1ee8baa4 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-video.c,v 1.42 2004/10/15 10:29:24 kraxel Exp $ + * $Id: cx88-video.c,v 1.43 2004/10/19 16:02:05 kraxel Exp $ * * device driver for Conexant 2388x based TV cards * video4linux video interface @@ -1033,7 +1033,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) { struct cx8800_fh *fh = file->private_data; struct cx88_buffer *buf; - + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { if (!res_get(fh->dev,fh,RESOURCE_VBI)) return POLLERR; @@ -2244,7 +2244,7 @@ static struct pci_driver cx8800_pci_driver = { .name = "cx8800", .id_table = cx8800_pci_tbl, .probe = cx8800_initdev, - .remove = cx8800_finidev, + .remove = __devexit_p(cx8800_finidev), .suspend = cx8800_suspend, .resume = cx8800_resume, diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 768de629a..f9412befd 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -1,5 +1,5 @@ /* - * $Id: cx88.h,v 1.37 2004/10/12 07:33:22 kraxel Exp $ + * $Id: cx88.h,v 1.38 2004/10/19 16:02:05 kraxel Exp $ * * v4l2 device driver for cx2388x based TV cards * @@ -26,22 +26,10 @@ #include <linux/videodev.h> #include <linux/kdev_t.h> -#include <dvbdev.h> -#include <dmxdev.h> -#include <dvb_demux.h> -#include <dvb_net.h> -#include <dvb_frontend.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,64) -#include "video-buf.h" -#include "tuner.h" -#include "audiochip.h" -#include "i2c-compat.h" -#else -#include <media/video-buf.h> #include <media/tuner.h> #include <media/audiochip.h> -#endif +#include <media/video-buf.h> +#include <media/video-buf-dvb.h> #include "compat.h" #include "btcx-risc.h" @@ -378,11 +366,6 @@ struct cx8802_dev { u32 ts_packet_size; u32 ts_packet_count; - /* error stats */ - u32 stopper_count; - u32 error_count; - u32 timeout_count; - /* other global state info */ struct cx8802_suspend_state state; @@ -392,15 +375,7 @@ struct cx8802_dev { u32 mailbox; /* for dvb only */ - struct dvb_adapter *dvb_adapter; - struct videobuf_queue dvbq; - struct task_struct *dvb_thread; - struct dvb_demux demux; - struct dmxdev dmxdev; - struct dmx_frontend fe_hw; - struct dmx_frontend fe_mem; - struct dvb_net dvbnet; - int nfeeds; + struct videobuf_dvb dvb; void* fe_handle; int (*fe_release)(void *handle); }; diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index bddf64d4a..784220844 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-cards.c,v 1.29 2004/10/13 10:39:00 kraxel Exp $ + * $Id: saa7134-cards.c,v 1.30 2004/10/19 16:02:05 kraxel Exp $ * * device driver for philips saa7134 based TV cards * card-specific stuff. @@ -199,7 +199,7 @@ struct saa7134_board saa7134_boards[] = { .name = name_radio, .amux = LINE2, }, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_MONSTERTV] = { @@ -323,7 +323,7 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, .gpio = 0x20000, }, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_CINERGY400] = { @@ -628,7 +628,7 @@ struct saa7134_board saa7134_boards[] = { .vmux = 8, .amux = LINE1, }}, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_VIDEOMATE_TV] = { @@ -752,7 +752,7 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, .tv = 1, }}, - .has_ts = 1, + .mpeg = SAA7134_MPEG_EMPRESS, .video_out = CCIR656, }, [SAA7134_BOARD_ASUSTEK_TVFM7133] = { @@ -785,7 +785,7 @@ struct saa7134_board saa7134_boards[] = { .name = "Pinnacle PCTV Stereo (saa7134)", .audio_clock = 0x00187de7, .tuner_type = TUNER_MT2032, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, .inputs = {{ .name = name_tv, .vmux = 3, @@ -1399,6 +1399,12 @@ struct pci_device_id saa7134_pci_tbl[] = { },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x11bd, + .subdevice = 0x002d, /* 300i DVB-T + PAL */ + .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x1019, .subdevice = 0x4cb4, .driver_data = SAA7134_BOARD_ECS_TVP3XP, diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 7f5b65776..996b8149f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-core.c,v 1.12 2004/10/13 10:39:00 kraxel Exp $ + * $Id: saa7134-core.c,v 1.13 2004/10/19 16:02:05 kraxel Exp $ * * device driver for philips saa7134 based TV cards * driver core @@ -38,8 +38,6 @@ MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); -#define SAA7134_MAXBOARDS 8 - /* ------------------------------------------------------------------ */ static unsigned int irq_debug = 0; @@ -58,10 +56,6 @@ static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; MODULE_PARM(video_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); MODULE_PARM_DESC(video_nr,"video device number"); -static unsigned int ts_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; -MODULE_PARM(ts_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); -MODULE_PARM_DESC(ts_nr,"ts device number"); - static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; MODULE_PARM(vbi_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); MODULE_PARM_DESC(vbi_nr,"vbi device number"); @@ -94,8 +88,10 @@ static unsigned int latency = UNSET; MODULE_PARM(latency,"i"); MODULE_PARM_DESC(latency,"pci latency timer"); -struct list_head saa7134_devlist; -unsigned int saa7134_devcount; +static DECLARE_MUTEX(devlist_lock); +LIST_HEAD(saa7134_devlist); +static LIST_HEAD(mops_list); +static unsigned int saa7134_devcount; #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) @@ -596,7 +592,7 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) saa7134_irq_vbi_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA2) && - card_has_ts(dev)) + card_has_mpeg(dev)) saa7134_irq_ts_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) @@ -643,7 +639,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa7134_track_gpio(dev,"pre-init"); saa7134_video_init1(dev); saa7134_vbi_init1(dev); - if (card_has_ts(dev)) + if (card_has_mpeg(dev)) saa7134_ts_init1(dev); saa7134_input_init1(dev); @@ -719,7 +715,7 @@ static int saa7134_hwfini(struct saa7134_dev *dev) saa7134_oss_fini(dev); break; } - if (card_has_ts(dev)) + if (card_has_mpeg(dev)) saa7134_ts_fini(dev); saa7134_input_fini(dev); saa7134_vbi_fini(dev); @@ -784,13 +780,6 @@ static void saa7134_unregister_video(struct saa7134_dev *dev) video_device_release(dev->video_dev); dev->video_dev = NULL; } - if (dev->ts_dev) { - if (-1 != dev->ts_dev->minor) - video_unregister_device(dev->ts_dev); - else - video_device_release(dev->ts_dev); - dev->ts_dev = NULL; - } if (dev->vbi_dev) { if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); @@ -807,10 +796,38 @@ static void saa7134_unregister_video(struct saa7134_dev *dev) } } +static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops, + struct saa7134_dev *dev) +{ + int err; + + if (NULL != dev->mops) + return; + if (saa7134_boards[dev->board].mpeg != ops->type) + return; + err = ops->init(dev); + if (0 != err) + return; + dev->mops = ops; +} + +static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops, + struct saa7134_dev *dev) +{ + if (NULL == dev->mops) + return; + if (dev->mops != ops) + return; + dev->mops->fini(dev); + dev->mops = NULL; +} + static int __devinit saa7134_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct saa7134_dev *dev; + struct list_head *item; + struct saa7134_mpeg_ops *mops; int err; dev = kmalloc(sizeof(*dev),GFP_KERNEL); @@ -824,7 +841,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, err = -EIO; goto fail1; } - sprintf(dev->name,"saa%x[%d]",pci_dev->device,saa7134_devcount); + + dev->nr = saa7134_devcount; + sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr); /* pci quirks */ if (pci_pci_problems) { @@ -866,21 +885,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* board config */ dev->board = pci_id->driver_data; - if (card[saa7134_devcount] >= 0 && - card[saa7134_devcount] < saa7134_bcount) - dev->board = card[saa7134_devcount]; + if (card[dev->nr] >= 0 && + card[dev->nr] < saa7134_bcount) + dev->board = card[dev->nr]; if (SAA7134_BOARD_NOAUTO == dev->board) { must_configure_manually(); dev->board = SAA7134_BOARD_UNKNOWN; } dev->tuner_type = saa7134_boards[dev->board].tuner_type; dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; - if (UNSET != tuner[saa7134_devcount]) - dev->tuner_type = tuner[saa7134_devcount]; + if (UNSET != tuner[dev->nr]) + dev->tuner_type = tuner[dev->nr]; printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, - dev->board, card[saa7134_devcount] == dev->board ? + dev->board, card[dev->nr] == dev->board ? "insmod option" : "autodetected"); /* get mmio */ @@ -927,8 +946,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, request_module("tuner"); if (dev->tda9887_conf) request_module("tda9887"); - if (card_has_ts(dev)) + if (card_is_empress(dev)) { + request_module("saa7134-empress"); request_module("saa6752hs"); + } + if (card_is_dvb(dev)) + request_module("saa7134-dvb"); #ifdef VIDIOC_G_PRIORITY v4l2_prio_init(&dev->prio); @@ -937,7 +960,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* register v4l devices */ dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, - video_nr[saa7134_devcount]); + video_nr[dev->nr]); if (err < 0) { printk(KERN_INFO "%s: can't register video device\n", dev->name); @@ -946,22 +969,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, printk(KERN_INFO "%s: registered device video%d [v4l2]\n", dev->name,dev->video_dev->minor & 0x1f); - if (card_has_ts(dev)) { - dev->ts_dev = vdev_init(dev,&saa7134_ts_template,"ts"); - err = video_register_device(dev->ts_dev,VFL_TYPE_GRABBER, - ts_nr[saa7134_devcount]); - if (err < 0) { - printk(KERN_INFO "%s: can't register video device\n", - dev->name); - goto fail4; - } - printk(KERN_INFO "%s: registered device video%d [mpeg]\n", - dev->name,dev->ts_dev->minor & 0x1f); - } - dev->vbi_dev = vdev_init(dev,&saa7134_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, - vbi_nr[saa7134_devcount]); + vbi_nr[dev->nr]); if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device vbi%d\n", @@ -970,7 +980,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (card_has_radio(dev)) { dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, - radio_nr[saa7134_devcount]); + radio_nr[dev->nr]); if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device radio%d\n", @@ -985,7 +995,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (oss) { err = dev->oss.minor_dsp = register_sound_dsp(&saa7134_dsp_fops, - dsp_nr[saa7134_devcount]); + dsp_nr[dev->nr]); if (err < 0) { goto fail4; } @@ -994,7 +1004,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, err = dev->oss.minor_mixer = register_sound_mixer(&saa7134_mixer_fops, - mixer_nr[saa7134_devcount]); + mixer_nr[dev->nr]); if (err < 0) goto fail5; printk(KERN_INFO "%s: registered device mixer%d\n", @@ -1004,9 +1014,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, } /* everything worked */ - list_add_tail(&dev->devlist,&saa7134_devlist); pci_set_drvdata(pci_dev,dev); saa7134_devcount++; + + down(&devlist_lock); + list_for_each(item,&mops_list) { + mops = list_entry(item, struct saa7134_mpeg_ops, next); + mpeg_ops_attach(mops, dev); + } + list_add_tail(&dev->devlist,&saa7134_devlist); + up(&devlist_lock); return 0; fail5: @@ -1036,6 +1053,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, static void __devexit saa7134_finidev(struct pci_dev *pci_dev) { struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct list_head *item; + struct saa7134_mpeg_ops *mops; /* debugging ... */ if (irq_debug) { @@ -1056,6 +1075,15 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) saa7134_hwfini(dev); /* unregister */ + down(&devlist_lock); + list_del(&dev->devlist); + list_for_each(item,&mops_list) { + mops = list_entry(item, struct saa7134_mpeg_ops, next); + mpeg_ops_detach(mops, dev); + } + up(&devlist_lock); + saa7134_devcount--; + saa7134_i2c_unregister(dev); switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: @@ -1081,16 +1109,50 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) pci_set_drvdata(pci_dev, NULL); /* free memory */ - list_del(&dev->devlist); - saa7134_devcount--; kfree(dev); } +/* ----------------------------------------------------------- */ + +int saa7134_ts_register(struct saa7134_mpeg_ops *ops) +{ + struct list_head *item; + struct saa7134_dev *dev; + + down(&devlist_lock); + list_for_each(item,&saa7134_devlist) { + dev = list_entry(item, struct saa7134_dev, devlist); + mpeg_ops_attach(ops, dev); + } + list_add_tail(&ops->next,&mops_list); + up(&devlist_lock); + return 0; +} + +void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) +{ + struct list_head *item; + struct saa7134_dev *dev; + + down(&devlist_lock); + list_del(&ops->next); + list_for_each(item,&saa7134_devlist) { + dev = list_entry(item, struct saa7134_dev, devlist); + mpeg_ops_detach(ops, dev); + } + up(&devlist_lock); +} + +EXPORT_SYMBOL(saa7134_ts_register); +EXPORT_SYMBOL(saa7134_ts_unregister); + +/* ----------------------------------------------------------- */ + static struct pci_driver saa7134_pci_driver = { .name = "saa7134", .id_table = saa7134_pci_tbl, .probe = saa7134_initdev, - .remove = saa7134_finidev, + .remove = __devexit_p(saa7134_finidev), }; static int saa7134_init(void) @@ -1116,6 +1178,13 @@ module_init(saa7134_init); module_exit(saa7134_fini); /* ----------------------------------------------------------- */ + +EXPORT_SYMBOL(saa7134_print_ioctl); +EXPORT_SYMBOL(saa7134_i2c_call_clients); +EXPORT_SYMBOL(saa7134_devlist); +EXPORT_SYMBOL(saa7134_boards); + +/* ----------------------------------------------------------- */ /* * Local variables: * c-basic-offset: 8 diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c new file mode 100644 index 000000000..662a45c10 --- /dev/null +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -0,0 +1,113 @@ +/* + * $Id: saa7134-dvb.c,v 1.1 2004/10/19 16:02:05 kraxel Exp $ + * + * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/suspend.h> + +#include "saa7134-reg.h" +#include "saa7134.h" + +MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); +MODULE_LICENSE("GPL"); + +/* ------------------------------------------------------------------ */ + +static int dvb_init(struct saa7134_dev *dev) +{ + int err; + + printk("%s: %s\n",dev->name,__FUNCTION__); + + videobuf_queue_init(&dev->dvb.dvbq, &saa7134_ts_qops, + dev->pci, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_TOP, + sizeof(struct saa7134_buf)); + init_MUTEX(&dev->dvb.dvbq.lock); + + /* init struct videobuf_dvb */ + dev->dvb.priv = dev; + dev->dvb.name = dev->name; + + /* register adapter */ + err = dvb_register_adapter(&dev->dvb.adapter, dev->name, + THIS_MODULE); + if (err < 0) { + printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", + dev->name, err); + goto fail1; + } + + /* TODO: init + register frontend */ + + /* register everything else */ + err = videobuf_dvb_register(&dev->dvb); + if (0 != err) + goto fail2; + return 0; + +fail2: + dvb_unregister_adapter(dev->dvb.adapter); +fail1: + return err; +} + +static int dvb_fini(struct saa7134_dev *dev) +{ + printk("%s: %s\n",dev->name,__FUNCTION__); + + videobuf_dvb_unregister(&dev->dvb); + /* TODO: unregister frontend */ + dvb_unregister_adapter(dev->dvb.adapter); + return 0; +} + +static struct saa7134_mpeg_ops dvb_ops = { + .type = SAA7134_MPEG_DVB, + .init = dvb_init, + .fini = dvb_fini, +}; + +static int __init dvb_register(void) +{ + return saa7134_ts_register(&dvb_ops); +} + +static void __exit dvb_unregister(void) +{ + saa7134_ts_unregister(&dvb_ops); +} + +module_init(dvb_register); +module_exit(dvb_unregister); + +/* ------------------------------------------------------------------ */ +/* + * Local variables: + * c-basic-offset: 8 + * compile-command: "make DVB=1" + * End: + */ diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c new file mode 100644 index 000000000..e301bec5e --- /dev/null +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -0,0 +1,406 @@ +/* + * $Id: saa7134-empress.c,v 1.1 2004/10/19 16:02:05 kraxel Exp $ + * + * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/delay.h> + +#include "saa7134-reg.h" +#include "saa7134.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,64) +#include "saa6752hs.h" +#else +#include <media/saa6752hs.h> +#endif + +/* ------------------------------------------------------------------ */ + +MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); +MODULE_LICENSE("GPL"); + +static unsigned int empress_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; +MODULE_PARM(empress_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i"); +MODULE_PARM_DESC(empress_nr,"ts device number"); + +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/empress: " fmt, dev->name , ## arg) + +/* ------------------------------------------------------------------ */ + +static void ts_reset_encoder(struct saa7134_dev* dev) +{ + saa_writeb(SAA7134_SPECIAL_MODE, 0x00); + msleep(10); + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + msleep(100); +} + +static int ts_init_encoder(struct saa7134_dev* dev, void* arg) +{ + ts_reset_encoder(dev); + saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg); + return 0; +} + +/* ------------------------------------------------------------------ */ + +static int ts_open(struct inode *inode, struct file *file) +{ + int minor = iminor(inode); + struct saa7134_dev *h,*dev = NULL; + struct list_head *list; + int err; + + list_for_each(list,&saa7134_devlist) { + h = list_entry(list, struct saa7134_dev, devlist); + if (h->empress_dev && h->empress_dev->minor == minor) + dev = h; + } + if (NULL == dev) + return -ENODEV; + + dprintk("open minor=%d\n",minor); + down(&dev->empress_tsq.lock); + err = -EBUSY; + if (dev->empress_users) + goto done; + + dev->empress_started = 0; + dev->empress_users++; + file->private_data = dev; + err = 0; + + done: + up(&dev->empress_tsq.lock); + return err; +} + +static int ts_release(struct inode *inode, struct file *file) +{ + struct saa7134_dev *dev = file->private_data; + + if (dev->empress_tsq.streaming) + videobuf_streamoff(file->private_data,&dev->empress_tsq); + down(&dev->empress_tsq.lock); + if (dev->empress_tsq.reading) + videobuf_read_stop(file->private_data,&dev->empress_tsq); + dev->empress_users--; + + /* stop the encoder */ + if (dev->empress_started) + ts_reset_encoder(dev); + + up(&dev->empress_tsq.lock); + return 0; +} + +static ssize_t +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, NULL); + dev->empress_started = 1; + } + + return videobuf_read_stream(file->private_data, &dev->empress_tsq, + data, count, ppos, 0, + file->f_flags & O_NONBLOCK); +} + +static unsigned int +ts_poll(struct file *file, struct poll_table_struct *wait) +{ + struct saa7134_dev *dev = file->private_data; + + return videobuf_poll_stream(file, file->private_data, + &dev->empress_tsq, wait); +} + + +static int +ts_mmap(struct file *file, struct vm_area_struct * vma) +{ + struct saa7134_dev *dev = file->private_data; + + return videobuf_mmap_mapper(vma, &dev->empress_tsq); +} + +/* + * This function is _not_ called directly, but from + * video_generic_ioctl (and maybe others). userspace + * copying is done already, arg is a kernel pointer. + */ +static int ts_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct saa7134_dev *dev = file->private_data; + + if (debug > 1) + saa7134_print_ioctl(dev->name,cmd); + switch (cmd) { + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + memset(cap,0,sizeof(*cap)); + 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)); + cap->version = SAA7134_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + return 0; + } + + /* --- input switching --------------------------------------- */ + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if (i->index != 0) + return -EINVAL; + i->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(i->name,"CCIR656"); + return 0; + } + case VIDIOC_G_INPUT: + { + int *i = arg; + *i = 0; + return 0; + } + case VIDIOC_S_INPUT: + { + int *i = arg; + + if (*i != 0) + return -EINVAL; + return 0; + } + /* --- capture ioctls ---------------------------------------- */ + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + int index; + + index = f->index; + if (index != 0) + return -EINVAL; + + memset(f,0,sizeof(*f)); + f->index = index; + strlcpy(f->description, "MPEG TS", sizeof(f->description)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->pixelformat = V4L2_PIX_FMT_MPEG; + return 0; + } + + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + + 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; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + return 0; + } + + case VIDIOC_S_FMT: + { + struct v4l2_format *f = arg; + + 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; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; + f->fmt.pix.sizeimage = TS_PACKET_SIZE* dev->ts.nr_packets; + return 0; + } + + case VIDIOC_REQBUFS: + return videobuf_reqbufs(file->private_data,&dev->empress_tsq,arg); + + case VIDIOC_QUERYBUF: + return videobuf_querybuf(&dev->empress_tsq,arg); + + case VIDIOC_QBUF: + return videobuf_qbuf(file->private_data,&dev->empress_tsq,arg); + + case VIDIOC_DQBUF: + return videobuf_dqbuf(file->private_data,&dev->empress_tsq,arg, + file->f_flags & O_NONBLOCK); + + case VIDIOC_STREAMON: + return videobuf_streamon(file->private_data,&dev->empress_tsq); + + case VIDIOC_STREAMOFF: + return videobuf_streamoff(file->private_data,&dev->empress_tsq); + + case VIDIOC_QUERYCTRL: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + return saa7134_common_ioctl(dev, cmd, arg); + + case MPEG_SETPARAMS: + return ts_init_encoder(dev, arg); + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int ts_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, ts_do_ioctl); +} + +static struct file_operations ts_fops = +{ + .owner = THIS_MODULE, + .open = ts_open, + .release = ts_release, + .read = ts_read, + .poll = ts_poll, + .mmap = ts_mmap, + .ioctl = ts_ioctl, + .llseek = no_llseek, +}; + +/* ----------------------------------------------------------- */ + +static struct video_device saa7134_empress_template = +{ + .name = "saa7134-empress", + .type = 0 /* FIXME */, + .type2 = 0 /* FIXME */, + .hardware = 0, + .fops = &ts_fops, + .minor = -1, +}; + +static int empress_init(struct saa7134_dev *dev) +{ + int err; + + dprintk("%s: %s\n",dev->name,__FUNCTION__); + dev->empress_dev = video_device_alloc(); + if (NULL == dev->empress_dev) + return -ENOMEM; + *(dev->empress_dev) = saa7134_empress_template; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + dev->empress_dev->dev = &dev->pci->dev; + dev->empress_dev->release = video_device_release; +#endif + snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name), + "%s empress (%s)", dev->name, + saa7134_boards[dev->board].name); + + err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, + empress_nr[dev->nr]); + if (err < 0) { + printk(KERN_INFO "%s: can't register video device\n", + dev->name); + video_device_release(dev->empress_dev); + dev->empress_dev = NULL; + return err; + } + printk(KERN_INFO "%s: registered device video%d [mpeg]\n", + dev->name,dev->empress_dev->minor & 0x1f); + + videobuf_queue_init(&dev->empress_tsq, + &saa7134_ts_qops, dev->pci, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_ALTERNATE, + sizeof(struct saa7134_buf)); + return 0; +} + +static int empress_fini(struct saa7134_dev *dev) +{ + dprintk("%s: %s\n",dev->name,__FUNCTION__); + + if (NULL == dev->empress_dev) + return 0; + video_unregister_device(dev->empress_dev); + dev->empress_dev = NULL; + return 0; +} + +static struct saa7134_mpeg_ops empress_ops = { + .type = SAA7134_MPEG_EMPRESS, + .init = empress_init, + .fini = empress_fini, +}; + +static int __init empress_register(void) +{ + return saa7134_ts_register(&empress_ops); +} + +static void __exit empress_unregister(void) +{ + saa7134_ts_unregister(&empress_ops); +} + +module_init(empress_register); +module_exit(empress_unregister); + +/* ----------------------------------------------------------- */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/linux/drivers/media/video/saa7134/saa7134-ts.c b/linux/drivers/media/video/saa7134/saa7134-ts.c index 01e93a720..3bcb51bf3 100644 --- a/linux/drivers/media/video/saa7134/saa7134-ts.c +++ b/linux/drivers/media/video/saa7134/saa7134-ts.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-ts.c,v 1.10 2004/10/13 10:39:00 kraxel Exp $ + * $Id: saa7134-ts.c,v 1.11 2004/10/19 16:02:05 kraxel Exp $ * * device driver for philips saa7134 based TV cards * video4linux video interface @@ -31,28 +31,12 @@ #include "saa7134-reg.h" #include "saa7134.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,64) -#include "saa6752hs.h" -#else -#include <media/saa6752hs.h> -#endif - /* ------------------------------------------------------------------ */ -#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ - static unsigned int ts_debug = 0; MODULE_PARM(ts_debug,"i"); MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]"); -static unsigned int tsbufs = 4; -MODULE_PARM(tsbufs,"i"); -MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); - -static unsigned int ts_nr_packets = 30; -MODULE_PARM(ts_nr_packets,"i"); -MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); - #define dprintk(fmt, arg...) if (ts_debug) \ printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg) @@ -105,7 +89,7 @@ static int buffer_prepare(void *priv, struct videobuf_buffer *vb, dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]); llength = TS_PACKET_SIZE; - lines = ts_nr_packets; + lines = dev->ts.nr_packets; size = lines * llength; if (0 != buf->vb.baddr && buf->vb.bsize < size) @@ -144,9 +128,11 @@ static int buffer_prepare(void *priv, struct videobuf_buffer *vb, static int buffer_setup(void *priv, unsigned int *count, unsigned int *size) { - *size = TS_PACKET_SIZE * ts_nr_packets; + struct saa7134_dev *dev = priv; + + *size = TS_PACKET_SIZE * dev->ts.nr_packets; if (0 == *count) - *count = tsbufs; + *count = dev->ts.nr_bufs; *count = saa7134_buffer_count(*size,*count); return 0; } @@ -167,298 +153,24 @@ static void buffer_release(void *priv, struct videobuf_buffer *vb) saa7134_dma_free(dev,buf); } -static struct videobuf_queue_ops ts_qops = { +struct videobuf_queue_ops saa7134_ts_qops = { .buf_setup = buffer_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, .buf_release = buffer_release, }; - - -/* ------------------------------------------------------------------ */ - -static void ts_reset_encoder(struct saa7134_dev* dev) -{ - saa_writeb(SAA7134_SPECIAL_MODE, 0x00); - msleep(10); - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); - msleep(100); -} - -static int ts_init_encoder(struct saa7134_dev* dev, void* arg) -{ - ts_reset_encoder(dev); - saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg); - return 0; -} - - -/* ------------------------------------------------------------------ */ - -static int ts_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct saa7134_dev *h,*dev = NULL; - struct list_head *list; - int err; - - list_for_each(list,&saa7134_devlist) { - h = list_entry(list, struct saa7134_dev, devlist); - if (h->ts_dev && h->ts_dev->minor == minor) - dev = h; - } - if (NULL == dev) - return -ENODEV; - - dprintk("open minor=%d\n",minor); - down(&dev->ts.ts.lock); - err = -EBUSY; - if (dev->ts.users) - goto done; - - dev->ts.started = 0; - dev->ts.users++; - file->private_data = dev; - err = 0; - - done: - up(&dev->ts.ts.lock); - return err; -} - -static int ts_release(struct inode *inode, struct file *file) -{ - struct saa7134_dev *dev = file->private_data; - - if (dev->ts.ts.streaming) - videobuf_streamoff(file->private_data,&dev->ts.ts); - down(&dev->ts.ts.lock); - if (dev->ts.ts.reading) - videobuf_read_stop(file->private_data,&dev->ts.ts); - dev->ts.users--; - - /* stop the encoder */ - if (dev->ts.started) - ts_reset_encoder(dev); - - up(&dev->ts.ts.lock); - return 0; -} - -static ssize_t -ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct saa7134_dev *dev = file->private_data; - - if (!dev->ts.started) { - ts_init_encoder(dev, NULL); - dev->ts.started = 1; - } - - return videobuf_read_stream(file->private_data, - &dev->ts.ts, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); -} - -static unsigned int -ts_poll(struct file *file, struct poll_table_struct *wait) -{ - struct saa7134_dev *dev = file->private_data; - - return videobuf_poll_stream(file, file->private_data, - &dev->ts.ts, wait); -} - - -static int -ts_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct saa7134_dev *dev = file->private_data; - - return videobuf_mmap_mapper(vma, &dev->ts.ts); -} - -/* - * This function is _not_ called directly, but from - * video_generic_ioctl (and maybe others). userspace - * copying is done already, arg is a kernel pointer. - */ -static int ts_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct saa7134_dev *dev = file->private_data; - - if (ts_debug > 1) - saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - memset(cap,0,sizeof(*cap)); - 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)); - cap->version = SAA7134_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - return 0; - } - - /* --- input switching --------------------------------------- */ - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - - if (i->index != 0) - return -EINVAL; - i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name,"CCIR656"); - return 0; - } - case VIDIOC_G_INPUT: - { - int *i = arg; - *i = 0; - return 0; - } - case VIDIOC_S_INPUT: - { - int *i = arg; - - if (*i != 0) - return -EINVAL; - return 0; - } - /* --- capture ioctls ---------------------------------------- */ - - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - int index; - - index = f->index; - if (index != 0) - return -EINVAL; - - memset(f,0,sizeof(*f)); - f->index = index; - strlcpy(f->description, "MPEG TS", sizeof(f->description)); - f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - f->pixelformat = V4L2_PIX_FMT_MPEG; - return 0; - } - - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - - 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; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets; - return 0; - } - - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; - - 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; - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.sizeimage = TS_PACKET_SIZE*ts_nr_packets; - return 0; - } - - case VIDIOC_REQBUFS: - return videobuf_reqbufs(file->private_data,&dev->ts.ts,arg); - - case VIDIOC_QUERYBUF: - return videobuf_querybuf(&dev->ts.ts,arg); - - case VIDIOC_QBUF: - return videobuf_qbuf(file->private_data,&dev->ts.ts,arg); - - case VIDIOC_DQBUF: - return videobuf_dqbuf(file->private_data,&dev->ts.ts,arg, - file->f_flags & O_NONBLOCK); - - case VIDIOC_STREAMON: - return videobuf_streamon(file->private_data,&dev->ts.ts); - - case VIDIOC_STREAMOFF: - return videobuf_streamoff(file->private_data,&dev->ts.ts); - - case VIDIOC_QUERYCTRL: - case VIDIOC_G_CTRL: - case VIDIOC_S_CTRL: - return saa7134_common_ioctl(dev, cmd, arg); - - case MPEG_SETPARAMS: - return ts_init_encoder(dev, arg); - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int ts_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, ts_do_ioctl); -} - - -static struct file_operations ts_fops = -{ - .owner = THIS_MODULE, - .open = ts_open, - .release = ts_release, - .read = ts_read, - .poll = ts_poll, - .mmap = ts_mmap, - .ioctl = ts_ioctl, - .llseek = no_llseek, -}; - +EXPORT_SYMBOL_GPL(saa7134_ts_qops); /* ----------------------------------------------------------- */ /* exported stuff */ -struct video_device saa7134_ts_template = -{ - .name = "saa7134-ts", - .type = 0 /* FIXME */, - .type2 = 0 /* FIXME */, - .hardware = 0, - .fops = &ts_fops, - .minor = -1, -}; +static unsigned int tsbufs = 4; +MODULE_PARM(tsbufs,"i"); +MODULE_PARM_DESC(tsbufs,"number of ts buffers, range 2-32"); + +static unsigned int ts_nr_packets = 30; +MODULE_PARM(ts_nr_packets,"i"); +MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)"); int saa7134_ts_init1(struct saa7134_dev *dev) { @@ -471,6 +183,8 @@ int saa7134_ts_init1(struct saa7134_dev *dev) ts_nr_packets = 4; if (ts_nr_packets > 312) ts_nr_packets = 312; + dev->ts.nr_bufs = tsbufs; + dev->ts.nr_packets = ts_nr_packets; INIT_LIST_HEAD(&dev->ts_q.queue); init_timer(&dev->ts_q.timeout); @@ -478,26 +192,21 @@ int saa7134_ts_init1(struct saa7134_dev *dev) dev->ts_q.timeout.data = (unsigned long)(&dev->ts_q); dev->ts_q.dev = dev; dev->ts_q.need_two = 1; - videobuf_queue_init(&dev->ts.ts, &ts_qops, dev->pci, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_ALTERNATE, - sizeof(struct saa7134_buf)); saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts); /* init TS hw */ saa_writeb(SAA7134_TS_SERIAL1, 0x00); /* deactivate TS softreset */ saa_writeb(SAA7134_TS_PARALLEL, 0xec); /* TSSOP high active, TSVAL high active, TSLOCK ignored */ saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1)); - saa_writeb(SAA7134_TS_DMA0, ((ts_nr_packets-1)&0xff)); - saa_writeb(SAA7134_TS_DMA1, (((ts_nr_packets-1)>>8)&0xff)); - saa_writeb(SAA7134_TS_DMA2, ((((ts_nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ + saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff)); + saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff)); + saa_writeb(SAA7134_TS_DMA2, ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */ return 0; } int saa7134_ts_fini(struct saa7134_dev *dev) { - /* nothing */ saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts); return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c index 0b911e8d8..1e687a5b5 100644 --- a/linux/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/linux/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-tvaudio.c,v 1.15 2004/10/15 10:29:24 kraxel Exp $ + * $Id: saa7134-tvaudio.c,v 1.16 2004/10/19 16:02:05 kraxel Exp $ * * device driver for philips saa7134 based TV cards * tv audio decoder (fm stereo, nicam, ...) @@ -963,7 +963,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) int (*my_thread)(void *data) = NULL; /* enable I2S audio output */ - if (saa7134_boards[dev->board].has_ts) { + if (card_is_empress(dev)) { int i2sform = (48000 == dev->oss.rate) ? 0x01 : 0x00; diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 3995f062b..be0057df0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1,5 +1,5 @@ /* - * $Id: saa7134-video.c,v 1.16 2004/10/13 10:39:00 kraxel Exp $ + * $Id: saa7134-video.c,v 1.17 2004/10/19 16:02:05 kraxel Exp $ * * device driver for philips saa7134 based TV cards * video4linux video interface @@ -1631,6 +1631,7 @@ int saa7134_common_ioctl(struct saa7134_dev *dev, } return 0; } +EXPORT_SYMBOL(saa7134_common_ioctl); /* * This function is _not_ called directly, but from diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 8a4446703..45fe49c3d 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -1,5 +1,5 @@ /* - * $Id: saa7134.h,v 1.22 2004/10/13 10:39:00 kraxel Exp $ + * $Id: saa7134.h,v 1.23 2004/10/19 16:02:05 kraxel Exp $ * * v4l2 device driver for philips saa7134 based TV cards * @@ -39,11 +39,12 @@ #include "i2c-compat.h" #include "ir-common.h" #else -#include <media/video-buf.h> #include <media/tuner.h> #include <media/audiochip.h> #include <media/id.h> #include <media/ir-common.h> +#include <media/video-buf.h> +#include <media/video-buf-dvb.h> #endif #include "compat.h" @@ -185,6 +186,7 @@ struct saa7134_format { #define SAA7134_BOARD_ZOLID_XPERT_TV7134 43 #define SAA7134_EMPIRE_PCI_TV_RADIO_LE 44 +#define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 struct saa7134_input { @@ -195,6 +197,12 @@ struct saa7134_input { unsigned int tv:1; }; +enum saa7134_mpeg_type { + SAA7134_MPEG_UNUSED, + SAA7134_MPEG_EMPRESS, + SAA7134_MPEG_DVB, +}; + struct saa7134_board { char *name; unsigned int audio_clock; @@ -205,17 +213,19 @@ struct saa7134_board { struct saa7134_input radio; struct saa7134_input mute; - /* peripheral I/O */ - unsigned int has_ts; - enum saa7134_video_out video_out; - /* i2c chip info */ unsigned int tuner_type; unsigned int tda9887_conf; + + /* peripheral I/O */ + enum saa7134_video_out video_out; + enum saa7134_mpeg_type mpeg; }; #define card_has_radio(dev) (NULL != saa7134_boards[dev->board].radio.name) -#define card_has_ts(dev) (saa7134_boards[dev->board].has_ts) +#define card_is_empress(dev) (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg) +#define card_is_dvb(dev) (SAA7134_MPEG_DVB == saa7134_boards[dev->board].mpeg) +#define card_has_mpeg(dev) (SAA7134_MPEG_UNUSED != saa7134_boards[dev->board].mpeg) #define card(dev) (saa7134_boards[dev->board]) #define card_in(dev,n) (saa7134_boards[dev->board].inputs[n]) @@ -303,16 +313,6 @@ struct saa7134_fh { struct saa7134_pgtable pt_vbi; }; -/* TS status */ -struct saa7134_ts { - unsigned int users; - - /* TS capture */ - struct videobuf_queue ts; - struct saa7134_pgtable pt_ts; - int started; -}; - /* oss dsp status */ struct saa7134_oss { struct semaphore lock; @@ -357,6 +357,22 @@ struct saa7134_ir { struct timer_list timer; }; +/* ts/mpeg status */ +struct saa7134_ts { + /* TS capture */ + struct saa7134_pgtable pt_ts; + int nr_packets; + int nr_bufs; +}; + +/* ts/mpeg ops */ +struct saa7134_mpeg_ops { + enum saa7134_mpeg_type type; + struct list_head next; + int (*init)(struct saa7134_dev *dev); + int (*fini)(struct saa7134_dev *dev); +}; + /* global device status */ struct saa7134_dev { struct list_head devlist; @@ -369,11 +385,9 @@ struct saa7134_dev { /* various device info */ unsigned int resources; struct video_device *video_dev; - struct video_device *ts_dev; struct video_device *radio_dev; struct video_device *vbi_dev; struct saa7134_oss oss; - struct saa7134_ts ts; /* infrared remote */ int has_remote; @@ -381,6 +395,7 @@ struct saa7134_dev { /* pci i/o */ char name[32]; + int nr; struct pci_dev *pci; unsigned char pci_rev,pci_lat; __u32 *lmmio; @@ -405,7 +420,6 @@ struct saa7134_dev { /* video+ts+vbi capture */ struct saa7134_dmaqueue video_q; - struct saa7134_dmaqueue ts_q; struct saa7134_dmaqueue vbi_q; unsigned int video_fieldcount; unsigned int vbi_fieldcount; @@ -439,6 +453,20 @@ struct saa7134_dev { struct saa7134_input *hw_input; unsigned int hw_mute; int last_carrier; + + /* SAA7134_MPEG_* */ + struct saa7134_ts ts; + struct saa7134_dmaqueue ts_q; + struct saa7134_mpeg_ops *mops; + + /* SAA7134_MPEG_EMPRESS only */ + struct video_device *empress_dev; + struct videobuf_queue empress_tsq; + int empress_started; + unsigned int empress_users; + + /* SAA7134_MPEG_DVB only */ + struct videobuf_dvb dvb; }; /* ----------------------------------------------------------- */ @@ -531,11 +559,16 @@ void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status); /* ----------------------------------------------------------- */ /* saa7134-ts.c */ -extern struct video_device saa7134_ts_template; +#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */ + +extern struct videobuf_queue_ops saa7134_ts_qops; + int saa7134_ts_init1(struct saa7134_dev *dev); int saa7134_ts_fini(struct saa7134_dev *dev); void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status); +int saa7134_ts_register(struct saa7134_mpeg_ops *ops); +void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops); /* ----------------------------------------------------------- */ /* saa7134-vbi.c */ 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: + */ |