summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hunold <devnull@localhost>2003-01-09 10:28:42 +0000
committerMichael Hunold <devnull@localhost>2003-01-09 10:28:42 +0000
commit6e2c952434138640f1dfa024fe69f545e81da43f (patch)
tree0288ebb6dceadc880b6217a9432dab52ad9ea8a1
parent096166622785876bd4360f2cdb1495665ca03c6c (diff)
downloadmediapointer-dvb-s2-6e2c952434138640f1dfa024fe69f545e81da43f.tar.gz
mediapointer-dvb-s2-6e2c952434138640f1dfa024fe69f545e81da43f.tar.bz2
Forgot to add some files.
-rw-r--r--linux/drivers/media/Kconfig38
-rw-r--r--linux/drivers/media/Makefile5
-rw-r--r--linux/drivers/media/dvb/ttpci-budget/budget-core.c511
3 files changed, 554 insertions, 0 deletions
diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig
new file mode 100644
index 000000000..22b991a9b
--- /dev/null
+++ b/linux/drivers/media/Kconfig
@@ -0,0 +1,38 @@
+#
+# Multimedia device configuration
+#
+
+menu "Multimedia devices"
+
+config VIDEO_DEV
+ tristate "Video For Linux"
+ ---help---
+ Support for audio/video capture and overlay devices and FM radio
+ cards. The exact capabilities of each device vary. User tools for
+ this are available from
+ <ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
+
+ This kernel includes support for the new Video for Linux Two API,
+ (V4L2) as well as the original system. Drivers and applications
+ need to be rewritten to use V4L2, but drivers for popular cards
+ and applications for most video capture functions already exist.
+
+ Documentation for the original API is included in the file
+ Documentation/video4linux/API.html. Documentation for V4L2 is
+ available on the web at http://bytesex.org/v4l/
+
+ This driver is also available as a module called videodev.o ( = code
+ which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+source "drivers/media/common/Kconfig"
+
+source "drivers/media/video/Kconfig"
+
+source "drivers/media/radio/Kconfig"
+
+source "drivers/media/dvb/Kconfig"
+
+endmenu
+
diff --git a/linux/drivers/media/Makefile b/linux/drivers/media/Makefile
new file mode 100644
index 000000000..772d6112f
--- /dev/null
+++ b/linux/drivers/media/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the kernel multimedia device drivers.
+#
+
+obj-y := video/ radio/ dvb/ common/
diff --git a/linux/drivers/media/dvb/ttpci-budget/budget-core.c b/linux/drivers/media/dvb/ttpci-budget/budget-core.c
new file mode 100644
index 000000000..0d9225d39
--- /dev/null
+++ b/linux/drivers/media/dvb/ttpci-budget/budget-core.c
@@ -0,0 +1,511 @@
+#include "budget.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
+ #define KBUILD_MODNAME budget
+#endif
+
+int budget_debug = 0;
+
+/****************************************************************************
+ * General helper functions
+ ****************************************************************************/
+
+/* this is videobuf_vmalloc_to_sg() from video-buf.c */
+struct scatterlist*
+vmalloc_to_sg(unsigned char *virt, int nr_pages)
+{
+ struct scatterlist *sglist;
+ struct page *pg;
+ int i;
+
+ sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
+ if (NULL == sglist)
+ return NULL;
+ memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
+ for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
+ pg = vmalloc_to_page(virt);
+ if (NULL == pg)
+ goto err;
+ if (PageHighMem(pg))
+ BUG();
+ sglist[i].page = pg;
+ sglist[i].length = PAGE_SIZE;
+ }
+ return sglist;
+
+ err:
+ kfree(sglist);
+ return NULL;
+}
+
+
+static inline void ddelay(int i)
+{
+ current->state=TASK_INTERRUPTIBLE;
+ schedule_timeout((HZ*i)/100);
+}
+
+/****************************************************************************
+ * TT budget / WinTV Nova
+ ****************************************************************************/
+
+static int
+TTBStop(struct budget_s *budget)
+{
+ DEB_EE(("budget: %p\n",budget));
+
+ if (--budget->feeding)
+ return budget->feeding;
+
+ saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
+ IER_DISABLE(budget->dev, MASK_07);
+ return 0;
+}
+
+static int
+TTBStart(struct budget_s *budget)
+{
+ struct saa7146_dev *dev=budget->dev;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ if (budget->feeding)
+ return ++budget->feeding;
+
+ saa7146_write(dev, MC1, MASK_20); // DMA3 off
+
+ memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH);
+
+ saa7146_write(dev, PCI_BT_V1, 0x001c0000);
+
+ budget->tsf=0;
+ budget->ttbp=0;
+ saa7146_write(dev, DD1_INIT, 0x02000680);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ saa7146_write(dev, BRS_CTRL, 0x60000000);
+ saa7146_write(dev, MC2, (MASK_08 | MASK_24));
+ mdelay(10);
+
+ saa7146_write(dev, BASE_ODD3, 0);
+ saa7146_write(dev, BASE_EVEN3, TS_WIDTH*TS_HEIGHT/2);
+ saa7146_write(dev, PROT_ADDR3, TS_WIDTH*TS_HEIGHT);
+ saa7146_write(dev, BASE_PAGE3, budget->pt.dma |ME1|0xb0);
+ saa7146_write(dev, PITCH3, TS_WIDTH);
+
+ saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT/2)<<16)|TS_WIDTH);
+ saa7146_write(dev, MC2, (MASK_04 | MASK_20));
+
+ saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on
+
+ // FIDB
+ IER_ENABLE(budget->dev, MASK_07);
+
+ return ++budget->feeding;
+}
+
+static
+void fidbirq (unsigned long data)
+{
+ struct budget_s *budget = (struct budget_s*) data;
+ u8 *mem=(u8 *)(budget->grabbing);
+ int num;
+ u32 dmapos;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ dmapos=saa7146_read(budget->dev, PCI_VDP3);
+ dmapos-=(dmapos%188);
+
+ if (dmapos>=TS_BUFLEN) {
+ DEB_S(("bogus dmapos value ignored, budget: %p\n",budget));
+ return;
+ }
+
+ if (budget->tsf) {
+ mem+=budget->ttbp;
+ if (dmapos<0x20000) {
+ num=1024-budget->ttbp/188;
+ budget->ttbp=0;
+ } else {
+ num=(dmapos - budget->ttbp)/188;
+ budget->ttbp=dmapos;
+ }
+ } else {
+ if (budget->ttbp>1000*188 && budget->ttbp<1024*188) {
+ if (budget->feeding)
+ dvb_dmx_swfilter_packets(&budget->demux,
+ mem+budget->ttbp,
+ 1024- budget->ttbp / 188);
+ }
+ num=dmapos/188;
+ budget->ttbp=dmapos;
+ }
+
+ budget->tsf^=1;
+ saa7146_write(budget->dev, DD1_INIT, 0x02000600|(budget->tsf ? 0x40:0x80));
+ saa7146_write(budget->dev, MC2,
+ (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+ // FIXME: use bottom half or tasklet
+ if (budget->feeding && mem[0]==0x47)
+ dvb_dmx_swfilter_packets(&budget->demux, mem, num);
+}
+
+inline static void
+Set22K(struct budget_s *budget, int state)
+{
+ struct saa7146_dev *dev=budget->dev;
+ DEB_EE(("budget: %p\n",budget));
+ saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
+}
+
+
+/* Diseqc functions only for TT Budget card */
+/* taken from the Skyvision DVB driver by
+ Ralph Metzler <rjkm@metzlerbros.de> */
+
+inline static void
+DiseqcSendBit(struct budget_s *budget, int data)
+{
+ struct saa7146_dev *dev=budget->dev;
+ DEB_EE(("budget: %p\n",budget));
+
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
+ udelay(data ? 500 : 1000);
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ udelay(data ? 1000 : 500);
+}
+
+static void
+DiseqcSendByte(struct budget_s *budget, int data)
+{
+ int i, par=1, d;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ for (i=7; i>=0; i--)
+ {
+ d=(data>>i)&1;
+ par^=d;
+ DiseqcSendBit(budget, d);
+ }
+ DiseqcSendBit(budget, par);
+}
+
+inline static int
+SendDiSEqCMsg(struct budget_s *budget, int len, u8 *msg, int burst)
+{
+ struct saa7146_dev *dev=budget->dev;
+ int i;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ mdelay(16);
+
+ for (i=0; i<len; i++)
+ DiseqcSendByte(budget, msg[i]);
+
+ mdelay(16);
+
+ if (burst!=-1) {
+ if (burst)
+ DiseqcSendByte(budget, 0xff);
+ else {
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
+ udelay(12500);
+ saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
+ }
+ ddelay(2);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * DVB API SECTION
+ ****************************************************************************/
+
+static int
+budget_start_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct budget_s *budget = (struct budget_s *) demux->priv;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ if (!demux->dmx.frontend)
+ return -EINVAL;
+
+ return TTBStart(budget);
+}
+
+static int
+budget_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct dvb_demux *demux = feed->demux;
+ struct budget_s *budget = (struct budget_s *) demux->priv;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ return TTBStop(budget);
+}
+
+/******************************************************************************
+ * SEC device file operations
+ ******************************************************************************/
+
+static
+int budget_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+ struct budget_s *budget = fe->before_after_data;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ switch (cmd) {
+ case FE_SET_TONE:
+ switch ((fe_sec_tone_mode_t) arg) {
+ case SEC_TONE_ON:
+ Set22K (budget, 1);
+ break;
+ case SEC_TONE_OFF:
+ Set22K (budget, 0);
+ break;
+ default:
+ return -EINVAL;
+ };
+ break;
+
+ case FE_DISEQC_SEND_MASTER_CMD:
+ {
+ struct dvb_diseqc_master_cmd *cmd = arg;
+
+ SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
+ break;
+ }
+
+ case FE_DISEQC_SEND_BURST:
+ SendDiSEqCMsg (budget, 0, NULL, (int) arg);
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ };
+
+ return 0;
+}
+
+int budget_register(struct budget_s *budget)
+{
+ int ret;
+ dmx_frontend_t *dvbfront=&budget->hw_frontend;
+ struct dvb_demux *dvbdemux=&budget->demux;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ if (budget->registered)
+ return -1;
+
+ budget->registered=1;
+
+ /* init DiSEqC stuff */
+ dvb_add_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL, budget);
+
+ memcpy(budget->demux_id, "demux0_0", 9);
+ budget->demux_id[7]=budget->dvb_adapter->num+0x30;
+ dvbdemux->priv=(void *) budget;
+
+ dvbdemux->filternum=256;
+ dvbdemux->feednum=256;
+ dvbdemux->start_feed=budget_start_feed;
+ dvbdemux->stop_feed=budget_stop_feed;
+ dvbdemux->write_to_decoder=NULL;
+
+ dvbdemux->dmx.vendor="CIM";
+ dvbdemux->dmx.model="sw";
+ dvbdemux->dmx.id=budget->demux_id;
+ dvbdemux->dmx.capabilities=(DMX_TS_FILTERING|
+ DMX_SECTION_FILTERING|
+ DMX_MEMORY_BASED_FILTERING);
+
+ dvb_dmx_init(&budget->demux);
+
+ dvbfront->id="hw_frontend";
+ dvbfront->vendor="VLSI";
+ dvbfront->model="DVB Frontend";
+ dvbfront->source=DMX_FRONTEND_0;
+
+ budget->dmxdev.filternum=256;
+ budget->dmxdev.demux=&dvbdemux->dmx;
+ budget->dmxdev.capabilities=0;
+
+ dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter);
+
+ ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx,
+ &budget->hw_frontend);
+ if (ret<0)
+ return ret;
+
+ budget->mem_frontend.id="mem_frontend";
+ budget->mem_frontend.vendor="memory";
+ budget->mem_frontend.model="sw";
+ budget->mem_frontend.source=DMX_MEMORY_FE;
+ ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx,
+ &budget->mem_frontend);
+ if (ret<0)
+ return ret;
+
+ ret=dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
+ &budget->hw_frontend);
+ if (ret<0)
+ return ret;
+
+ budget->dvb_net.card_num=budget->dvb_adapter->num;
+ dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
+
+ return 0;
+}
+
+
+static void
+dvb_unregister(struct budget_s *budget)
+{
+ struct dvb_demux *dvbdemux=&budget->demux;
+
+ DEB_EE(("budget: %p\n",budget));
+
+ if (!budget->registered)
+ return;
+
+ dvb_net_release(&budget->dvb_net);
+
+ dvbdemux->dmx.close(&dvbdemux->dmx);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
+
+ dvb_dmxdev_release(&budget->dmxdev);
+ dvb_dmx_release(&budget->demux);
+ dvb_remove_frontend_ioctls (budget->dvb_adapter, budget_diseqc_ioctl, NULL);
+}
+
+static
+int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num)
+{
+ struct saa7146_dev *dev = i2c->data;
+ return saa7146_i2c_transfer(dev, msgs, num, 6);
+}
+
+int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
+{
+ struct budget_s *budget = NULL;
+ struct scatterlist *slist = NULL;
+ int slen = 0;
+ int length = TS_WIDTH*TS_HEIGHT;
+ int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
+ int ret = 0;
+ struct budget_info *bi = info->ext_priv;
+
+ if (!(budget = kmalloc (sizeof (struct budget_s), GFP_KERNEL))) {
+ printk ("%s: out of memory!\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+ memset(budget, 0, sizeof(struct budget_s));
+
+ DEB_EE(("dev: %p, budget: %p\n",dev,budget));
+
+ budget->card = bi;
+ budget->dev=(struct saa7146_dev *)dev;
+ (struct budget_s*)dev->ext_priv = budget;
+
+ dvb_register_adapter(&budget->dvb_adapter, budget->card->name);
+
+ saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200);
+ budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, budget->dvb_adapter, 0);
+
+ if (!budget->i2c_bus) {
+ dvb_unregister_adapter (budget->dvb_adapter);
+ kfree(budget);
+ return -ENOMEM;
+ }
+
+ budget->grabbing = vmalloc(length);
+ if (!budget->grabbing) {
+ printk(KERN_ERR "dvb: vmalloc() failed.\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (!(slist = vmalloc_to_sg(budget->grabbing, pages))) {
+ printk(KERN_ERR "dvb: vmalloc_to_sg() failed.\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ if (saa7146_pgtable_alloc(dev->pci, &budget->pt)) {
+ printk(KERN_ERR "dvb: saa7146_pgtable_alloc() failed.\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ slen = pci_map_sg(dev->pci,slist,pages,PCI_DMA_FROMDEVICE);
+ saa7146_pgtable_build_single(dev->pci, &budget->pt, slist, slen);
+
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+ /* upload all */
+ saa7146_write(dev, MC2, 0x077c077c);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
+
+ tasklet_init (&budget->fidb_tasklet, fidbirq, (unsigned long) budget);
+
+ saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); /* frontend power on */
+ return 0;
+
+err:
+ if( NULL != budget->grabbing ) {
+ vfree(budget->grabbing);
+ }
+ if( NULL != slist ) {
+ kfree(slist);
+ }
+ dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, budget->i2c_bus->id);
+ dvb_unregister_adapter (budget->dvb_adapter);
+ if( NULL != budget ) {
+ kfree(budget);
+ }
+ return ret;
+}
+
+int budget_detach (struct saa7146_dev* saa)
+{
+ struct budget_s *budget = (struct budget_s*)saa->ext_priv;
+ DEB_EE(("budget: %p\n",budget));
+
+ dvb_unregister(budget);
+ dvb_unregister_i2c_bus (master_xfer,budget->i2c_bus->adapter, budget->i2c_bus->id);
+ dvb_unregister_adapter (budget->dvb_adapter);
+
+ saa7146_pgtable_free(saa->pci, &budget->pt);
+ vfree(budget->grabbing);
+ kfree (budget);
+
+ saa->ext_priv = NULL;
+
+ return 0;
+}
+
+void budget_irq(struct saa7146_dev* dev, u32 *isr)
+{
+ struct budget_s *budget = (struct budget_s*)dev->ext_priv;
+
+ DEB_EE(("dev: %p, budget: %p\n",dev,budget));
+
+ if (*isr & MASK_07)
+ tasklet_schedule (&budget->fidb_tasklet);
+}
+
+EXPORT_SYMBOL_GPL(budget_register);
+EXPORT_SYMBOL_GPL(budget_irq);
+EXPORT_SYMBOL_GPL(budget_attach);
+EXPORT_SYMBOL_GPL(budget_detach);
+
+MODULE_PARM(budget_debug,"i");