summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/bt8xx
diff options
context:
space:
mode:
authorFlorian Schirmer <devnull@localhost>2003-01-21 18:59:21 +0000
committerFlorian Schirmer <devnull@localhost>2003-01-21 18:59:21 +0000
commit67c2cb401fed80bd2d5a2225d447785e7cc65408 (patch)
tree5ce01177af00963374857f62ce395979f5630ec7 /linux/drivers/media/dvb/bt8xx
parente9064d09febdcd05bc998f46cb5138cd5bca6bf7 (diff)
downloadmediapointer-dvb-s2-67c2cb401fed80bd2d5a2225d447785e7cc65408.tar.gz
mediapointer-dvb-s2-67c2cb401fed80bd2d5a2225d447785e7cc65408.tar.bz2
Add Bt8xx interface files (stolen from PCTV driver)
Diffstat (limited to 'linux/drivers/media/dvb/bt8xx')
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt848.h358
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt878.c603
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt878.h109
3 files changed, 1070 insertions, 0 deletions
diff --git a/linux/drivers/media/dvb/bt8xx/bt848.h b/linux/drivers/media/dvb/bt8xx/bt848.h
new file mode 100644
index 000000000..7015fd825
--- /dev/null
+++ b/linux/drivers/media/dvb/bt8xx/bt848.h
@@ -0,0 +1,358 @@
+/*
+ bt848.h - Bt848 register offsets
+
+ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.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 _BT848_H_
+#define _BT848_H_
+
+#ifndef PCI_VENDOR_ID_BROOKTREE
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#endif
+#ifndef PCI_DEVICE_ID_BT848
+#define PCI_DEVICE_ID_BT848 0x350
+#endif
+#ifndef PCI_DEVICE_ID_BT849
+#define PCI_DEVICE_ID_BT849 0x351
+#endif
+#ifndef PCI_DEVICE_ID_BT878
+#define PCI_DEVICE_ID_BT878 0x36e
+#endif
+#ifndef PCI_DEVICE_ID_BT879
+#define PCI_DEVICE_ID_BT879 0x36f
+#endif
+
+
+/* Brooktree 848 registers */
+
+#define BT848_DSTATUS 0x000
+#define BT848_DSTATUS_PRES (1<<7)
+#define BT848_DSTATUS_HLOC (1<<6)
+#define BT848_DSTATUS_FIELD (1<<5)
+#define BT848_DSTATUS_NUML (1<<4)
+#define BT848_DSTATUS_CSEL (1<<3)
+#define BT848_DSTATUS_PLOCK (1<<2)
+#define BT848_DSTATUS_LOF (1<<1)
+#define BT848_DSTATUS_COF (1<<0)
+
+#define BT848_IFORM 0x004
+#define BT848_IFORM_HACTIVE (1<<7)
+#define BT848_IFORM_MUXSEL (3<<5)
+#define BT848_IFORM_MUX0 (2<<5)
+#define BT848_IFORM_MUX1 (3<<5)
+#define BT848_IFORM_MUX2 (1<<5)
+#define BT848_IFORM_XTSEL (3<<3)
+#define BT848_IFORM_XT0 (1<<3)
+#define BT848_IFORM_XT1 (2<<3)
+#define BT848_IFORM_XTAUTO (3<<3)
+#define BT848_IFORM_XTBOTH (3<<3)
+#define BT848_IFORM_NTSC 1
+#define BT848_IFORM_NTSC_J 2
+#define BT848_IFORM_PAL_BDGHI 3
+#define BT848_IFORM_PAL_M 4
+#define BT848_IFORM_PAL_N 5
+#define BT848_IFORM_SECAM 6
+#define BT848_IFORM_PAL_NC 7
+#define BT848_IFORM_AUTO 0
+#define BT848_IFORM_NORM 7
+
+#define BT848_TDEC 0x008
+#define BT848_TDEC_DEC_FIELD (1<<7)
+#define BT848_TDEC_FLDALIGN (1<<6)
+#define BT848_TDEC_DEC_RAT (0x1f)
+
+#define BT848_E_CROP 0x00C
+#define BT848_O_CROP 0x08C
+
+#define BT848_E_VDELAY_LO 0x010
+#define BT848_O_VDELAY_LO 0x090
+
+#define BT848_E_VACTIVE_LO 0x014
+#define BT848_O_VACTIVE_LO 0x094
+
+#define BT848_E_HDELAY_LO 0x018
+#define BT848_O_HDELAY_LO 0x098
+
+#define BT848_E_HACTIVE_LO 0x01C
+#define BT848_O_HACTIVE_LO 0x09C
+
+#define BT848_E_HSCALE_HI 0x020
+#define BT848_O_HSCALE_HI 0x0A0
+
+#define BT848_E_HSCALE_LO 0x024
+#define BT848_O_HSCALE_LO 0x0A4
+
+#define BT848_BRIGHT 0x028
+
+#define BT848_E_CONTROL 0x02C
+#define BT848_O_CONTROL 0x0AC
+#define BT848_CONTROL_LNOTCH (1<<7)
+#define BT848_CONTROL_COMP (1<<6)
+#define BT848_CONTROL_LDEC (1<<5)
+#define BT848_CONTROL_CBSENSE (1<<4)
+#define BT848_CONTROL_CON_MSB (1<<2)
+#define BT848_CONTROL_SAT_U_MSB (1<<1)
+#define BT848_CONTROL_SAT_V_MSB (1<<0)
+
+#define BT848_CONTRAST_LO 0x030
+#define BT848_SAT_U_LO 0x034
+#define BT848_SAT_V_LO 0x038
+#define BT848_HUE 0x03C
+
+#define BT848_E_SCLOOP 0x040
+#define BT848_O_SCLOOP 0x0C0
+#define BT848_SCLOOP_CAGC (1<<6)
+#define BT848_SCLOOP_CKILL (1<<5)
+#define BT848_SCLOOP_HFILT_AUTO (0<<3)
+#define BT848_SCLOOP_HFILT_CIF (1<<3)
+#define BT848_SCLOOP_HFILT_QCIF (2<<3)
+#define BT848_SCLOOP_HFILT_ICON (3<<3)
+
+#define BT848_SCLOOP_PEAK (1<<7)
+#define BT848_SCLOOP_HFILT_MINP (1<<3)
+#define BT848_SCLOOP_HFILT_MEDP (2<<3)
+#define BT848_SCLOOP_HFILT_MAXP (3<<3)
+
+
+#define BT848_OFORM 0x048
+#define BT848_OFORM_RANGE (1<<7)
+#define BT848_OFORM_CORE0 (0<<5)
+#define BT848_OFORM_CORE8 (1<<5)
+#define BT848_OFORM_CORE16 (2<<5)
+#define BT848_OFORM_CORE32 (3<<5)
+
+#define BT848_E_VSCALE_HI 0x04C
+#define BT848_O_VSCALE_HI 0x0CC
+#define BT848_VSCALE_YCOMB (1<<7)
+#define BT848_VSCALE_COMB (1<<6)
+#define BT848_VSCALE_INT (1<<5)
+#define BT848_VSCALE_HI 15
+
+#define BT848_E_VSCALE_LO 0x050
+#define BT848_O_VSCALE_LO 0x0D0
+#define BT848_TEST 0x054
+#define BT848_ADELAY 0x060
+#define BT848_BDELAY 0x064
+
+#define BT848_ADC 0x068
+#define BT848_ADC_RESERVED (2<<6)
+#define BT848_ADC_SYNC_T (1<<5)
+#define BT848_ADC_AGC_EN (1<<4)
+#define BT848_ADC_CLK_SLEEP (1<<3)
+#define BT848_ADC_Y_SLEEP (1<<2)
+#define BT848_ADC_C_SLEEP (1<<1)
+#define BT848_ADC_CRUSH (1<<0)
+
+#define BT848_E_VTC 0x06C
+#define BT848_O_VTC 0x0EC
+#define BT848_VTC_HSFMT (1<<7)
+#define BT848_VTC_VFILT_2TAP 0
+#define BT848_VTC_VFILT_3TAP 1
+#define BT848_VTC_VFILT_4TAP 2
+#define BT848_VTC_VFILT_5TAP 3
+
+#define BT848_SRESET 0x07C
+
+#define BT848_COLOR_FMT 0x0D4
+#define BT848_COLOR_FMT_O_RGB32 (0<<4)
+#define BT848_COLOR_FMT_O_RGB24 (1<<4)
+#define BT848_COLOR_FMT_O_RGB16 (2<<4)
+#define BT848_COLOR_FMT_O_RGB15 (3<<4)
+#define BT848_COLOR_FMT_O_YUY2 (4<<4)
+#define BT848_COLOR_FMT_O_BtYUV (5<<4)
+#define BT848_COLOR_FMT_O_Y8 (6<<4)
+#define BT848_COLOR_FMT_O_RGB8 (7<<4)
+#define BT848_COLOR_FMT_O_YCrCb422 (8<<4)
+#define BT848_COLOR_FMT_O_YCrCb411 (9<<4)
+#define BT848_COLOR_FMT_O_RAW (14<<4)
+#define BT848_COLOR_FMT_E_RGB32 0
+#define BT848_COLOR_FMT_E_RGB24 1
+#define BT848_COLOR_FMT_E_RGB16 2
+#define BT848_COLOR_FMT_E_RGB15 3
+#define BT848_COLOR_FMT_E_YUY2 4
+#define BT848_COLOR_FMT_E_BtYUV 5
+#define BT848_COLOR_FMT_E_Y8 6
+#define BT848_COLOR_FMT_E_RGB8 7
+#define BT848_COLOR_FMT_E_YCrCb422 8
+#define BT848_COLOR_FMT_E_YCrCb411 9
+#define BT848_COLOR_FMT_E_RAW 14
+
+#define BT848_COLOR_FMT_RGB32 0x00
+#define BT848_COLOR_FMT_RGB24 0x11
+#define BT848_COLOR_FMT_RGB16 0x22
+#define BT848_COLOR_FMT_RGB15 0x33
+#define BT848_COLOR_FMT_YUY2 0x44
+#define BT848_COLOR_FMT_BtYUV 0x55
+#define BT848_COLOR_FMT_Y8 0x66
+#define BT848_COLOR_FMT_RGB8 0x77
+#define BT848_COLOR_FMT_YCrCb422 0x88
+#define BT848_COLOR_FMT_YCrCb411 0x99
+#define BT848_COLOR_FMT_RAW 0xee
+
+#define BT848_COLOR_CTL 0x0D8
+#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7)
+#define BT848_COLOR_CTL_COLOR_BARS (1<<6)
+#define BT848_COLOR_CTL_RGB_DED (1<<5)
+#define BT848_COLOR_CTL_GAMMA (1<<4)
+#define BT848_COLOR_CTL_WSWAP_ODD (1<<3)
+#define BT848_COLOR_CTL_WSWAP_EVEN (1<<2)
+#define BT848_COLOR_CTL_BSWAP_ODD (1<<1)
+#define BT848_COLOR_CTL_BSWAP_EVEN (1<<0)
+
+#define BT848_CAP_CTL 0x0DC
+#define BT848_CAP_CTL_DITH_FRAME (1<<4)
+#define BT848_CAP_CTL_CAPTURE_VBI_ODD (1<<3)
+#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
+#define BT848_CAP_CTL_CAPTURE_ODD (1<<1)
+#define BT848_CAP_CTL_CAPTURE_EVEN (1<<0)
+
+#define BT848_VBI_PACK_SIZE 0x0E0
+
+#define BT848_VBI_PACK_DEL 0x0E4
+#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc
+#define BT848_VBI_PACK_DEL_EXT_FRAME 2
+#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1
+
+
+#define BT848_INT_STAT 0x100
+#define BT848_INT_MASK 0x104
+
+#define BT848_INT_ETBF (1<<23)
+
+#define BT848_INT_RISCS (0xf<<28)
+#define BT848_INT_RISC_EN (1<<27)
+#define BT848_INT_RACK (1<<25)
+#define BT848_INT_FIELD (1<<24)
+#define BT848_INT_SCERR (1<<19)
+#define BT848_INT_OCERR (1<<18)
+#define BT848_INT_PABORT (1<<17)
+#define BT848_INT_RIPERR (1<<16)
+#define BT848_INT_PPERR (1<<15)
+#define BT848_INT_FDSR (1<<14)
+#define BT848_INT_FTRGT (1<<13)
+#define BT848_INT_FBUS (1<<12)
+#define BT848_INT_RISCI (1<<11)
+#define BT848_INT_GPINT (1<<9)
+#define BT848_INT_I2CDONE (1<<8)
+#define BT848_INT_VPRES (1<<5)
+#define BT848_INT_HLOCK (1<<4)
+#define BT848_INT_OFLOW (1<<3)
+#define BT848_INT_HSYNC (1<<2)
+#define BT848_INT_VSYNC (1<<1)
+#define BT848_INT_FMTCHG (1<<0)
+
+
+#define BT848_GPIO_DMA_CTL 0x10C
+#define BT848_GPIO_DMA_CTL_GPINTC (1<<15)
+#define BT848_GPIO_DMA_CTL_GPINTI (1<<14)
+#define BT848_GPIO_DMA_CTL_GPWEC (1<<13)
+#define BT848_GPIO_DMA_CTL_GPIOMODE (3<<11)
+#define BT848_GPIO_DMA_CTL_GPCLKMODE (1<<10)
+#define BT848_GPIO_DMA_CTL_PLTP23_4 (0<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_8 (1<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_16 (2<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_32 (3<<6)
+#define BT848_GPIO_DMA_CTL_PLTP1_4 (0<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_8 (1<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_16 (2<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_32 (3<<4)
+#define BT848_GPIO_DMA_CTL_PKTP_4 (0<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_8 (1<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_16 (2<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_32 (3<<2)
+#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1)
+#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0)
+
+#define BT848_I2C 0x110
+#define BT848_I2C_DIV (0xf<<4)
+#define BT848_I2C_SYNC (1<<3)
+#define BT848_I2C_W3B (1<<2)
+#define BT848_I2C_SCL (1<<1)
+#define BT848_I2C_SDA (1<<0)
+
+
+#define BT848_RISC_STRT_ADD 0x114
+#define BT848_GPIO_OUT_EN 0x118
+#define BT848_GPIO_REG_INP 0x11C
+#define BT848_RISC_COUNT 0x120
+#define BT848_GPIO_DATA 0x200
+
+
+/* Bt848 RISC commands */
+
+/* only for the SYNC RISC command */
+#define BT848_FIFO_STATUS_FM1 0x06
+#define BT848_FIFO_STATUS_FM3 0x0e
+#define BT848_FIFO_STATUS_SOL 0x02
+#define BT848_FIFO_STATUS_EOL4 0x01
+#define BT848_FIFO_STATUS_EOL3 0x0d
+#define BT848_FIFO_STATUS_EOL2 0x09
+#define BT848_FIFO_STATUS_EOL1 0x05
+#define BT848_FIFO_STATUS_VRE 0x04
+#define BT848_FIFO_STATUS_VRO 0x0c
+#define BT848_FIFO_STATUS_PXV 0x00
+
+#define BT848_RISC_RESYNC (1<<15)
+
+/* WRITE and SKIP */
+/* disable which bytes of each DWORD */
+#define BT848_RISC_BYTE0 (1<<12)
+#define BT848_RISC_BYTE1 (1<<13)
+#define BT848_RISC_BYTE2 (1<<14)
+#define BT848_RISC_BYTE3 (1<<15)
+#define BT848_RISC_BYTE_ALL (0x0f<<12)
+#define BT848_RISC_BYTE_NONE 0
+/* cause RISCI */
+#define BT848_RISC_IRQ (1<<24)
+/* RISC command is last one in this line */
+#define BT848_RISC_EOL (1<<26)
+/* RISC command is first one in this line */
+#define BT848_RISC_SOL (1<<27)
+
+#define BT848_RISC_WRITE (0x01<<28)
+#define BT848_RISC_SKIP (0x02<<28)
+#define BT848_RISC_WRITEC (0x05<<28)
+#define BT848_RISC_JUMP (0x07<<28)
+#define BT848_RISC_SYNC (0x08<<28)
+
+#define BT848_RISC_WRITE123 (0x09<<28)
+#define BT848_RISC_SKIP123 (0x0a<<28)
+#define BT848_RISC_WRITE1S23 (0x0b<<28)
+
+
+
+/* Bt848A and higher only !! */
+#define BT848_TGLB 0x080
+#define BT848_TGCTRL 0x084
+#define BT848_FCAP 0x0E8
+#define BT848_PLL_F_LO 0x0F0
+#define BT848_PLL_F_HI 0x0F4
+
+#define BT848_PLL_XCI 0x0F8
+#define BT848_PLL_X (1<<7)
+#define BT848_PLL_C (1<<6)
+
+#define BT848_DVSIF 0x0FC
+
+/* Bt878 register */
+
+#define BT878_DEVCTRL 0x40
+#define BT878_EN_TBFX 0x02
+#define BT878_EN_VSFX 0x04
+
+#endif
diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c
new file mode 100644
index 000000000..8ade22161
--- /dev/null
+++ b/linux/drivers/media/dvb/bt8xx/bt878.c
@@ -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/version.h>
+#include <linux/module.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/wrapper.h>
+#include <linux/interrupt.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include "bt878.h"
+
+/**************************************/
+/* Miscellaneous utility definitions */
+/**************************************/
+
+unsigned int bt878_verbose = 1;
+unsigned int bt878_debug = 0;
+MODULE_PARM(bt878_verbose,"i");
+MODULE_PARM_DESC(bt878_verbose,"verbose startup messages, default is 1 (yes)");
+MODULE_PARM(bt878_debug,"i");
+MODULE_PARM_DESC(bt878_debug,"debug messages, default is 0 (no)");
+
+int bt878_num;
+struct bt878 bt878[BT878_MAX];
+
+EXPORT_SYMBOL(bt878_num);
+EXPORT_SYMBOL(bt878);
+
+#if defined(__powerpc__) /* big-endian */
+extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val)
+{
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : \
+ "=m" (*addr) : "r" (val), "r" (addr));
+ __asm__ __volatile__ ("eieio" : : : "memory");
+}
+#define btwrite(dat,adr) io_st_le32((unsigned *)(bt->bt878_mem+(adr)),(dat))
+#define btread(adr) ld_le32((unsigned *)(bt->bt878_mem+(adr)))
+#else
+#define btwrite(dat,adr) writel((dat), (char *) (bt->bt878_mem+(adr)))
+#define btread(adr) readl(bt->bt878_mem+(adr))
+#endif
+
+#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
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+#define MDEBUG(x) do { } while(0) /* Debug memory management */
+
+/* All taken from [DaveM] from the bttv driver
+ * I will not pretend that I understand this, but
+ * it seems to work.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed. We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if(pte_present(pte)) {
+ ret = (unsigned long) page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+
+ }
+ }
+ }
+ MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+ unsigned long kva, ret;
+
+ kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+ ret = virt_to_bus((void *)kva);
+ MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = virt_to_bus((void *)kva);
+ MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = __pa(kva);
+ MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+static void * rvmalloc(signed long size)
+{
+ void * mem;
+ unsigned long adr, page;
+
+ mem=vmalloc_32(size);
+ if (mem)
+ {
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ page = kvirt_to_pa(adr);
+ mem_map_reserve(virt_to_page(__va(page)));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ }
+ return mem;
+}
+
+static void rvfree(void * mem, signed long size)
+{
+ unsigned long adr, page;
+
+ if (mem)
+ {
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ page = kvirt_to_pa(adr);
+ mem_map_unreserve(virt_to_page(__va(page)));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ vfree(mem);
+ }
+}
+
+/*****************************/
+/* Buffer setup function(s) */
+/*****************************/
+
+int bt878_get_buffers(struct bt878 *bt, int bpl, int lpf, int nbufs, int sync)
+{
+ /* try to allocate nbufs buffers, 2<=nbufs<=16. Each buffer is
+ a "frame" bpl bytes wide and lpf lines high.
+ The buffers will be contiguous in kernel virtual space, but
+ will consist of discontinuous physical pages.
+ Set up a DMA program to read all these buffers in sequence,
+ and generate an interrupt at the start of each buffer.
+ if sync==1, insert a sync RISC op at the start of each buffer,
+ else don't.
+ */
+
+ unsigned long *pc, *pc2;
+ unsigned char *bp;
+ int i, j, size, rest;
+ unsigned long op;
+
+ dprintk("bt878 debug: bt878_get_buffers(%p, bpl=0x%x, lpf=0x%x, n=0x%x\n",bt,bpl,lpf,nbufs);
+ if(nbufs<2||nbufs>16) return -EINVAL;
+ if(bpl<0||bpl>4095) return -EINVAL;
+ if(lpf*nbufs<0||lpf*nbufs>255) return -EINVAL;
+ if(!bt) return -ENXIO;
+
+ /* stop a possibly running DMA operation */
+ btand(~0x0f,BT878_AGPIO_DMA_CTL);
+ i=btread(BT878_AGPIO_DMA_CTL);
+
+ if(bt->buffer) {rvfree(bt->buffer,bt->allocbufsize); bt->buffer=0; }
+ if(bt->riscprog) {rvfree(bt->riscprog,PAGE_SIZE); bt->riscprog=0;}
+
+ bt->framesize=bpl*lpf;
+ bt->buffersize=bt->framesize*nbufs;
+ bt->allocbufsize=(bpl*lpf*nbufs);
+ if(bt->allocbufsize&~PAGE_MASK)
+ bt->allocbufsize=(bt->allocbufsize&PAGE_MASK)+PAGE_SIZE;
+ dprintk("bt878 debug: allocating 0x%x bytes (min was 0x%x)\n",bt->allocbufsize,(bpl*lpf*nbufs));
+ if(!(bt->buffer=rvmalloc(bt->allocbufsize))) {
+ return -ENOMEM;
+ }
+ if(!(bt->riscprog=rvmalloc(PAGE_SIZE))) {
+ goto fail1;
+ }
+
+ dprintk("bt878 debug: buffer=%p, riscprog=%p\n",bt->buffer,bt->riscprog);
+ /* ok. We have the memory for the buffers. Let us set up the DMA prog */
+ pc=bt->riscprog;
+ bp=bt->buffer;
+ /* sync operation at the beginning of the program */
+ *pc++=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|
+ BT848_FIFO_STATUS_FM1|(0xf<<20));
+ *pc++=0;
+ for(i=0;i<nbufs;i++) {
+ for(j=0;j<lpf;j++) {
+ size=bpl;
+ rest=PAGE_SIZE-((unsigned int)bp&(~PAGE_MASK));
+ if(rest<size) size=rest;
+ op=BT848_RISC_WRITE|((~i)&0x0f)<<20|(i&0x0f)<<16|size
+ |BT848_RISC_SOL;
+ if(j==0) op|=BT848_RISC_IRQ;
+ if(size==bpl) op|=BT848_RISC_EOL;
+ *pc++=cpu_to_le32(op);
+ *pc++=cpu_to_le32(kvirt_to_bus((unsigned long)bp));
+ bp+=size;
+ if(size<bpl) {
+ size=bpl-size;
+ op=BT848_RISC_WRITE|((~i)&0x0f)<<20|(i&0x0f)<<16|size
+ |BT848_RISC_EOL;
+ *pc++=cpu_to_le32(op);
+ *pc++=cpu_to_le32(kvirt_to_bus((unsigned long)bp));
+ bp+=size;
+ if((pc-(unsigned long *)bt->riscprog)*sizeof(long)>PAGE_SIZE) goto fail2;
+ }
+ }
+ if(sync) {
+ *pc++=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|
+ BT848_FIFO_STATUS_FM1);
+ *pc++=0;
+ }
+ }
+ *pc++=cpu_to_le32(BT848_RISC_JUMP);
+ *pc++=cpu_to_le32(kvirt_to_bus((unsigned long)bt->riscprog));
+
+ btwrite(cpu_to_le32(bpl|((lpf*nbufs)<<16)),BT878_APACK_LEN);
+ btwrite(cpu_to_le32(kvirt_to_bus((unsigned long)bt->riscprog)),BT878_ARISC_START);
+
+ if(bt878_debug) {
+ for(pc2=bt->riscprog;pc2<pc;pc2++) printk("riscprog[%3.3x]=%8.8lx\n",
+ (pc2-(unsigned long *)(bt->riscprog)),*pc2);
+ }
+
+ bt->nbuffers=nbufs;
+
+ return 0;
+
+fail2:
+ if(bt->riscprog) {rvfree(bt->riscprog,PAGE_SIZE); bt->riscprog=0;}
+fail1:
+ if(bt->buffer) {rvfree(bt->buffer,bt->allocbufsize); bt->buffer=0; bt->allocbufsize=0;}
+ return -ENOMEM;
+}
+
+EXPORT_SYMBOL(bt878_get_buffers);
+
+/*****************************/
+/* Start/Stop grabbing funcs */
+/*****************************/
+
+void bt878_start(struct bt878 *bt, u32 controlreg)
+{
+ if(!bt->buffer||!bt->riscprog) bt878_get_buffers(bt,0x400,1,4,0);
+ /* this call to bt878_get_buffers ought to succeed... */
+ dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n",controlreg);
+ controlreg&=~0x1f;
+ controlreg|=0x1b;
+ btwrite(cpu_to_le32(kvirt_to_bus((unsigned long)bt->riscprog)),
+ BT878_ARISC_START);
+ if(bt->tasklet) tasklet_enable(bt->tasklet);
+ btwrite(0x000ff800,BT878_AINT_MASK);
+ btwrite(controlreg,BT878_AGPIO_DMA_CTL);
+}
+
+void bt878_stop(struct bt878 *bt)
+{
+ u32 stat;
+ int i=0;
+
+ btwrite(0,BT878_AINT_MASK);
+ btand(~0x1f,BT878_AGPIO_DMA_CTL);
+ dprintk("bt878 debug: bt878_stop\n");
+ do {
+ stat=btread(BT878_AINT_STAT);
+ if(!(stat&BT878_ARISC_EN)) break;
+ i++;
+ } while(i<500);
+ if(bt->tasklet) tasklet_disable(bt->tasklet);
+ 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 void 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; /* 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) {
+ spin_lock(&bt->s_lock);
+ bt->writebuf=(stat&BT878_ARISCS)>>28;
+ spin_unlock(&bt->s_lock);
+ wake_up_interruptible(&bt->readq);
+ if(bt->tasklet) tasklet_schedule(bt->tasklet);
+ return;
+ }
+ count++;
+ if(count>20) {
+ btwrite(0,BT878_AINT_MASK);
+ printk(KERN_ERR
+ "bt878(%d): IRQ lockup, cleared int mask\n", bt->nr);
+ break;
+ }
+ }
+}
+
+/***********************/
+/* 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);
+
+ bt=&bt878[bt878_num];
+ bt->dev=dev;
+ bt->nr = bt878_num;
+ init_waitqueue_head(&bt->readq);
+ bt->s_lock = SPIN_LOCK_UNLOCKED;
+ bt->shutdown=0;
+
+ bt->id=dev->device;
+ bt->irq=dev->irq;
+ bt->bt878_adr=pci_resource_start(dev,0);
+ if (pci_enable_device(dev))
+ return -EIO;
+ if (!request_mem_region(pci_resource_start(dev,0),
+ pci_resource_len(dev,0),
+ "bt878")) {
+ return -EBUSY;
+ }
+
+ 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;
+ }
+*/
+ bt->nbuffers=bt->allocbufsize=0;
+ bt->buffer=bt->riscprog=0;
+
+ 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));
+ 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(~15, BT878_AGPIO_DMA_CTL);
+
+ /* first disable interrupts before unmapping the memory! */
+ btwrite(0, BT878_AINT_MASK);
+ btwrite(~0x0UL,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;
+
+ if(bt->buffer) {rvfree(bt->buffer,bt->allocbufsize); bt->buffer=0;}
+ if(bt->riscprog) {rvfree(bt->riscprog,PAGE_SIZE); bt->riscprog=0;}
+
+ pci_set_drvdata(pci_dev, NULL);
+ 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,
+};
+
+/*******************************/
+/* Module management functions */
+/*******************************/
+
+int bt878_init_module(void)
+{
+ bt878_num = 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();
+*/
+ return pci_module_init(&bt878_pci_driver);
+}
+
+void bt878_cleanup_module(void)
+{
+ pci_unregister_driver(&bt878_pci_driver);
+ return;
+}
+
+module_init(bt878_init_module);
+module_exit(bt878_cleanup_module);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/linux/drivers/media/dvb/bt8xx/bt878.h b/linux/drivers/media/dvb/bt8xx/bt878.h
new file mode 100644
index 000000000..adbb74145
--- /dev/null
+++ b/linux/drivers/media/dvb/bt8xx/bt878.h
@@ -0,0 +1,109 @@
+/*
+ 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"
+
+#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
+
+#define BT878_MAX 4
+extern int bt878_num;
+extern struct bt878 bt878[BT878_MAX];
+
+struct bt878 {
+ spinlock_t s_lock;
+ unsigned int nr;
+ struct pci_dev *dev;
+ unsigned int id;
+ unsigned char revision;
+ unsigned int irq;
+ unsigned long bt878_adr;
+ unsigned char *bt878_mem;
+ int nbuffers;
+ int buffersize;
+ int framesize;
+ int allocbufsize;
+ void *buffer;
+ void *riscprog;
+
+ int writebuf;
+ int readbuf;
+ int readptr;
+
+ wait_queue_head_t readq;
+ struct tasklet_struct *tasklet;
+ int shutdown;
+ };
+
+int bt878_get_buffers(struct bt878 *bt, int bpl, int lpf, int nbufs, int sync);
+void bt878_start(struct bt878 *bt, u32 controlreg);
+void bt878_stop(struct bt878 *bt);
+#endif