diff options
author | Michael Hunold <devnull@localhost> | 2003-01-09 10:28:42 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2003-01-09 10:28:42 +0000 |
commit | 6e2c952434138640f1dfa024fe69f545e81da43f (patch) | |
tree | 0288ebb6dceadc880b6217a9432dab52ad9ea8a1 | |
parent | 096166622785876bd4360f2cdb1495665ca03c6c (diff) | |
download | mediapointer-dvb-s2-6e2c952434138640f1dfa024fe69f545e81da43f.tar.gz mediapointer-dvb-s2-6e2c952434138640f1dfa024fe69f545e81da43f.tar.bz2 |
Forgot to add some files.
-rw-r--r-- | linux/drivers/media/Kconfig | 38 | ||||
-rw-r--r-- | linux/drivers/media/Makefile | 5 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget-core.c | 511 |
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"); |