(2006-08-06) rescue-bootcd

This commit is contained in:
2006-08-06 00:00:00 +02:00
parent 2f796b816a
commit decb062d20
21091 changed files with 7076462 additions and 0 deletions

View File

@@ -0,0 +1 @@
cmd_drivers/media/dvb/bt8xx/built-in.o := rm -f drivers/media/dvb/bt8xx/built-in.o; ar rcs drivers/media/dvb/bt8xx/built-in.o

View File

@@ -0,0 +1,18 @@
config DVB_BT8XX
tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards"
depends on DVB_CORE && PCI && VIDEO_BT848
select DVB_MT352
select DVB_SP887X
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards and Twinhan DST cards.
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
an external software decoder to watch TV on your computer.
If you have a Twinhan card, don't forget to select
"Twinhan DST based DVB-S/-T frontend".
Say Y if you own such a device and want to use it.

View File

@@ -0,0 +1,5 @@
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends

View File

@@ -0,0 +1,603 @@
/*
* bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
*
* Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
*
* large parts based on the bttv driver
* Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
* & Marcus Metzler (mocm@thp.uni-koeln.de)
* (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
* 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
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "bt878.h"
#include "dst_priv.h"
/**************************************/
/* Miscellaneous utility definitions */
/**************************************/
static unsigned int bt878_verbose = 1;
static unsigned int bt878_debug;
module_param_named(verbose, bt878_verbose, int, 0444);
MODULE_PARM_DESC(bt878_verbose,
"verbose startup messages, default is 1 (yes)");
module_param_named(debug, bt878_debug, int, 0644);
MODULE_PARM_DESC(bt878_debug, "Turn on/off debugging (default:off).");
int bt878_num;
struct bt878 bt878[BT878_MAX];
EXPORT_SYMBOL(bt878_debug);
EXPORT_SYMBOL(bt878_verbose);
EXPORT_SYMBOL(bt878_num);
EXPORT_SYMBOL(bt878);
#define btwrite(dat,adr) bmtwrite((dat), (bt->bt878_mem+(adr)))
#define btread(adr) bmtread(bt->bt878_mem+(adr))
#define btand(dat,adr) btwrite((dat) & btread(adr), adr)
#define btor(dat,adr) btwrite((dat) | btread(adr), adr)
#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
#if defined(dprintk)
#undef dprintk
#endif
#define dprintk if(bt878_debug) printk
static void bt878_mem_free(struct bt878 *bt)
{
if (bt->buf_cpu) {
pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu,
bt->buf_dma);
bt->buf_cpu = NULL;
}
if (bt->risc_cpu) {
pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu,
bt->risc_dma);
bt->risc_cpu = NULL;
}
}
static int bt878_mem_alloc(struct bt878 *bt)
{
if (!bt->buf_cpu) {
bt->buf_size = 128 * 1024;
bt->buf_cpu =
pci_alloc_consistent(bt->dev, bt->buf_size,
&bt->buf_dma);
if (!bt->buf_cpu)
return -ENOMEM;
memset(bt->buf_cpu, 0, bt->buf_size);
}
if (!bt->risc_cpu) {
bt->risc_size = PAGE_SIZE;
bt->risc_cpu =
pci_alloc_consistent(bt->dev, bt->risc_size,
&bt->risc_dma);
if (!bt->risc_cpu) {
bt878_mem_free(bt);
return -ENOMEM;
}
memset(bt->risc_cpu, 0, bt->risc_size);
}
return 0;
}
/* RISC instructions */
#define RISC_WRITE (0x01 << 28)
#define RISC_JUMP (0x07 << 28)
#define RISC_SYNC (0x08 << 28)
/* RISC bits */
#define RISC_WR_SOL (1 << 27)
#define RISC_WR_EOL (1 << 26)
#define RISC_IRQ (1 << 24)
#define RISC_STATUS(status) ((((~status) & 0x0F) << 20) | ((status & 0x0F) << 16))
#define RISC_SYNC_RESYNC (1 << 15)
#define RISC_SYNC_FM1 0x06
#define RISC_SYNC_VRO 0x0C
#define RISC_FLUSH() bt->risc_pos = 0
#define RISC_INSTR(instr) bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr)
static int bt878_make_risc(struct bt878 *bt)
{
bt->block_bytes = bt->buf_size >> 4;
bt->block_count = 1 << 4;
bt->line_bytes = bt->block_bytes;
bt->line_count = bt->block_count;
while (bt->line_bytes > 4095) {
bt->line_bytes >>= 1;
bt->line_count <<= 1;
}
if (bt->line_count > 255) {
printk("bt878: buffer size error!\n");
return -EINVAL;
}
return 0;
}
static void bt878_risc_program(struct bt878 *bt, u32 op_sync_orin)
{
u32 buf_pos = 0;
u32 line;
RISC_FLUSH();
RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1 | op_sync_orin);
RISC_INSTR(0);
dprintk("bt878: risc len lines %u, bytes per line %u\n",
bt->line_count, bt->line_bytes);
for (line = 0; line < bt->line_count; line++) {
// At the beginning of every block we issue an IRQ with previous (finished) block number set
if (!(buf_pos % bt->block_bytes))
RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
RISC_IRQ |
RISC_STATUS(((buf_pos /
bt->block_bytes) +
(bt->block_count -
1)) %
bt->block_count) | bt->
line_bytes);
else
RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
bt->line_bytes);
RISC_INSTR(bt->buf_dma + buf_pos);
buf_pos += bt->line_bytes;
}
RISC_INSTR(RISC_SYNC | op_sync_orin | RISC_SYNC_VRO);
RISC_INSTR(0);
RISC_INSTR(RISC_JUMP);
RISC_INSTR(bt->risc_dma);
btwrite((bt->line_count << 16) | bt->line_bytes, BT878_APACK_LEN);
}
/*****************************/
/* Start/Stop grabbing funcs */
/*****************************/
void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
u32 irq_err_ignore)
{
u32 int_mask;
dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n", controlreg);
/* complete the writing of the risc dma program now we have
* the card specifics
*/
bt878_risc_program(bt, op_sync_orin);
controlreg &= ~0x1f;
controlreg |= 0x1b;
btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START);
/* original int mask had :
* 6 2 8 4 0
* 1111 1111 1000 0000 0000
* SCERR|OCERR|PABORT|RIPERR|FDSR|FTRGT|FBUS|RISCI
* Hacked for DST to:
* SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI
*/
int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT |
BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT |
BT878_AFBUS | BT878_ARISCI;
/* ignore pesky bits */
int_mask &= ~irq_err_ignore;
btwrite(int_mask, BT878_AINT_MASK);
btwrite(controlreg, BT878_AGPIO_DMA_CTL);
}
void bt878_stop(struct bt878 *bt)
{
u32 stat;
int i = 0;
dprintk("bt878 debug: bt878_stop\n");
btwrite(0, BT878_AINT_MASK);
btand(~0x13, BT878_AGPIO_DMA_CTL);
do {
stat = btread(BT878_AINT_STAT);
if (!(stat & BT878_ARISC_EN))
break;
i++;
} while (i < 500);
dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",
bt->nr, i, stat);
}
EXPORT_SYMBOL(bt878_start);
EXPORT_SYMBOL(bt878_stop);
/*****************************/
/* Interrupt service routine */
/*****************************/
static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs)
{
u32 stat, astat, mask;
int count;
struct bt878 *bt;
bt = (struct bt878 *) dev_id;
count = 0;
while (1) {
stat = btread(BT878_AINT_STAT);
mask = btread(BT878_AINT_MASK);
if (!(astat = (stat & mask)))
return IRQ_NONE; /* this interrupt is not for me */
/* dprintk("bt878(%d) debug: irq count %d, stat 0x%8.8x, mask 0x%8.8x\n",bt->nr,count,stat,mask); */
btwrite(astat, BT878_AINT_STAT); /* try to clear interupt condition */
if (astat & (BT878_ASCERR | BT878_AOCERR)) {
if (bt878_verbose) {
printk("bt878(%d): irq%s%s risc_pc=%08x\n",
bt->nr,
(astat & BT878_ASCERR) ? " SCERR" :
"",
(astat & BT878_AOCERR) ? " OCERR" :
"", btread(BT878_ARISC_PC));
}
}
if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) {
if (bt878_verbose) {
printk
("bt878(%d): irq%s%s%s risc_pc=%08x\n",
bt->nr,
(astat & BT878_APABORT) ? " PABORT" :
"",
(astat & BT878_ARIPERR) ? " RIPERR" :
"",
(astat & BT878_APPERR) ? " PPERR" :
"", btread(BT878_ARISC_PC));
}
}
if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) {
if (bt878_verbose) {
printk
("bt878(%d): irq%s%s%s risc_pc=%08x\n",
bt->nr,
(astat & BT878_AFDSR) ? " FDSR" : "",
(astat & BT878_AFTRGT) ? " FTRGT" :
"",
(astat & BT878_AFBUS) ? " FBUS" : "",
btread(BT878_ARISC_PC));
}
}
if (astat & BT878_ARISCI) {
bt->finished_block = (stat & BT878_ARISCS) >> 28;
tasklet_schedule(&bt->tasklet);
break;
}
count++;
if (count > 20) {
btwrite(0, BT878_AINT_MASK);
printk(KERN_ERR
"bt878(%d): IRQ lockup, cleared int mask\n",
bt->nr);
break;
}
}
return IRQ_HANDLED;
}
int
bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp)
{
int retval;
retval = 0;
if (down_interruptible (&bt->gpio_lock))
return -ERESTARTSYS;
/* special gpio signal */
switch (cmd) {
case DST_IG_ENABLE:
// dprintk("dvb_bt8xx: dst enable mask 0x%02x enb 0x%02x \n", mp->dstg.enb.mask, mp->dstg.enb.enable);
retval = bttv_gpio_enable(bt->bttv_nr,
mp->enb.mask,
mp->enb.enable);
break;
case DST_IG_WRITE:
// dprintk("dvb_bt8xx: dst write gpio mask 0x%02x out 0x%02x\n", mp->dstg.outp.mask, mp->dstg.outp.highvals);
retval = bttv_write_gpio(bt->bttv_nr,
mp->outp.mask,
mp->outp.highvals);
break;
case DST_IG_READ:
/* read */
retval = bttv_read_gpio(bt->bttv_nr, &mp->rd.value);
// dprintk("dvb_bt8xx: dst read gpio 0x%02x\n", (unsigned)mp->dstg.rd.value);
break;
case DST_IG_TS:
/* Set packet size */
bt->TS_Size = mp->psize;
break;
default:
retval = -EINVAL;
break;
}
up(&bt->gpio_lock);
return retval;
}
EXPORT_SYMBOL(bt878_device_control);
struct bt878 *bt878_find_by_i2c_adap(struct i2c_adapter *adapter)
{
unsigned int card_nr;
printk("bt878 find by dvb adap: checking \"%s\"\n",adapter->name);
for (card_nr = 0; card_nr < bt878_num; card_nr++) {
if (bt878[card_nr].adapter == adapter)
return &bt878[card_nr];
}
printk("bt878 find by dvb adap: NOT found \"%s\"\n",adapter->name);
return NULL;
}
EXPORT_SYMBOL(bt878_find_by_i2c_adap);
/***********************/
/* PCI device handling */
/***********************/
static int __devinit bt878_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
int result;
unsigned char lat;
struct bt878 *bt;
#if defined(__powerpc__)
unsigned int cmd;
#endif
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num);
if (pci_enable_device(dev))
return -EIO;
bt = &bt878[bt878_num];
bt->dev = dev;
bt->nr = bt878_num;
bt->shutdown = 0;
bt->id = dev->device;
bt->irq = dev->irq;
bt->bt878_adr = pci_resource_start(dev, 0);
if (!request_mem_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0), "bt878")) {
result = -EBUSY;
goto fail0;
}
pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
bt878_num, bt->id, bt->revision, dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
printk("irq: %d, latency: %d, memory: 0x%lx\n",
bt->irq, lat, bt->bt878_adr);
#if defined(__powerpc__)
/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
/* response on cards with no firmware is not enabled by OF */
pci_read_config_dword(dev, PCI_COMMAND, &cmd);
cmd = (cmd | PCI_COMMAND_MEMORY);
pci_write_config_dword(dev, PCI_COMMAND, cmd);
#endif
#ifdef __sparc__
bt->bt878_mem = (unsigned char *) bt->bt878_adr;
#else
bt->bt878_mem = ioremap(bt->bt878_adr, 0x1000);
#endif
/* clear interrupt mask */
btwrite(0, BT848_INT_MASK);
result = request_irq(bt->irq, bt878_irq,
SA_SHIRQ | SA_INTERRUPT, "bt878",
(void *) bt);
if (result == -EINVAL) {
printk(KERN_ERR "bt878(%d): Bad irq number or handler\n",
bt878_num);
goto fail1;
}
if (result == -EBUSY) {
printk(KERN_ERR
"bt878(%d): IRQ %d busy, change your PnP config in BIOS\n",
bt878_num, bt->irq);
goto fail1;
}
if (result < 0)
goto fail1;
pci_set_master(dev);
pci_set_drvdata(dev, bt);
/* if(init_bt878(btv) < 0) {
bt878_remove(dev);
return -EIO;
}
*/
if ((result = bt878_mem_alloc(bt))) {
printk("bt878: failed to allocate memory!\n");
goto fail2;
}
bt878_make_risc(bt);
btwrite(0, BT878_AINT_MASK);
bt878_num++;
return 0;
fail2:
free_irq(bt->irq, bt);
fail1:
release_mem_region(pci_resource_start(bt->dev, 0),
pci_resource_len(bt->dev, 0));
fail0:
pci_disable_device(dev);
return result;
}
static void __devexit bt878_remove(struct pci_dev *pci_dev)
{
u8 command;
struct bt878 *bt = pci_get_drvdata(pci_dev);
if (bt878_verbose)
printk("bt878(%d): unloading\n", bt->nr);
/* turn off all capturing, DMA and IRQs */
btand(~0x13, BT878_AGPIO_DMA_CTL);
/* first disable interrupts before unmapping the memory! */
btwrite(0, BT878_AINT_MASK);
btwrite(~0U, BT878_AINT_STAT);
/* disable PCI bus-mastering */
pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
/* Should this be &=~ ?? */
command &= ~PCI_COMMAND_MASTER;
pci_write_config_byte(bt->dev, PCI_COMMAND, command);
free_irq(bt->irq, bt);
printk(KERN_DEBUG "bt878_mem: 0x%p.\n", bt->bt878_mem);
if (bt->bt878_mem)
iounmap(bt->bt878_mem);
release_mem_region(pci_resource_start(bt->dev, 0),
pci_resource_len(bt->dev, 0));
/* wake up any waiting processes
because shutdown flag is set, no new processes (in this queue)
are expected
*/
bt->shutdown = 1;
bt878_mem_free(bt);
pci_set_drvdata(pci_dev, NULL);
pci_disable_device(pci_dev);
return;
}
static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BROOKTREE_878,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
static struct pci_driver bt878_pci_driver = {
.name = "bt878",
.id_table = bt878_pci_tbl,
.probe = bt878_probe,
.remove = bt878_remove,
};
static int bt878_pci_driver_registered = 0;
/*******************************/
/* Module management functions */
/*******************************/
static int bt878_init_module(void)
{
bt878_num = 0;
bt878_pci_driver_registered = 0;
printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n",
(BT878_VERSION_CODE >> 16) & 0xff,
(BT878_VERSION_CODE >> 8) & 0xff,
BT878_VERSION_CODE & 0xff);
/*
bt878_check_chipset();
*/
/* later we register inside of bt878_find_audio_dma()
* because we may want to ignore certain cards */
bt878_pci_driver_registered = 1;
return pci_module_init(&bt878_pci_driver);
}
static void bt878_cleanup_module(void)
{
if (bt878_pci_driver_registered) {
bt878_pci_driver_registered = 0;
pci_unregister_driver(&bt878_pci_driver);
}
return;
}
module_init(bt878_init_module);
module_exit(bt878_cleanup_module);
//MODULE_AUTHOR("XXX");
MODULE_LICENSE("GPL");
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@@ -0,0 +1,146 @@
/*
bt878.h - Bt878 audio module (register offsets)
Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
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.
*/
#ifndef _BT878_H_
#define _BT878_H_
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include "bt848.h"
#include "bttv.h"
#define BT878_VERSION_CODE 0x000000
#define BT878_AINT_STAT 0x100
#define BT878_ARISCS (0xf<<28)
#define BT878_ARISC_EN (1<<27)
#define BT878_ASCERR (1<<19)
#define BT878_AOCERR (1<<18)
#define BT878_APABORT (1<<17)
#define BT878_ARIPERR (1<<16)
#define BT878_APPERR (1<<15)
#define BT878_AFDSR (1<<14)
#define BT878_AFTRGT (1<<13)
#define BT878_AFBUS (1<<12)
#define BT878_ARISCI (1<<11)
#define BT878_AOFLOW (1<<3)
#define BT878_AINT_MASK 0x104
#define BT878_AGPIO_DMA_CTL 0x10c
#define BT878_A_GAIN (0xf<<28)
#define BT878_A_G2X (1<<27)
#define BT878_A_PWRDN (1<<26)
#define BT878_A_SEL (3<<24)
#define BT878_DA_SCE (1<<23)
#define BT878_DA_LRI (1<<22)
#define BT878_DA_MLB (1<<21)
#define BT878_DA_LRD (0x1f<<16)
#define BT878_DA_DPM (1<<15)
#define BT878_DA_SBR (1<<14)
#define BT878_DA_ES2 (1<<13)
#define BT878_DA_LMT (1<<12)
#define BT878_DA_SDR (0xf<<8)
#define BT878_DA_IOM (3<<6)
#define BT878_DA_APP (1<<5)
#define BT878_ACAP_EN (1<<4)
#define BT878_PKTP (3<<2)
#define BT878_RISC_EN (1<<1)
#define BT878_FIFO_EN 1
#define BT878_APACK_LEN 0x110
#define BT878_AFP_LEN (0xff<<16)
#define BT878_ALP_LEN 0xfff
#define BT878_ARISC_START 0x114
#define BT878_ARISC_PC 0x120
/* BT878 FUNCTION 0 REGISTERS */
#define BT878_GPIO_DMA_CTL 0x10c
/* Interrupt register */
#define BT878_INT_STAT 0x100
#define BT878_INT_MASK 0x104
#define BT878_I2CRACK (1<<25)
#define BT878_I2CDONE (1<<8)
#define BT878_MAX 4
#define BT878_RISC_SYNC_MASK (1 << 15)
extern int bt878_num;
extern struct bt878 bt878[BT878_MAX];
struct bt878 {
struct semaphore gpio_lock;
unsigned int nr;
unsigned int bttv_nr;
struct i2c_adapter *adapter;
struct pci_dev *dev;
unsigned int id;
unsigned int TS_Size;
unsigned char revision;
unsigned int irq;
unsigned long bt878_adr;
volatile void __iomem *bt878_mem; /* function 1 */
volatile u32 finished_block;
volatile u32 last_block;
u32 block_count;
u32 block_bytes;
u32 line_bytes;
u32 line_count;
u32 buf_size;
u8 *buf_cpu;
dma_addr_t buf_dma;
u32 risc_size;
u32 *risc_cpu;
dma_addr_t risc_dma;
u32 risc_pos;
struct tasklet_struct tasklet;
int shutdown;
};
void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
u32 irq_err_ignore);
void bt878_stop(struct bt878 *bt);
#if defined(__powerpc__) /* big-endian */
extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
{
__asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val),
"r"(addr));
__asm__ __volatile__("eieio":::"memory");
}
#define bmtwrite(dat,adr) io_st_le32((adr),(dat))
#define bmtread(adr) ld_le32((adr))
#else
#define bmtwrite(dat,adr) writel((dat), (adr))
#define bmtread(adr) readl(adr)
#endif
#endif

View File

@@ -0,0 +1 @@
!<arch>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/*
Frontend-driver for TwinHan DST Frontend
Copyright (C) 2003 Jamie Honan
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.
*/
#ifndef DST_H
#define DST_H
#include <linux/dvb/frontend.h>
#include <linux/device.h>
#include "bt878.h"
struct dst_config
{
/* the demodulator's i2c address */
u8 demod_address;
};
extern struct dvb_frontend* dst_attach(const struct dst_config* config,
struct i2c_adapter* i2c,
struct bt878 *bt);
#endif // DST_H

View File

@@ -0,0 +1,37 @@
/*
* dst-bt878.h: part of the DST driver for the TwinHan DST Frontend
*
* Copyright (C) 2003 Jamie Honan
*/
struct dst_gpio_enable {
u32 mask;
u32 enable;
};
struct dst_gpio_output {
u32 mask;
u32 highvals;
};
struct dst_gpio_read {
unsigned long value;
};
union dst_gpio_packet {
struct dst_gpio_enable enb;
struct dst_gpio_output outp;
struct dst_gpio_read rd;
int psize;
};
#define DST_IG_ENABLE 0
#define DST_IG_WRITE 1
#define DST_IG_READ 2
#define DST_IG_TS 3
struct bt878;
int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
struct bt878 *bt878_find_by_i2c_adap(struct i2c_adapter *adap);

View File

@@ -0,0 +1,649 @@
/*
* Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
*
* 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/bitops.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb-bt8xx.h"
#include "bt878.h"
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk( args... ) \
do { \
if (debug) printk(KERN_DEBUG args); \
} while (0)
static void dvb_bt8xx_task(unsigned long data)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data;
//printk("%d ", card->bt->finished_block);
while (card->bt->last_block != card->bt->finished_block) {
(card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
(&card->demux,
&card->bt->buf_cpu[card->bt->last_block *
card->bt->block_bytes],
card->bt->block_bytes);
card->bt->last_block = (card->bt->last_block + 1) %
card->bt->block_count;
}
}
static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct dvb_bt8xx_card *card = dvbdmx->priv;
int rc;
dprintk("dvb_bt8xx: start_feed\n");
if (!dvbdmx->dmx.frontend)
return -EINVAL;
down(&card->lock);
card->nfeeds++;
rc = card->nfeeds;
if (card->nfeeds == 1)
bt878_start(card->bt, card->gpio_mode,
card->op_sync_orin, card->irq_err_ignore);
up(&card->lock);
return rc;
}
static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct dvb_bt8xx_card *card = dvbdmx->priv;
dprintk("dvb_bt8xx: stop_feed\n");
if (!dvbdmx->dmx.frontend)
return -EINVAL;
down(&card->lock);
card->nfeeds--;
if (card->nfeeds == 0)
bt878_stop(card->bt);
up(&card->lock);
return 0;
}
static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
{
if ((adev->subsystem_vendor == bdev->subsystem_vendor) &&
(adev->subsystem_device == bdev->subsystem_device) &&
(adev->bus->number == bdev->bus->number) &&
(PCI_SLOT(adev->devfn) == PCI_SLOT(bdev->devfn)))
return 1;
return 0;
}
static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
{
unsigned int card_nr;
/* Hmm, n squared. Hope n is small */
for (card_nr = 0; card_nr < bt878_num; card_nr++) {
if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
return &bt878[card_nr];
}
return NULL;
}
static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
{
static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };
static u8 mt352_reset [] = { 0x50, 0x80 };
static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 };
static u8 mt352_gpp_ctl_cfg [] = { 0x75, 0x33 };
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
udelay(2000);
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
return 0;
}
static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
{
u32 div;
unsigned char bs = 0;
unsigned char cp = 0;
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
if (params->frequency < 542000000) cp = 0xb4;
else if (params->frequency < 771000000) cp = 0xbc;
else cp = 0xf4;
if (params->frequency == 0) bs = 0x03;
else if (params->frequency < 443250000) bs = 0x02;
else bs = 0x08;
pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = cp;
pllbuf[4] = bs;
return 0;
}
static struct mt352_config thomson_dtt7579_config = {
.demod_address = 0x0f,
.demod_init = thomson_dtt7579_demod_init,
.pll_set = thomson_dtt7579_pll_set,
};
static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
u8 cfg, cpump, band_select;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
div = (36000000 + params->frequency + 83333) / 166666;
cfg = 0x88;
if (params->frequency < 175000000) cpump = 2;
else if (params->frequency < 390000000) cpump = 1;
else if (params->frequency < 470000000) cpump = 2;
else if (params->frequency < 750000000) cpump = 2;
else cpump = 3;
if (params->frequency < 175000000) band_select = 0x0e;
else if (params->frequency < 470000000) band_select = 0x05;
else band_select = 0x03;
data[0] = (div >> 8) & 0x7f;
data[1] = div & 0xff;
data[2] = ((div >> 10) & 0x60) | cfg;
data[3] = cpump | band_select;
i2c_transfer(card->i2c_adapter, &msg, 1);
return (div * 166666 - 36000000);
}
static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
{
struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
return request_firmware(fw, name, &bt->bt->dev->dev);
}
struct sp887x_config microtune_mt7202dtf_config = {
.demod_address = 0x70,
.pll_set = microtune_mt7202dtf_pll_set,
.request_firmware = microtune_mt7202dtf_request_firmware,
};
static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
{
static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
static u8 mt352_reset [] = { 0x50, 0x80 };
static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
0x00, 0xFF, 0x00, 0x40, 0x40 };
static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
udelay(2000);
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
udelay(2000);
mt352_write(fe, mt352_av771_extra,sizeof(mt352_av771_extra));
mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
return 0;
}
static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
{
u32 div;
unsigned char bs = 0;
unsigned char cp = 0;
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
if (params->frequency < 150000000) cp = 0xB4;
else if (params->frequency < 173000000) cp = 0xBC;
else if (params->frequency < 250000000) cp = 0xB4;
else if (params->frequency < 400000000) cp = 0xBC;
else if (params->frequency < 420000000) cp = 0xF4;
else if (params->frequency < 470000000) cp = 0xFC;
else if (params->frequency < 600000000) cp = 0xBC;
else if (params->frequency < 730000000) cp = 0xF4;
else cp = 0xFC;
if (params->frequency < 150000000) bs = 0x01;
else if (params->frequency < 173000000) bs = 0x01;
else if (params->frequency < 250000000) bs = 0x02;
else if (params->frequency < 400000000) bs = 0x02;
else if (params->frequency < 420000000) bs = 0x02;
else if (params->frequency < 470000000) bs = 0x02;
else if (params->frequency < 600000000) bs = 0x08;
else if (params->frequency < 730000000) bs = 0x08;
else bs = 0x08;
pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = cp;
pllbuf[4] = bs;
return 0;
}
static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
.demod_address = 0x0f,
.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
.pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
};
static struct dst_config dst_config = {
.demod_address = 0x55,
};
static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };
div = (params->frequency + 36166667) / 166667;
buf[0] = (div >> 8) & 0x7F;
buf[1] = div & 0xFF;
buf[2] = 0x85;
if ((params->frequency >= 47000000) && (params->frequency < 153000000))
buf[3] = 0x01;
else if ((params->frequency >= 153000000) && (params->frequency < 430000000))
buf[3] = 0x02;
else if ((params->frequency >= 430000000) && (params->frequency < 824000000))
buf[3] = 0x0C;
else if ((params->frequency >= 824000000) && (params->frequency < 863000000))
buf[3] = 0x8C;
else
return -EINVAL;
i2c_transfer(card->i2c_adapter, &msg, 1);
return 0;
}
static struct nxt6000_config vp3021_alps_tded4_config = {
.demod_address = 0x0a,
.clock_inversion = 1,
.pll_set = vp3021_alps_tded4_pll_set,
};
static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
{
switch(type) {
#ifdef BTTV_DVICO_DVBT_LITE
case BTTV_DVICO_DVBT_LITE:
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
card->fe->ops->info.frequency_max = 862000000;
break;
}
break;
#endif
#ifdef BTTV_TWINHAN_VP3021
case BTTV_TWINHAN_VP3021:
#else
case BTTV_NEBULA_DIGITV:
#endif
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
if (card->fe != NULL) {
break;
}
break;
case BTTV_AVDVBT_761:
card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
if (card->fe != NULL) {
break;
}
break;
case BTTV_AVDVBT_771:
card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
if (card->fe != NULL) {
card->fe->ops->info.frequency_min = 174000000;
card->fe->ops->info.frequency_max = 862000000;
break;
}
break;
case BTTV_TWINHAN_DST:
card->fe = dst_attach(&dst_config, card->i2c_adapter, card->bt);
if (card->fe != NULL) {
break;
}
break;
}
if (card->fe == NULL) {
printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
card->bt->dev->vendor,
card->bt->dev->device,
card->bt->dev->subsystem_vendor,
card->bt->dev->subsystem_device);
} else {
if (dvb_register_frontend(card->dvb_adapter, card->fe)) {
printk("dvb-bt8xx: Frontend registration failed!\n");
if (card->fe->ops->release)
card->fe->ops->release(card->fe);
card->fe = NULL;
}
}
}
static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
{
int result;
if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
THIS_MODULE)) < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
return result;
}
card->dvb_adapter->priv = card;
card->bt->adapter = card->i2c_adapter;
memset(&card->demux, 0, sizeof(struct dvb_demux));
card->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING;
card->demux.priv = card;
card->demux.filternum = 256;
card->demux.feednum = 256;
card->demux.start_feed = dvb_bt8xx_start_feed;
card->demux.stop_feed = dvb_bt8xx_stop_feed;
card->demux.write_to_decoder = NULL;
if ((result = dvb_dmx_init(&card->demux)) < 0) {
printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
dvb_unregister_adapter(card->dvb_adapter);
return result;
}
card->dmxdev.filternum = 256;
card->dmxdev.demux = &card->demux.dmx;
card->dmxdev.capabilities = 0;
if ((result = dvb_dmxdev_init(&card->dmxdev, card->dvb_adapter)) < 0) {
printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);
dvb_dmx_release(&card->demux);
dvb_unregister_adapter(card->dvb_adapter);
return result;
}
card->fe_hw.source = DMX_FRONTEND_0;
if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
dvb_unregister_adapter(card->dvb_adapter);
return result;
}
card->fe_mem.source = DMX_MEMORY_FE;
if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem)) < 0) {
printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
dvb_unregister_adapter(card->dvb_adapter);
return result;
}
if ((result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw)) < 0) {
printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
dvb_unregister_adapter(card->dvb_adapter);
return result;
}
dvb_net_init(card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
frontend_init(card, type);
return 0;
}
static int dvb_bt8xx_probe(struct device *dev)
{
struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
struct dvb_bt8xx_card *card;
struct pci_dev* bttv_pci_dev;
int ret;
if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
return -ENOMEM;
memset(card, 0, sizeof(*card));
init_MUTEX(&card->lock);
card->bttv_nr = sub->core->nr;
strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
card->i2c_adapter = &sub->core->i2c_adap;
switch(sub->core->type)
{
/* case BTTV_PINNACLESAT: UNDEFINED HARDWARE */
#ifdef BTTV_DVICO_DVBT_LITE
case BTTV_DVICO_DVBT_LITE:
#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
/* 26, 15, 14, 6, 5
* A_PWRDN DA_DPM DA_SBR DA_IOM_DA
* DA_APP(parallel) */
break;
#ifdef BTTV_TWINHAN_VP3021
case BTTV_TWINHAN_VP3021:
#else
case BTTV_NEBULA_DIGITV:
#endif
case BTTV_AVDVBT_761:
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
/* A_PWRDN DA_SBR DA_APP (high speed serial) */
break;
case BTTV_AVDVBT_771: //case 0x07711461:
card->gpio_mode = 0x0400402B;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = 0;
/* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/
break;
case BTTV_TWINHAN_DST:
card->gpio_mode = 0x2204f2c;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR |
BT878_APPERR | BT878_AFBUS;
/* 25,21,14,11,10,9,8,3,2 then
* 0x33 = 5,4,1,0
* A_SEL=SML, DA_MLB, DA_SBR,
* DA_SDR=f, fifo trigger = 32 DWORDS
* IOM = 0 == audio A/D
* DPM = 0 == digital audio mode
* == async data parallel port
* then 0x33 (13 is set by start_capture)
* DA_APP = async data parallel port,
* ACAP_EN = 1,
* RISC+FIFO ENABLE */
break;
default:
printk(KERN_WARNING "dvb_bt8xx: Unknown bttv card type: %d.\n",
sub->core->type);
kfree(card);
return -ENODEV;
}
dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);
if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
printk("dvb_bt8xx: no pci device for card %d\n", card->bttv_nr);
kfree(card);
return -EFAULT;
}
if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
printk("dvb_bt8xx: unable to determine DMA core of card %d,\n",
card->bttv_nr);
printk("dvb_bt8xx: if you have the ALSA bt87x audio driver "
"installed, try removing it.\n");
kfree(card);
return -EFAULT;
}
init_MUTEX(&card->bt->gpio_lock);
card->bt->bttv_nr = sub->core->nr;
if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) {
kfree(card);
return ret;
}
dev_set_drvdata(dev, card);
return 0;
}
static int dvb_bt8xx_remove(struct device *dev)
{
struct dvb_bt8xx_card *card = dev_get_drvdata(dev);
dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
bt878_stop(card->bt);
tasklet_kill(&card->bt->tasklet);
dvb_net_release(&card->dvbnet);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
if (card->fe) dvb_unregister_frontend(card->fe);
dvb_unregister_adapter(card->dvb_adapter);
kfree(card);
return 0;
}
static struct bttv_sub_driver driver = {
.drv = {
.name = "dvb-bt8xx",
.probe = dvb_bt8xx_probe,
.remove = dvb_bt8xx_remove,
/* FIXME:
* .shutdown = dvb_bt8xx_shutdown,
* .suspend = dvb_bt8xx_suspend,
* .resume = dvb_bt8xx_resume,
*/
},
};
static int __init dvb_bt8xx_init(void)
{
return bttv_sub_register(&driver, "dvb");
}
static void __exit dvb_bt8xx_exit(void)
{
bttv_sub_unregister(&driver);
}
module_init(dvb_bt8xx_init);
module_exit(dvb_bt8xx_exit);
MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");
MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,52 @@
/*
* Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
* Copyright (C) 1999-2001 Ralph Metzler & Marcus Metzler for convergence integrated media GmbH
* Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
*
* 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/i2c.h>
#include "dvbdev.h"
#include "dvb_net.h"
#include "bttv.h"
#include "mt352.h"
#include "sp887x.h"
#include "dst.h"
#include "nxt6000.h"
struct dvb_bt8xx_card {
struct semaphore lock;
int nfeeds;
char card_name[32];
struct dvb_adapter *dvb_adapter;
struct bt878 *bt;
unsigned int bttv_nr;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
u32 gpio_mode;
u32 op_sync_orin;
u32 irq_err_ignore;
struct i2c_adapter *i2c_adapter;
struct dvb_net dvbnet;
struct dvb_frontend* fe;
};