diff options
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r-- | linux/drivers/media/dvb/Kconfig | 3 | ||||
-rw-r--r-- | linux/drivers/media/dvb/Makefile | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/Kconfig (renamed from linux/drivers/media/dvb/av7110/Kconfig) | 7 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/Makefile | 9 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget.c | 739 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/Kconfig | 9 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/Makefile (renamed from linux/drivers/media/dvb/av7110/Makefile) | 0 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110.c (renamed from linux/drivers/media/dvb/av7110/av7110.c) | 478 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110.h (renamed from linux/drivers/media/dvb/av7110/av7110.h) | 46 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110_firm.h (renamed from linux/drivers/media/dvb/av7110/av7110_firm.h) | 0 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110_ipack.c (renamed from linux/drivers/media/dvb/av7110/av7110_ipack.c) | 0 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110_ipack.h (renamed from linux/drivers/media/dvb/av7110/av7110_ipack.h) | 0 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110_ir.c (renamed from linux/drivers/media/dvb/av7110/av7110_ir.c) | 0 |
13 files changed, 852 insertions, 441 deletions
diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig index 5aba59f9e..edbec1c88 100644 --- a/linux/drivers/media/dvb/Kconfig +++ b/linux/drivers/media/dvb/Kconfig @@ -35,7 +35,8 @@ source "drivers/media/dvb/frontends/Kconfig" comment "Supported DVB Adapters" depends on DVB -source "drivers/media/dvb/av7110/Kconfig" +source "drivers/media/dvb/ttpci/Kconfig" +source "drivers/media/dvb/ttpci-budget/Kconfig" endmenu diff --git a/linux/drivers/media/dvb/Makefile b/linux/drivers/media/dvb/Makefile index 3290afb80..d23a404bf 100644 --- a/linux/drivers/media/dvb/Makefile +++ b/linux/drivers/media/dvb/Makefile @@ -2,4 +2,4 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ av7110/ +obj-y := dvb-core/ frontends/ ttpci/ ttpci-budget/ diff --git a/linux/drivers/media/dvb/av7110/Kconfig b/linux/drivers/media/dvb/ttpci-budget/Kconfig index 93270f079..3c4d43d41 100644 --- a/linux/drivers/media/dvb/av7110/Kconfig +++ b/linux/drivers/media/dvb/ttpci-budget/Kconfig @@ -1,13 +1,12 @@ config DVB_AV7110 - tristate "SAA7146 based AV7110 and Nova/Budget PCI cards" + tristate "SAA7146 based AV7110 PCI cards" depends on VIDEO_DEV && DVB_CORE help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. - Simple cards like so called Budget- or Nova-PCI cards are - supported as well as fullfeatured cards with onboard MPEG2 - decoder. + This driver only supports the fullfeatured cards with + onboard MPEG2 decoder. Say Y if you own such a card and want to use it. diff --git a/linux/drivers/media/dvb/ttpci-budget/Makefile b/linux/drivers/media/dvb/ttpci-budget/Makefile new file mode 100644 index 000000000..11c671d1b --- /dev/null +++ b/linux/drivers/media/dvb/ttpci-budget/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the kernel AV7110 DVB device driver +# + +dvb-ttpci-budget-objs := budget.o + +obj-$(CONFIG_DVB_BUDGET) += dvb-ttpci-budget.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -I$(src)/../../common/ -I$(src)/../../common/saa7146 diff --git a/linux/drivers/media/dvb/ttpci-budget/budget.c b/linux/drivers/media/dvb/ttpci-budget/budget.c new file mode 100644 index 000000000..b50b1d4ad --- /dev/null +++ b/linux/drivers/media/dvb/ttpci-budget/budget.c @@ -0,0 +1,739 @@ +/* + * budget.c: driver for the SAA7146 based Nova/Budget DVB cards + * + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org/dvb/ + */ + +#include "dvb_i2c.h" +#include "dvb_frontend.h" +#include "dvbdev.h" +#include "demux.h" +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_filter.h" +#include "dvb_net.h" + +#include "saa7146.h" + +static int budget_debug = 0; +#if 1 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + #define KBUILD_MODNAME budget +#endif +#define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_MODNAME),__FUNCTION__) +#define DEB_S(x) if (0!=(budget_debug&0x01)) { DEBUG_PROLOG; printk x; } /* simple debug messages */ +#define DEB_D(x) if (0!=(budget_debug&0x02)) { DEBUG_PROLOG; printk x; } /* more detailed debug messages */ +#define DEB_EE(x) if (0!=(budget_debug&0x04)) { DEBUG_PROLOG; printk x; } /* print enter and exit of functions */ +#else +#define DEB_S(x) +#define DEB_D(x) +#define DEB_EE(x) +#endif + +int budget_num = 0; + +/* place to store all the necessary device information */ +typedef struct budget_s { + + /* devices */ + struct dvb_device dvb_dev; + dvb_net_t dvb_net; + + struct saa7146_dev *dev; + + struct dvb_i2c_bus *i2c_bus; + struct card_info *card_type; + + unsigned char *grabbing; + struct saa7146_pgtable pt; + + struct tasklet_struct fidb_tasklet; + + dmxdev_t dmxdev; + struct dvb_demux demux; + char demux_id[16]; + + dmx_frontend_t hw_frontend; + dmx_frontend_t mem_frontend; + + int fe_synced; + struct semaphore pid_mutex; + + int tsf; + u32 ttbp; + int feeding; + + int registered; + + struct dvb_adapter *dvb_adapter; +} budget_t; + +/**************************************************************************** + * 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(budget_t *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; +} + +#define TS_WIDTH (4*188) +#define TS_HEIGHT (1024/4) +#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT) + +static int +TTBStart(budget_t *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(budget_t *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(budget_t *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(budget_t *budget, int data) +{ + struct saa7146_dev *dev=budget->dev; + 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(budget_t *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; + budget_t *budget = (budget_t *) 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; + budget_t *budget = (budget_t *) 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) +{ + budget_t *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; +} + +static +int budget_register(budget_t *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(budget_t *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); +} + +/**************************************************************************** + * INITIALIZATION + ****************************************************************************/ + +int budget_preinit(struct saa7146_dev* dev) +{ + DEB_EE(("dev: %p\n",dev)); + return 0; +} + +struct card_info { + int type; + char *name; +}; + +#define DVB_CARD_TT_BUDGET 0 +#define DVB_CARD_TT_BUDGET_CI 1 +#define DVB_CARD_KNC1 2 + +static struct card_info ttbs = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-S PCI" }; +static struct card_info ttbc = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-C PCI" }; +static struct card_info ttbt = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-T PCI" }; +static struct card_info ttbci = { DVB_CARD_TT_BUDGET_CI, "TT-Budget/WinTV-NOVA-CI PCI" }; +static struct card_info satel = { DVB_CARD_TT_BUDGET, "SATELCO Multimedia PCI"}; +static struct card_info knc1 = { DVB_CARD_KNC1, "KNC1 DVB-S" }; + +static struct saa7146_sub_info sub_data[] = { + { 0x1131, 0x4f56 }, + { 0x13c2, 0x1003 }, + { 0x13c2, 0x1004 }, + { 0x13c2, 0x1005 }, + { 0x13c2, 0x100c }, + { 0x13c2, 0x1013 }, + { 0xffff, 0xffff }, +}; + +struct card_match { + struct saa7146_sub_info *sub; /* Subsystem IDs or PCI_ANY_ID */ + struct card_info *card; +}; + +static struct card_match match_data[] = { + { &sub_data[ 0], &knc1 }, + { &sub_data[ 1], &ttbs }, + { &sub_data[ 2], &ttbc }, + { &sub_data[ 3], &ttbt }, + { &sub_data[ 4], &ttbci }, + { &sub_data[ 5], &satel }, + { &sub_data[ 6], NULL }, +}; + + +int budget_probe(struct saa7146_dev* dev, unsigned int subvendor, unsigned int subdevice) +{ + budget_t *budget; + int i = 0; + + DEB_EE(("dev: %p\n",dev)); + + for(i = 0;;i++) { + if( 0xffff == match_data[i].sub->subvendor ) { + printk(KERN_ERR "dvb: device subvendor:0x%04x, subdevice:0x%04x is not a known dvb card.\n",subvendor,subdevice); + return -ENODEV; + } + if( subvendor == match_data[i].sub->subvendor && subdevice == match_data[i].sub->subdevice ) { + break; + } + } + + if (!(budget = kmalloc (sizeof (struct budget_s), GFP_KERNEL))) { + printk ("%s: out of memory!\n", __FUNCTION__); + return -ENOMEM; + } + memset(budget, 0, sizeof(budget_t)); + budget->card_type = match_data[i].card; + + (budget_t*)dev->ext_priv = budget; + + return 0; +} + +static +int budget_attach (struct saa7146_dev* dev) +{ + budget_t *budget = (budget_t*)dev->ext_priv; + struct scatterlist *slist = NULL; + int slen = 0; + int length = TS_WIDTH*TS_HEIGHT; + int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; + int ret = 0; + + DEB_EE(("dev: %p, budget: %p\n",dev,budget)); + + budget->dev=(struct saa7146_dev *)dev; + dvb_register_adapter(&budget->dvb_adapter, budget->card_type->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); + 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); + /* set dd1 stream a & b */ + saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, DD1_INIT, 0x02000000); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + /* 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 */ + + budget_register(budget); + + printk(KERN_INFO "budget: found budget-%d.\n",budget_num); + budget_num++; + 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); + return ret; +} + +static +int budget_detach (struct saa7146_dev* saa) +{ + budget_t *budget = (budget_t*)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; + budget_num--; + + return 0; +} + + +static +void budget_irq(struct saa7146_dev* dev, u32 *isr) +{ + budget_t *budget = (budget_t*)dev->ext_priv; + + DEB_EE(("dev: %p, budget: %p\n",dev,budget)); + + if (*isr & MASK_07) + tasklet_schedule (&budget->fidb_tasklet); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) +static +void budget_inc_use(struct saa7146_dev* adap) +{ + MOD_INC_USE_COUNT; +} + +static +void budget_dec_use(struct saa7146_dev* adap) +{ + MOD_DEC_USE_COUNT; +} +#endif + +static +struct saa7146_extension budget_extension = { + .name = "budget dvb\0", + .devices = &sub_data[0], + .module = THIS_MODULE, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + .inc_use = budget_inc_use, + .dec_use = budget_dec_use, +#endif + .preinit = budget_preinit, + .probe = budget_probe, + .attach = budget_attach, + .detach = budget_detach, + + .irq_mask = MASK_07, + .irq_func = budget_irq, +}; + + +static +int __init budget_init(void) +{ + DEB_EE((".\n")); + + if (saa7146_register_extension(&budget_extension)) + return -ENODEV; + + return 0; +} + + +static +void __exit budget_exit(void) +{ + DEB_EE((".\n")); + + if (saa7146_unregister_extension(&budget_extension)) + printk(KERN_ERR "dvb: extension deregistration failed.\n"); +} + +module_init(budget_init); +module_exit(budget_exit); + +MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by " + "Siemens, Technotrend, Hauppauge"); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(budget_debug,"i"); diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig new file mode 100644 index 000000000..cf8fe5251 --- /dev/null +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -0,0 +1,9 @@ +config DVB_BUDGET + tristate "SAA7146 based Nova/Budget PCI cards" + depends on VIDEO_DEV && DVB_CORE + help + Support for simple SAA7146 based DVB cards + (so called Budget- or Nova-PCI cards) without onboard + MPEG2 decoder. + + Say Y if you own such a card and want to use it. diff --git a/linux/drivers/media/dvb/av7110/Makefile b/linux/drivers/media/dvb/ttpci/Makefile index 5a9fd0c0c..5a9fd0c0c 100644 --- a/linux/drivers/media/dvb/av7110/Makefile +++ b/linux/drivers/media/dvb/ttpci/Makefile diff --git a/linux/drivers/media/dvb/av7110/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index 77ccc15db..f196ec210 100644 --- a/linux/drivers/media/dvb/av7110/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -1,6 +1,5 @@ /* * av7110.c: driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB) - * and Nova/Budget DVB cards * * Copyright (C) 1999-2002 Ralph Metzler * & Marcus Metzler for convergence integrated media GmbH @@ -121,21 +120,9 @@ static inline void ddelay(int i) /**************************************************************************** - * GPIO and DEBI functions + * DEBI functions ****************************************************************************/ -inline static void -setgpio(av7110_t *av7110, int port, u32 data) -{ - struct saa7146_dev *dev = av7110->dev; - u32 val = 0; - - val=saa7146_read(dev,GPIO_CTRL); - val&=~(0xff << (8*(port))); - val|=(data)<<(8*(port)); - saa7146_write(dev, GPIO_CTRL, val); -} - /* This DEBI code is based on the Stradis driver by Nathan Laredo <laredo@gnu.org> */ @@ -311,7 +298,7 @@ reset_arm(av7110_t *av7110) { DEB_EE(("av7110: %p\n",av7110)); - setgpio(av7110, RESET_LINE, GPIO_OUTLO); + saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ IER_DISABLE(av7110->dev, (MASK_19 | MASK_03)); @@ -320,7 +307,7 @@ reset_arm(av7110_t *av7110) saa7146_write(av7110->dev, ISR, (MASK_19 | MASK_03)); mdelay(800); - setgpio(av7110, RESET_LINE, GPIO_OUTHI); + saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI); mdelay(800); ARM_ResetMailBox(av7110); @@ -703,84 +690,6 @@ ring_buffer_put(ring_buffer_t *db, u8 *buf, int len) } #endif - -/**************************************************************************** - * TT budget / WinTV Nova - ****************************************************************************/ - -static int -TTBStop(av7110_t *av7110) -{ - DEB_EE(("av7110: %p\n",av7110)); - - if (--av7110->feeding) - return av7110->feeding; - saa7146_write(av7110->dev, MC1, MASK_20); // DMA3 off - -// saa7146_write(av7110->dev, MC1, MASK_28); // RPS0 off - - IER_DISABLE(av7110->dev, (MASK_07 | MASK_10)); -/* - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER) & ~MASK_10 ); - saa7146_write(av7110->dev, IER, - saa7146_read(av7110->dev, IER)& ~MASK_07); -*/ - return 0; -} - -#define TS_WIDTH (4*188) -#define TS_HEIGHT (1024/4) -#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT) - -static int -TTBStart(av7110_t *av7110) -{ - struct saa7146_dev *dev=av7110->dev; - - DEB_EE(("av7110: %p\n",av7110)); - - //printk ("function : %s\n", __FUNCTION__); - if (av7110->feeding) - return ++av7110->feeding; - - saa7146_write(dev, MC1, MASK_20); // DMA3 off - - memset(av7110->grabbing, 0x00, TS_HEIGHT*TS_WIDTH); - - saa7146_write(dev, PCI_BT_V1, 0x001c0000); - - av7110->tsf=0; - av7110->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, av7110->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)); - - // VPE - IER_ENABLE(av7110->dev, MASK_10); -// saa7146_write(dev, IER, saa7146_read(saa->mem, IER)|MASK_10); - - saa7146_write(dev, MC1, (MASK_04 | MASK_20)); // DMA3 on - - // FIDB - IER_ENABLE(av7110->dev, MASK_07); -// saa7146_write(dev, IER, saa7146_read(saa->mem, IER)|MASK_07); - - return ++av7110->feeding; -} - /** * Hack! we save the last av7110 ptr. This should be ok, since * you rarely will use more then one IR control. @@ -928,86 +837,6 @@ u8 pshead[0x26] = { }; -static void vpeirq (unsigned long data) -{ - //printk("vpeirq %08x\n", saa7146_read(av7110->dev, PCI_VDP3)); -} - -#if 0 -static void fidbirq(struct saa7146_dev* saa, void *data) -{ - av7110_t *av7110=(av7110_t *) data; - u8 *mem; - - DEB_EE(("av7110: %p\n",av7110)); - - mem=(av7110->tsf ? TS_HEIGHT*TS_WIDTH/2 :0)+(u8 *)av7110->grabbing; - - // FIXME: think of something better without busy waiting - if (av7110->tsf) - while (saa7146_read(av7110->dev, PCI_VDP3)>0x20000); - else - while (saa7146_read(av7110->dev, PCI_VDP3)<0x17800); - - av7110->tsf^=1; - saa7146_write(av7110->dev, DD1_INIT, 0x02000600|(av7110->tsf ? 0x40:0x80)); - saa7146_write(av7110->dev, MC2, - (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - - // FIXME: use bottom half or tasklet - if (av7110->feeding && mem[0]==0x47) - dvb_dmx_swfilter_packets(&av7110->demux, mem, 512); -} -#else -static -void fidbirq (unsigned long data) -{ - struct av7110_s *av7110 = (struct av7110_s*) data; - u8 *mem=(u8 *)(av7110->grabbing); - int num; - u32 dmapos; - - DEB_EE(("av7110: %p\n",av7110)); - - dmapos=saa7146_read(av7110->dev, PCI_VDP3); - dmapos-=(dmapos%188); - - if (dmapos>=TS_BUFLEN) { - DEB_S(("bogus dmapos value ignored, av7110: %p\n",av7110)); - return; - } - - if (av7110->tsf) { - mem+=av7110->ttbp; - if (dmapos<0x20000) { - num=1024-av7110->ttbp/188; - av7110->ttbp=0; - } else { - num=(dmapos - av7110->ttbp)/188; - av7110->ttbp=dmapos; - } - } else { - if (av7110->ttbp>1000*188 && av7110->ttbp<1024*188) { - if (av7110->feeding) - dvb_dmx_swfilter_packets(&av7110->demux, - mem+av7110->ttbp, - 1024- av7110->ttbp / 188); - } - num=dmapos/188; - av7110->ttbp=dmapos; - } - - av7110->tsf^=1; - saa7146_write(av7110->dev, DD1_INIT, 0x02000600|(av7110->tsf ? 0x40:0x80)); - saa7146_write(av7110->dev, MC2, - (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - - // FIXME: use bottom half or tasklet - if (av7110->feeding && mem[0]==0x47) - dvb_dmx_swfilter_packets(&av7110->demux, mem, num); -} -#endif - //#define DEBUG_TIMING inline static void print_time(char *s) @@ -2247,12 +2076,13 @@ bootcode[] = { static int bootarm(av7110_t *av7110) { + struct saa7146_dev *dev= av7110->dev; u32 ret; int i; DEB_EE(("av7110: %p\n",av7110)); - setgpio(av7110, RESET_LINE, GPIO_OUTLO); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); /* Disable DEBI and GPIO irq */ IER_DISABLE(av7110->dev, MASK_03|MASK_19); @@ -2282,15 +2112,15 @@ bootarm(av7110_t *av7110) /* boot */ DEB_D(("bootarm: load boot code\n")); - setgpio(av7110, ARM_IRQ_LINE, GPIO_IRQLO); - //setgpio(av7110, DEBI_DONE_LINE, GPIO_INPUT); - //setgpio(av7110, 3, GPIO_INPUT); + saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO); + //saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT); + //saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT); iwdebi(av7110, DEBISWAB, DPRAM_BASE, (u32) bootcode, sizeof(bootcode)); iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); wait_for_debi_done(av7110); - setgpio(av7110, RESET_LINE, GPIO_OUTHI); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); current->state=TASK_INTERRUPTIBLE; schedule_timeout(HZ); @@ -2299,7 +2129,7 @@ bootarm(av7110_t *av7110) if (load_dram(av7110, (u32 *)Root, sizeof(Root))<0) return -1; - setgpio(av7110, RESET_LINE, GPIO_OUTLO); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO); mdelay(1); DEB_D(("bootarm: load dpram code\n")); @@ -2308,7 +2138,7 @@ bootarm(av7110_t *av7110) wait_for_debi_done(av7110); - setgpio(av7110, RESET_LINE, GPIO_OUTHI); + saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); mdelay(800); //ARM_ClearIrq(av7110); @@ -2412,43 +2242,8 @@ inline static void Set22K(av7110_t *av7110, int state) { DEB_EE(("av7110: %p\n",av7110)); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) outcom(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0); - if (av7110->card_type->type==DVB_CARD_TT_BUDGET) - setgpio(av7110, 3, (state ? GPIO_OUTHI : 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(av7110_t *av7110, int data) -{ - DEB_EE(("av7110: %p\n",av7110)); - - setgpio(av7110, 3, GPIO_OUTHI); - udelay(data ? 500 : 1000); - setgpio(av7110, 3, GPIO_OUTLO); - udelay(data ? 1000 : 500); -} - -static void -DiseqcSendByte(av7110_t *av7110, int data) -{ - int i, par=1, d; - - DEB_EE(("av7110: %p\n",av7110)); - - for (i=7; i>=0; i--) - { - d=(data>>i)&1; - par^=d; - DiseqcSendBit(av7110, d); - } - DiseqcSendBit(av7110, par); } inline static int @@ -2458,8 +2253,10 @@ SendDiSEqCMsg(av7110_t *av7110, int len, u8 *msg, int burst) DEB_EE(("av7110: %p\n",av7110)); +/* switch (av7110->card_type->type) { case DVB_CARD_TT_SIEMENS: +*/ { u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC), 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -2479,35 +2276,12 @@ SendDiSEqCMsg(av7110_t *av7110, int len, u8 *msg, int burst) buf[i+4]=msg[i]; SOutCommand(av7110, buf, 18); +/* break; } - - case DVB_CARD_TT_BUDGET: - setgpio(av7110, 3, GPIO_OUTLO); - - mdelay(16); - - for (i=0; i<len; i++) - DiseqcSendByte(av7110, msg[i]); - - mdelay(16); - - if (burst!=-1) { - if (burst) - DiseqcSendByte(av7110, 0xff); - else { - setgpio(av7110, 3, GPIO_OUTHI); - udelay(12500); - setgpio(av7110, 3, GPIO_OUTLO); - } - - ddelay(2); - } - - break; - default: return -1; +*/ } return 0; } @@ -3223,9 +2997,6 @@ av7110_start_feed(struct dvb_demux_feed *feed) if (!demux->dmx.frontend) return -EINVAL; - if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - return TTBStart(av7110); - if (feed->pid > 0x1fff) return -EINVAL; @@ -3282,9 +3053,6 @@ av7110_stop_feed(struct dvb_demux_feed *feed) DEB_EE(("av7110: %p\n",av7110)); - if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - return TTBStop(av7110); - if (feed->type == DMX_TYPE_TS) { if (feed->ts_type & TS_DECODER) { if (feed->pes_type >= DMX_TS_PES_OTHER || @@ -4221,14 +3989,13 @@ int av7110_register(av7110_t *av7110) av7110->registered=1; - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) dvb_add_frontend_notifier (av7110->dvb_adapter, av7110_before_after_tune, av7110); /** * init DiSEqC stuff */ - if (av7110->card_type->type==DVB_CARD_TT_BUDGET || - av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) dvb_add_frontend_ioctls (av7110->dvb_adapter, av7110_diseqc_ioctl, NULL, av7110); @@ -4250,7 +4017,7 @@ int av7110_register(av7110_t *av7110) av7110->demux_id[7]=av7110->dvb_adapter->num+0x30; dvbdemux->priv=(void *) av7110; - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { for (i=0; i<32; i++) av7110->handle2filter[i]=NULL; @@ -4280,35 +4047,7 @@ int av7110_register(av7110_t *av7110) av7110->dmxdev.capabilities=0; dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); - } - - if (av7110->card_type->type>=DVB_CARD_TT_BUDGET) { - dvbdemux->filternum=256; - dvbdemux->feednum=256; - dvbdemux->start_feed=av7110_start_feed; - dvbdemux->stop_feed=av7110_stop_feed; - dvbdemux->write_to_decoder=NULL; - - dvbdemux->dmx.vendor="CIM"; - dvbdemux->dmx.model="sw"; - dvbdemux->dmx.id=av7110->demux_id; - dvbdemux->dmx.capabilities=(DMX_TS_FILTERING| - DMX_SECTION_FILTERING| - DMX_MEMORY_BASED_FILTERING); - - dvb_dmx_init(&av7110->demux); - - dvbfront->id="hw_frontend"; - dvbfront->vendor="VLSI"; - dvbfront->model="DVB Frontend"; - dvbfront->source=DMX_FRONTEND_0; - - av7110->dmxdev.filternum=256; - av7110->dmxdev.demux=&dvbdemux->dmx; - av7110->dmxdev.capabilities=0; - - dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); - } +// } ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend); @@ -4329,7 +4068,7 @@ int av7110_register(av7110_t *av7110) if (ret<0) return ret; - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { dvb_register_device(av7110->dvb_adapter, &av7110->video_dev, &dvbdev_video, av7110, DVB_DEVICE_VIDEO); dvb_register_device(av7110->dvb_adapter, &av7110->audio_dev, @@ -4347,7 +4086,7 @@ int av7110_register(av7110_t *av7110) dvb_audio_write, av7110->audio_dev); #endif - } +// } av7110->dvb_net.card_num=av7110->dvb_adapter->num; dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); @@ -4375,14 +4114,14 @@ dvb_unregister(av7110_t *av7110) dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) dvb_remove_frontend_notifier (av7110->dvb_adapter, av7110_before_after_tune); dvb_remove_frontend_ioctls (av7110->dvb_adapter, av7110_diseqc_ioctl, NULL); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { dvb_unregister_device(av7110->audio_dev); dvb_unregister_device(av7110->video_dev); dvb_unregister_device(av7110->osd_dev); @@ -4390,7 +4129,7 @@ dvb_unregister(av7110_t *av7110) #ifdef USE_DVB_DSP dvb_unregister_dsp(av7110->dsp_dev); #endif - } +// } } static @@ -4423,32 +4162,25 @@ int av7110_preinit(struct saa7146_dev* dev) return 0; } -static struct card_info fs_1_5 = { DVB_CARD_TT_SIEMENS, "Siemens cable card PCI rev1.5" }; -static struct card_info fs_1_3 = { DVB_CARD_TT_SIEMENS, "Siemens/Technotrend/Hauppauge PCI rev1.3" }; -static struct card_info ttbs = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-S PCI" }; -static struct card_info ttbc = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-C PCI" }; -static struct card_info ttbt = { DVB_CARD_TT_BUDGET, "TT-Budget/WinTV-NOVA-T PCI" }; -static struct card_info ttbci = { DVB_CARD_TT_BUDGET_CI, "TT-Budget/WinTV-NOVA-CI PCI" }; -static struct card_info satel = { DVB_CARD_TT_BUDGET, "SATELCO Multimedia PCI"}; -static struct card_info unkwn = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI rev?(unknown0)?"}; -static struct card_info tt_1_6 = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI rev1.3 or 1.6" }; -static struct card_info tt_2_1 = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI rev2.1" }; -static struct card_info tt_t = { DVB_CARD_TT_SIEMENS, "Technotrend/Hauppauge PCI DVB-T" }; -static struct card_info knc1 = { DVB_CARD_KNC1, "KNC1 DVB-S" }; +struct card_info { + char *name; +}; + +static char *fs_1_5 = { "Siemens cable card PCI rev1.5" }; +static char *fs_1_3 = { "Siemens/Technotrend/Hauppauge PCI rev1.3" }; +static char *unkwn = { "Technotrend/Hauppauge PCI rev?(unknown0)?"}; +static char *tt_1_6 = { "Technotrend/Hauppauge PCI rev1.3 or 1.6" }; +static char *tt_2_1 = { "Technotrend/Hauppauge PCI rev2.1" }; +static char *tt_t = { "Technotrend/Hauppauge PCI DVB-T" }; struct card_match { - struct saa7146_sub_info *sub; /* Subsystem ID's or PCI_ANY_ID */ - struct card_info *card; + struct saa7146_sub_info *sub; /* Subsystem IDs or PCI_ANY_ID */ + char **card; }; static struct saa7146_sub_info sub_data[] = { { 0x110a, 0xffff }, { 0x110a, 0x0000 }, - { 0x13c2, 0x1003 }, - { 0x13c2, 0x1004 }, - { 0x13c2, 0x1005 }, - { 0x13c2, 0x100c }, - { 0x13c2, 0x1013 }, { 0x13c2, 0x0000 }, { 0x13c2, 0x1002 }, { 0x13c2, 0x0001 }, @@ -4458,29 +4190,22 @@ static struct saa7146_sub_info sub_data[] = { { 0x13c2, 0x0006 }, { 0x13c2, 0x0008 }, { 0xffc2, 0x0000 }, - { 0x1131, 0x4f56 }, { 0xffff, 0xffff }, }; static struct card_match match_data[] = { { &sub_data[ 0], &fs_1_5 }, { &sub_data[ 1], &fs_1_5 }, - { &sub_data[ 2], &ttbs }, - { &sub_data[ 3], &ttbc }, - { &sub_data[ 4], &ttbt }, - { &sub_data[ 5], &ttbci }, - { &sub_data[ 6], &satel }, - { &sub_data[ 7], &fs_1_3 }, - { &sub_data[ 8], &unkwn }, - { &sub_data[ 9], &tt_1_6 }, - { &sub_data[10], &tt_2_1 }, - { &sub_data[11], &tt_2_1 }, - { &sub_data[12], &tt_2_1 }, - { &sub_data[13], &tt_1_6 }, - { &sub_data[14], &tt_t }, - { &sub_data[15], &unkwn }, - { &sub_data[16], &knc1 }, - { &sub_data[17], NULL }, + { &sub_data[ 2], &fs_1_3 }, + { &sub_data[ 3], &unkwn }, + { &sub_data[ 4], &tt_1_6 }, + { &sub_data[ 5], &tt_2_1 }, + { &sub_data[ 6], &tt_2_1 }, + { &sub_data[ 7], &tt_2_1 }, + { &sub_data[ 8], &tt_1_6 }, + { &sub_data[ 9], &tt_t }, + { &sub_data[10], &unkwn }, + { &sub_data[11], NULL }, }; @@ -4506,7 +4231,7 @@ int av7110_probe(struct saa7146_dev* dev, unsigned int subvendor, unsigned int s return -ENOMEM; } memset(av7110, 0, sizeof(av7110_t)); - av7110->card_type = match_data[i].card; + av7110->card_name = *match_data[i].card; (av7110_t*)dev->ext_priv = av7110; @@ -4517,56 +4242,33 @@ static int av7110_attach (struct saa7146_dev* dev) { av7110_t *av7110 = (av7110_t*)dev->ext_priv; - struct scatterlist *slist = NULL; - int slen = 0; - int length = TS_WIDTH*TS_HEIGHT; - int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; int ret = 0; DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); - saa7146_video_uops.init(dev); + if( 0 != saa7146_vv_init(dev)) { + ERR(("cannot init capture device. skipping.\n")); + return -1; + } + if( 0 != saa7146_register_device(&av7110->vd, dev, "av7710", VFL_TYPE_GRABBER)) { ERR(("cannot register capture device. skipping.\n")); + saa7146_vv_release(dev); return -1; } av7110->dev=(struct saa7146_dev *)dev; - dvb_register_adapter(&av7110->dvb_adapter, av7110->card_type->name); + dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name); saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200); av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, av7110->dvb_adapter, 0); if (!av7110->i2c_bus) { + saa7146_unregister_device(&av7110->vd, dev); + saa7146_vv_release(dev); dvb_unregister_adapter (av7110->dvb_adapter); return -ENOMEM; } - -// fixme if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - av7110->grabbing = vmalloc(length); - if (!av7110->grabbing) { - printk(KERN_ERR "dvb: vmalloc() failed.\n"); - ret = -ENOMEM; - goto err; - } - - if (!(slist = videobuf_vmalloc_to_sg(av7110->grabbing, pages))) { - printk(KERN_ERR "dvb: videobuf_vmalloc_to_sg() failed.\n"); - ret = -ENOMEM; - goto err; - } - - if (saa7146_pgtable_alloc(dev->pci, &av7110->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, &av7110->pt, slist, slen); - -// } - saa7146_write(dev, PCI_BT_V1, 0x1c00101f); saa7146_write(dev, BCS_CTRL, 0x80400040); @@ -4581,8 +4283,6 @@ int av7110_attach (struct saa7146_dev* dev) tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110); tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110); - tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110); - tasklet_init (&av7110->fidb_tasklet, fidbirq, (unsigned long) av7110); sema_init(&av7110->pid_mutex, 1); @@ -4640,23 +4340,18 @@ int av7110_attach (struct saa7146_dev* dev) /* handle different card types */ /* load firmware into AV7110 cards */ - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { bootarm(av7110); firmversion(av7110); if ((av7110->arm_app&0xffff)<0x2502) { printk("av7110: Warning, firmware version is too old. System might be unstable!!!\n"); } kernel_thread(arm_thread, (void *) av7110, 0); - } else { - saa7146_write(av7110->dev, DD1_INIT, 0x02000600); - saa7146_write(av7110->dev, MC2, - (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - setgpio(av7110, 2, GPIO_OUTHI); /* frontend power on */ - } +// } SetVolume(av7110, 0xff, 0xff); - if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { +// if (av7110->card_type->type==DVB_CARD_TT_SIEMENS) { VidMode(av7110, vidmode); /* remaining inits according to card and frontend type */ @@ -4693,11 +4388,11 @@ int av7110_attach (struct saa7146_dev* dev) outcom(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); outcom(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); - //setgpio(av7110, 1, GPIO_OUTHI); // RGB on, SCART pin 16 - //setgpio(av7110, 3, GPIO_OUTLO); // SCARTpin 8 + //saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 + //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 av7110->adac_type = DVB_ADAC_NONE; } - } +// } av7110_setup_irc_config (av7110, 0); av7110_register(av7110); @@ -4707,12 +4402,9 @@ int av7110_attach (struct saa7146_dev* dev) return 0; err: - if( NULL != av7110->grabbing ) { - vfree(av7110->grabbing); - } - if( NULL != slist ) { - kfree(slist); - } + /* FIXME: error handling is totally bogus: memory does not get freed ... */ + saa7146_unregister_device(&av7110->vd, dev); + saa7146_vv_release(dev); dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); dvb_unregister_adapter (av7110->dvb_adapter); return ret; @@ -4747,11 +4439,6 @@ int av7110_detach (struct saa7146_dev* saa) pci_free_consistent(saa->pci, 8192, av7110->debi_virt, av7110->debi_bus); -// fixme if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) - saa7146_pgtable_free(saa->pci, &av7110->pt); - vfree(av7110->grabbing); -// } - dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); dvb_unregister_adapter (av7110->dvb_adapter); @@ -4776,12 +4463,6 @@ void av7110_irq(struct saa7146_dev* dev, u32 *isr) if (*isr & MASK_03) tasklet_schedule (&av7110->gpio_tasklet); - - if (*isr & MASK_10) - tasklet_schedule (&av7110->vpe_tasklet); - - if (*isr & MASK_07) - tasklet_schedule (&av7110->fidb_tasklet); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) @@ -4809,35 +4490,38 @@ struct saa7146_standard standard[] = { }; static -struct saa7146_extension av7110_extension = { - .name = "dvb\0", +struct saa7146_ext_vv av7110_vv_data = { .inputs = 1, .audios = 1, .capabilities = 0, - .flags = SAA7146_EXT_SWAP_ODD_EVEN, + .stds = &standard[0], + .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), + .std_callback = NULL, + + .ioctls = &ioctls[0], + .ioctl = av7110_ioctl, +}; + +static +struct saa7146_extension av7110_extension = { + .name = "dvb\0", + .devices = &sub_data[0], .module = THIS_MODULE, - + .ext_vv_data = &av7110_vv_data, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) .inc_use = av7110_inc_use, .dec_use = av7110_dec_use, #endif - .stds = &standard[0], - .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), - .std_callback = NULL, - - .ioctls = &ioctls[0], - .preinit = av7110_preinit, .probe = av7110_probe, .attach = av7110_attach, .detach = av7110_detach, - .ioctl = av7110_ioctl, - .irq_mask = MASK_07|MASK_10|MASK_19|MASK_03, // |MASK_27, + .irq_mask = MASK_19|MASK_03, .irq_func = av7110_irq, }; diff --git a/linux/drivers/media/dvb/av7110/av7110.h b/linux/drivers/media/dvb/ttpci/av7110.h index a379a3fcd..d1eabe3ab 100644 --- a/linux/drivers/media/dvb/av7110/av7110.h +++ b/linux/drivers/media/dvb/ttpci/av7110.h @@ -11,7 +11,7 @@ #include <linux/devfs_fs_kernel.h> #endif -#include "saa7146.h" +#include "saa7146_vv.h" /* DEBI transfer mode defs */ @@ -39,11 +39,6 @@ #include "dvb_filter.h" #include "dvb_net.h" -#define DVB_CARD_TT_SIEMENS 0 -#define DVB_CARD_TT_BUDGET 1 -#define DVB_CARD_TT_BUDGET_CI 2 -#define DVB_CARD_KNC1 3 - typedef enum BOOTSTATES { BOOTSTATE_BUFFER_EMPTY = 0, @@ -51,16 +46,6 @@ typedef enum BOOTSTATES BOOTSTATE_BOOT_COMPLETE = 2 } BOOTSTATES; -typedef enum GPIO_MODE -{ - GPIO_INPUT = 0x00, - GPIO_IRQHI = 0x10, - GPIO_IRQLO = 0x20, - GPIO_IRQHL = 0x30, - GPIO_OUTLO = 0x40, - GPIO_OUTHI = 0x50 -} GPIO_MODE; - typedef enum { RP_None, AudioPES, @@ -111,14 +96,14 @@ typedef enum { // switch defines #define SB_GPIO 3 -#define SB_OFF GPIO_OUTLO //SlowBlank aus (TV-Mode) -#define SB_ON GPIO_INPUT //SlowBlank an (AV-Mode) -#define SB_WIDE GPIO_OUTHI //SlowBlank 6V (16/9-Mode) nicht realisiert +#define SB_OFF SAA7146_GPIO_OUTLO //SlowBlank aus (TV-Mode) +#define SB_ON SAA7146_GPIO_INPUT //SlowBlank an (AV-Mode) +#define SB_WIDE SAA7146_GPIO_OUTHI //SlowBlank 6V (16/9-Mode) nicht realisiert #define FB_GPIO 1 -#define FB_OFF GPIO_LO //FastBlank aus (CVBS-Mode) -#define FB_ON GPIO_OUTHI //FastBlank an (RGB-Mode) -#define FB_LOOP GPIO_INPUT //FastBlank der PC-Grafik durchschleifen +#define FB_OFF SAA7146_GPIO_LO //FastBlank aus (CVBS-Mode) +#define FB_ON SAA7146_GPIO_OUTHI //FastBlank an (RGB-Mode) +#define FB_LOOP SAA7146_GPIO_INPUT //FastBlank der PC-Grafik durchschleifen typedef enum VIDEOOUTPUTMODE { @@ -471,11 +456,6 @@ typedef struct p2t_s { struct dvb_demux_feed *feed; } p2t_t; -struct card_info { - int type; - char *name; -}; - /* place to store all the necessary device information */ typedef struct av7110_s { @@ -488,15 +468,10 @@ typedef struct av7110_s { struct saa7146_dev *dev; struct dvb_i2c_bus *i2c_bus; - struct card_info *card_type; - - unsigned char *grabbing; - struct saa7146_pgtable pt; + char *card_name; struct tasklet_struct debi_tasklet; struct tasklet_struct gpio_tasklet; - struct tasklet_struct vpe_tasklet; - struct tasklet_struct fidb_tasklet; int adac_type; /* audio DAC type */ #define DVB_ADAC_TI 0 @@ -586,11 +561,6 @@ typedef struct av7110_s { u8 *kbuf[2]; int sinfo; - int shsize; - int swsize; - - int tsf; - u32 ttbp; int feeding; int arm_errors; diff --git a/linux/drivers/media/dvb/av7110/av7110_firm.h b/linux/drivers/media/dvb/ttpci/av7110_firm.h index 5c93deb3d..5c93deb3d 100644 --- a/linux/drivers/media/dvb/av7110/av7110_firm.h +++ b/linux/drivers/media/dvb/ttpci/av7110_firm.h diff --git a/linux/drivers/media/dvb/av7110/av7110_ipack.c b/linux/drivers/media/dvb/ttpci/av7110_ipack.c index 3d16442e6..3d16442e6 100644 --- a/linux/drivers/media/dvb/av7110/av7110_ipack.c +++ b/linux/drivers/media/dvb/ttpci/av7110_ipack.c diff --git a/linux/drivers/media/dvb/av7110/av7110_ipack.h b/linux/drivers/media/dvb/ttpci/av7110_ipack.h index d1c995aff..d1c995aff 100644 --- a/linux/drivers/media/dvb/av7110/av7110_ipack.h +++ b/linux/drivers/media/dvb/ttpci/av7110_ipack.h diff --git a/linux/drivers/media/dvb/av7110/av7110_ir.c b/linux/drivers/media/dvb/ttpci/av7110_ir.c index 4e89ed71f..4e89ed71f 100644 --- a/linux/drivers/media/dvb/av7110/av7110_ir.c +++ b/linux/drivers/media/dvb/ttpci/av7110_ir.c |