* the usual pile of tv card database updates.
* various signed/unsigned fixups (fix gcc 3.3 warnings)
and releated cleanups (use ARRAY_SIZE macro, ...).
* moved some code which can be shared with the new,
upcoming cx2388x driver to a separate module.
* split the irq handler into smaller functions.
* some new features (field rate capture support for example).
* simplified i2c code a bit by removing redundant
bookkeeping of attached i2c clients.
* merged i2c changes back into my tree, there are some no-op
changes due to this.
* various other bugfixes.
* fix build failure with CONFIG_FW_LOADER enabled
obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o
obj-$(CONFIG_VIDEO_BUF) += video-buf.o
-
+obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
#define BT848_COLOR_FMT_YCrCb411 0x99
#define BT848_COLOR_FMT_RAW 0xee
+#define BT848_VTOTAL_LO 0xB0
+#define BT848_VTOTAL_HI 0xB4
+
#define BT848_COLOR_CTL 0x0D8
#define BT848_COLOR_CTL_EXT_FRMRATE (1<<7)
#define BT848_COLOR_CTL_COLOR_BARS (1<<6)
/* 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_BYTE0 (1U<<12)
+#define BT848_RISC_BYTE1 (1U<<13)
+#define BT848_RISC_BYTE2 (1U<<14)
+#define BT848_RISC_BYTE3 (1U<<15)
+#define BT848_RISC_BYTE_ALL (0x0fU<<12)
#define BT848_RISC_BYTE_NONE 0
/* cause RISCI */
-#define BT848_RISC_IRQ (1<<24)
+#define BT848_RISC_IRQ (1U<<24)
/* RISC command is last one in this line */
-#define BT848_RISC_EOL (1<<26)
+#define BT848_RISC_EOL (1U<<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_SOL (1U<<27)
-#define BT848_RISC_WRITE123 (0x09<<28)
-#define BT848_RISC_SKIP123 (0x0a<<28)
-#define BT848_RISC_WRITE1S23 (0x0b<<28)
+#define BT848_RISC_WRITE (0x01U<<28)
+#define BT848_RISC_SKIP (0x02U<<28)
+#define BT848_RISC_WRITEC (0x05U<<28)
+#define BT848_RISC_JUMP (0x07U<<28)
+#define BT848_RISC_SYNC (0x08U<<28)
+#define BT848_RISC_WRITE123 (0x09U<<28)
+#define BT848_RISC_SKIP123 (0x0aU<<28)
+#define BT848_RISC_WRITE1S23 (0x0bU<<28)
/* Bt848A and higher only !! */
--- /dev/null
+/*
+ btcx-risc.c
+
+ bt848/bt878/cx2388x risc code generator.
+
+ (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+ 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/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "btcx-risc.h"
+
+MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug = 0;
+MODULE_PARM(debug,"i");
+MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
+
+/* ---------------------------------------------------------- */
+/* allocate/free risc memory */
+
+static int memcnt;
+
+int btcx_riscmem_alloc(struct pci_dev *pci,
+ struct btcx_riscmem *risc,
+ unsigned int size)
+{
+ u32 *cpu;
+ dma_addr_t dma;
+
+ cpu = pci_alloc_consistent(pci, size, &dma);
+ if (NULL == cpu)
+ return -ENOMEM;
+ memset(cpu,0,size);
+
+#if 0
+ if (risc->cpu && risc->size < size) {
+ /* realloc (enlarge buffer) -- copy old stuff */
+ memcpy(cpu,risc->cpu,risc->size);
+ btcx_riscmem_free(pci,risc);
+ }
+#else
+ BUG_ON(NULL != risc->cpu);
+#endif
+ risc->cpu = cpu;
+ risc->dma = dma;
+ risc->size = size;
+
+ if (debug) {
+ memcnt++;
+ printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt);
+ }
+
+ return 0;
+}
+
+void btcx_riscmem_free(struct pci_dev *pci,
+ struct btcx_riscmem *risc)
+{
+ if (NULL == risc->cpu)
+ return;
+ pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
+ memset(risc,0,sizeof(*risc));
+ if (debug) {
+ memcnt--;
+ printk("btcx: riscmem free [%d]\n",memcnt);
+ }
+}
+
+/* ---------------------------------------------------------- */
+/* screen overlay helpers */
+
+int
+btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+ struct v4l2_clip *clips, unsigned int n)
+{
+ if (win->left < 0) {
+ /* left */
+ clips[n].c.left = 0;
+ clips[n].c.top = 0;
+ clips[n].c.width = -win->left;
+ clips[n].c.height = win->height;
+ n++;
+ }
+ if (win->left + win->width > swidth) {
+ /* right */
+ clips[n].c.left = swidth - win->left;
+ clips[n].c.top = 0;
+ clips[n].c.width = win->width - clips[n].c.left;
+ clips[n].c.height = win->height;
+ n++;
+ }
+ if (win->top < 0) {
+ /* top */
+ clips[n].c.left = 0;
+ clips[n].c.top = 0;
+ clips[n].c.width = win->width;
+ clips[n].c.height = -win->top;
+ n++;
+ }
+ if (win->top + win->height > sheight) {
+ /* bottom */
+ clips[n].c.left = 0;
+ clips[n].c.top = sheight - win->top;
+ clips[n].c.width = win->width;
+ clips[n].c.height = win->height - clips[n].c.top;
+ n++;
+ }
+ return n;
+}
+
+int
+btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
+{
+ s32 nx,nw,dx;
+ unsigned int i;
+
+ /* fixup window */
+ nx = (win->left + mask) & ~mask;
+ nw = (win->width) & ~mask;
+ if (nx + nw > win->left + win->width)
+ nw -= mask+1;
+ dx = nx - win->left;
+ win->left = nx;
+ win->width = nw;
+ if (debug)
+ printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
+ win->width, win->height, win->left, win->top, dx);
+
+ /* fixup clips */
+ for (i = 0; i < n; i++) {
+ nx = (clips[i].c.left-dx) & ~mask;
+ nw = (clips[i].c.width) & ~mask;
+ if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
+ nw += mask+1;
+ clips[i].c.left = nx;
+ clips[i].c.width = nw;
+ if (debug)
+ printk(KERN_DEBUG "btcx: clip align %dx%d+%d+%d\n",
+ clips[i].c.width, clips[i].c.height,
+ clips[i].c.left, clips[i].c.top);
+ }
+ return 0;
+}
+
+void
+btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
+{
+ struct v4l2_clip swap;
+ int i,j,n;
+
+ if (nclips < 2)
+ return;
+ for (i = nclips-2; i >= 0; i--) {
+ for (n = 0, j = 0; j <= i; j++) {
+ if (clips[j].c.left > clips[j+1].c.left) {
+ swap = clips[j];
+ clips[j] = clips[j+1];
+ clips[j+1] = swap;
+ n++;
+ }
+ }
+ if (0 == n)
+ break;
+ }
+}
+
+void
+btcx_calc_skips(int line, int width, unsigned int *maxy,
+ struct btcx_skiplist *skips, unsigned int *nskips,
+ const struct v4l2_clip *clips, unsigned int nclips)
+{
+ unsigned int clip,skip;
+ int end,maxline;
+
+ skip=0;
+ maxline = 9999;
+ for (clip = 0; clip < nclips; clip++) {
+
+ /* sanity checks */
+ if (clips[clip].c.left + clips[clip].c.width <= 0)
+ continue;
+ if (clips[clip].c.left > (signed)width)
+ break;
+
+ /* vertical range */
+ if (line > clips[clip].c.top+clips[clip].c.height-1)
+ continue;
+ if (line < clips[clip].c.top) {
+ if (maxline > clips[clip].c.top-1)
+ maxline = clips[clip].c.top-1;
+ continue;
+ }
+ if (maxline > clips[clip].c.top+clips[clip].c.height-1)
+ maxline = clips[clip].c.top+clips[clip].c.height-1;
+
+ /* horizontal range */
+ if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
+ /* new one */
+ skips[skip].start = clips[clip].c.left;
+ if (skips[skip].start < 0)
+ skips[skip].start = 0;
+ skips[skip].end = clips[clip].c.left + clips[clip].c.width;
+ if (skips[skip].end > width)
+ skips[skip].end = width;
+ skip++;
+ } else {
+ /* overlaps -- expand last one */
+ end = clips[clip].c.left + clips[clip].c.width;
+ if (skips[skip-1].end < end)
+ skips[skip-1].end = end;
+ if (skips[skip-1].end > width)
+ skips[skip-1].end = width;
+ }
+ }
+ *nskips = skip;
+ *maxy = maxline;
+
+ if (debug) {
+ printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
+ for (skip = 0; skip < *nskips; skip++) {
+ printk(" %d-%d",skips[skip].start,skips[skip].end);
+ }
+ printk("\n");
+ }
+}
+
+/* ---------------------------------------------------------- */
+
+EXPORT_SYMBOL(btcx_riscmem_alloc);
+EXPORT_SYMBOL(btcx_riscmem_free);
+
+EXPORT_SYMBOL(btcx_screen_clips);
+EXPORT_SYMBOL(btcx_align);
+EXPORT_SYMBOL(btcx_sort_clips);
+EXPORT_SYMBOL(btcx_calc_skips);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
--- /dev/null
+
+struct btcx_riscmem {
+ unsigned int size;
+ u32 *cpu;
+ u32 *jmp;
+ dma_addr_t dma;
+};
+
+struct btcx_skiplist {
+ int start;
+ int end;
+};
+
+int btcx_riscmem_alloc(struct pci_dev *pci,
+ struct btcx_riscmem *risc,
+ unsigned int size);
+void btcx_riscmem_free(struct pci_dev *pci,
+ struct btcx_riscmem *risc);
+
+int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+ struct v4l2_clip *clips, unsigned int n);
+int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
+ unsigned int n, int mask);
+void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
+void btcx_calc_skips(int line, int width, unsigned int *maxy,
+ struct btcx_skiplist *skips, unsigned int *nskips,
+ const struct v4l2_clip *clips, unsigned int nclips);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
*/
#include <linux/version.h>
+#include <linux/config.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
+#include <linux/firmware.h>
#include <asm/io.h>
static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set);
static void windvr_audio(struct bttv *btv, struct video_audio *v, int set);
+static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set);
static void rv605_muxsel(struct bttv *btv, unsigned int input);
static void eagle_muxsel(struct bttv *btv, unsigned int input);
+static void xguard_muxsel(struct bttv *btv, unsigned int input);
static int terratec_active_radio_upgrade(struct bttv *btv);
static int tea5757_read(struct bttv *btv);
static int tea5757_write(struct bttv *btv, int value);
-int is_MM20xPCTV(unsigned char eeprom_data[256]);
-
+static void identify_by_eeprom(struct bttv *btv,
+ unsigned char eeprom_data[256]);
/* config variables */
-static int triton1=0;
-static int vsfx=0;
-static int no_overlay=-1;
-static int latency = -1;
-
-static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = -1};
-static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = -1};
-static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = -1};
+static unsigned int triton1=0;
+static unsigned int vsfx=0;
+static unsigned int latency = UNSET;
+unsigned int no_overlay=-1;
+
+static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET};
+static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET};
+static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET};
#ifdef MODULE
static unsigned int autoload = 1;
#else
static unsigned int autoload = 0;
#endif
-static unsigned int gpiomask = -1;
-static unsigned int audioall = -1;
-static unsigned int audiomux[5] = { -1, -1, -1, -1, -1 };
+static unsigned int gpiomask = UNSET;
+static unsigned int audioall = UNSET;
+static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
/* insmod options */
MODULE_PARM(triton1,"i");
{ 0x6606107d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
{ 0x6607107d, BTTV_WINFAST2000, "Leadtek WinFast VC 100" },
{ 0x263610b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" },
+ { 0x264510b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" },
{ 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" },
{ 0x405010fc, BTTV_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" },
{ 0x407010fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" },
- { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" },
+ // some cards ship with byteswapped IDs ...
+ { 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
+ { 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
{ 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
{ 0x3060121a, BTTV_STB2, "3Dfx VoodooTV 100/ STB OEM" },
{ 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
{ 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
{ 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
+ { 0x5000144f, BTTV_MAGICTVIEW061, "Askey CPH050" },
{ 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" },
{ 0x00021461, BTTV_AVERMEDIA98, "AVermedia TVCapture 98" },
{ 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
{ 0x401615b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+ { 0x1430aa00, BTTV_PV143, "Provideo PV143A" },
+ { 0x1431aa00, BTTV_PV143, "Provideo PV143B" },
+ { 0x1432aa00, BTTV_PV143, "Provideo PV143C" },
+ { 0x1433aa00, BTTV_PV143, "Provideo PV143D" },
+
+ { 0x1460aa00, BTTV_PV150, "Provideo PV150A-1" },
+ { 0x1461aa01, BTTV_PV150, "Provideo PV150A-2" },
+ { 0x1462aa02, BTTV_PV150, "Provideo PV150A-3" },
+ { 0x1463aa03, BTTV_PV150, "Provideo PV150A-4" },
+
+ { 0x1464aa04, BTTV_PV150, "Provideo PV150B-1" },
+ { 0x1465aa05, BTTV_PV150, "Provideo PV150B-2" },
+ { 0x1466aa06, BTTV_PV150, "Provideo PV150B-3" },
+ { 0x1467aa07, BTTV_PV150, "Provideo PV150B-4" },
+
+
+ { 0xa1550000, BTTV_IVC200, "IVC-200" },
+ { 0xa1550001, BTTV_IVC200, "IVC-200" },
+ { 0xa1550002, BTTV_IVC200, "IVC-200" },
+ { 0xa1550003, BTTV_IVC200, "IVC-200" },
+
+ { 0x41424344, BTTV_GRANDTEC, "GrandTec Multi Capture" },
+ { 0x01020304, BTTV_XGUARD, "Grandtec Grand X-Guard" },
+
{ 0x010115cb, BTTV_GMV1, "AG GMV1" },
{ 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
{ 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
{ 0x03116000, BTTV_SENSORAY311, "Sensoray 311" },
{ 0x00790e11, BTTV_WINDVR, "Canopus WinDVR PCI" },
{ 0xa0fca1a0, BTTV_ZOLTRIX, "Face to Face Tvmax" },
- { 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+ { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
+ // likely broken, vendor id doesn't match the other magic views ...
+ //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+
{ 0, -1, NULL }
};
},{
/* ---- card 0x08 ---------------------------------- */
- .name = "Lifeview FlyVideo II (Bt848) LR26",
+ .name = "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26",
.video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
.muxsel = { 2, 3, 1, 1},
.audiomux = { 13, 14, 11, 7, 0, 0},
.needs_tvaudio = 1,
+ .msp34xx_alt = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
},{
.pll = PLL_28,
.tuner_type = -1,
},{
- .name = "Formac iProTV",
+ .name = "Formac iProTV, Formac ProTV I (bt848)",
.video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
.audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
.needs_tvaudio = 1,
.pll = PLL_28,
- .tuner_type = -1,
+ .tuner_type = 1,
},{
.name = "Pinnacle PCTV Studio/Rave",
.video_inputs = 3,
.pll = PLL_28,
.tuner_type = -1,
.has_radio = 1,
+ .audio_hook = avermedia_tvphone_audio,
},{
.name = "ProVideo PV951", /* pic16c54 */
.video_inputs = 3,
/* ---- card 0x34 ---------------------------------- */
/* David Härdeman <david@2gen.com> */
.name = "Pinnacle PCTV Studio Pro",
- .video_inputs = 3,
+ .video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
- .svhs = 2,
+ .svhs = 3,
.gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 1},
.audiomux = { 1, 0xd0001, 0, 0, 10},
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
+ .gpiomask = 0x01,
+ .audiomux = { 0, 0, 0, 0, 1 },
.muxsel = { 3, 0, 1, 2},
.needs_tvaudio = 0,
.pll = PLL_28,
},{
- .name = "Formac ProTV II",
+ .name = "Formac ProTV II (bt878)",
.video_inputs = 4,
.audio_inputs = 1,
.tuner = 0,
not soldered here, though unknown wiring.
Card lacks: external audio in, pci subsystem id.
*/
-
},{
+
/* ---- card 0x60 ---------------------------------- */
.name = "MachTV",
.video_inputs = 3,
.no_tda7432 = 1,
.muxsel = { 2, 0, 1},
.pll = PLL_28,
+},{
+ /* Luc Van Hoeylandt <luc@e-magic.be> */
+ .name = "ProVideo PV150", /* 0x4f */
+ .video_inputs = 2,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0,
+ .muxsel = { 2, 3 },
+ .audiomux = { 0 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+},{
+ /* Hiroshi Takekawa <sian@big.or.jp> */
+ /* This card lacks subsystem ID */
+ .name = "AD-TVK503", /* 0x63 */
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x001e8007,
+ .muxsel = { 2, 3, 1, 0 },
+ /* Tuner, Radio, external, internal, off, on */
+ .audiomux = { 0x08, 0x0f, 0x0a, 0x08, 0x0f, 0x08 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = 2,
+ .audio_hook = adtvk503_audio,
+},{
+
+ /* ---- card 0x64 ---------------------------------- */
+ .name = "Hercules Smart TV Stereo",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 0x00,
+ .muxsel = { 2, 3, 1, 1 },
+ .needs_tvaudio = 1,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = 5,
+ /* Notes:
+ - card lacks subsystem ID
+ - stereo variant w/ daughter board with tda9874a @0xb0
+ - Audio Routing:
+ always from tda9874 independent of GPIO (?)
+ external line in: unknown
+ - Other chips: em78p156elp @ 0x96 (probably IR remote control)
+ hef4053 (instead 4052) for unknown function
+ */
+},{
+ .name = "Pace TV & Radio Card",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 1}, // Tuner, CVid, SVid, CVid over SVid connector
+ .gpiomask = 0,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = 1,
+ .has_radio = 1,
+ .pll = PLL_28,
+ /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
+ only internal line out: (4pin header) RGGL
+ Radio must be decoded by msp3410d (not routed through)*/
+ // .digital_mode = DIGITAL_MODE_CAMERA, // todo!
+},{
+ /* Chris Willing <chris@vislab.usyd.edu.au> */
+ .name = "IVC-200",
+ .video_inputs = 1,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .svhs = -1,
+ .gpiomask = 0xdf,
+ .muxsel = { 2 },
+ .pll = PLL_28,
+},{
+ .name = "Grand X-Guard / Trust 814PCI",
+ .video_inputs = 16,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .tuner_type = 4,
+ .gpiomask2 = 0xff,
+ .muxsel = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 },
+ .muxsel_hook = xguard_muxsel,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .pll = PLL_28,
+},{
+
+ /* ---- card 0x68 ---------------------------------- */
+ .name = "Nebula Electronics DigiTV",
+ .video_inputs = 0,
+ .audio_inputs = 0,
+ .svhs = -1,
+ .muxsel = { 2, 3, 1, 0},
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+},{
+ /* Jorge Boncompte - DTI2 <jorge@dti2.net> */
+ .name = "ProVideo PV143",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0,
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0 },
+ .needs_tvaudio = 0,
+ .no_msp34xx = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+},{
+ /* M.Klahr@phytec.de */
+ .name = "PHYTEC VD-009-X1 MiniDIN (bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1, /* card has no tuner */
+ .svhs = 3,
+ .gpiomask = 0x00,
+ .muxsel = { 2, 3, 1, 0},
+ .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+},{
+ .name = "PHYTEC VD-009-X1 Combi (bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1, /* card has no tuner */
+ .svhs = 3,
+ .gpiomask = 0x00,
+ .muxsel = { 2, 3, 1, 1},
+ .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+},{
+
+ /* ---- card 0x6c ---------------------------------- */
+ .name = "PHYTEC VD-009 MiniDIN (bt878)",
+ .video_inputs = 10,
+ .audio_inputs = 0,
+ .tuner = -1, /* card has no tuner */
+ .svhs = 9,
+ .gpiomask = 0x00,
+ .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
+ via the upper nibble of muxsel. here: used for
+ xternal video-mux */
+ .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
+ .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
+},{
+ .name = "PHYTEC VD-009 Combi (bt878)",
+ .video_inputs = 10,
+ .audio_inputs = 0,
+ .tuner = -1, /* card has no tuner */
+ .svhs = 9,
+ .gpiomask = 0x00,
+ .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio
+ via the upper nibble of muxsel. here: used for
+ xternal video-mux */
+ .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
+ .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
+ .needs_tvaudio = 1,
+ .pll = PLL_28,
+ .tuner_type = -1,
}};
-const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard));
+const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
/* ----------------------------------------------------------------------- */
printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
"PCI subsystem ID is %04x:%04x\n",
btv->nr,cards[type].name,cards[type].cardnr,
- btv->cardid & 0xffff, btv->cardid >> 16);
+ btv->cardid & 0xffff,
+ (btv->cardid >> 16) & 0xffff);
btv->type = cards[type].cardnr;
} else {
/* 404 */
printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n",
- btv->nr, btv->cardid&0xffff, btv->cardid>>16);
+ btv->nr, btv->cardid & 0xffff,
+ (btv->cardid >> 16) & 0xffff);
printk(KERN_DEBUG "please mail id, board name and "
"the correct card= insmod option to kraxel@bytesex.org\n");
}
}
/* let the user override the autodetected type */
- if (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards)
+ if (card[btv->nr] < bttv_num_tvcards)
btv->type=card[btv->nr];
/* print which card config we are using */
bttv_tvcards[btv->type].name);
printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr,
btv->video_dev.name,btv->type,
- (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ?
- "insmod option" : "autodetected");
+ card[btv->nr] < bttv_num_tvcards
+ ? "insmod option" : "autodetected");
/* overwrite gpio stuff ?? */
- if (-1 == audioall && -1 == audiomux[0])
+ if (UNSET == audioall && UNSET == audiomux[0])
return;
- if (-1 != audiomux[0]) {
+ if (UNSET != audiomux[0]) {
gpiobits = 0;
for (i = 0; i < 5; i++) {
bttv_tvcards[btv->type].audiomux[i] = audiomux[i];
bttv_tvcards[btv->type].audiomux[i] = audioall;
}
}
- bttv_tvcards[btv->type].gpiomask = (-1 != gpiomask) ? gpiomask : gpiobits;
+ bttv_tvcards[btv->type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
btv->nr,bttv_tvcards[btv->type].gpiomask);
for (i = 0; i < 5; i++) {
*/
/* Some Modular Technology cards have an eeprom, but no subsystem ID */
-int is_MM20xPCTV(unsigned char eeprom_data[256])
+void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
{
- if (0 == strncmp(eeprom_data,"GET.MM20xPCTV",13)) {
- printk("bttv: GET.MM20xPCTV found\n");
- return 1; // found
+ int type = -1;
+
+ if (0 == strncmp(eeprom_data,"GET.MM20xPCTV",13))
+ type = BTTV_MODTEC_205;
+ else if (0 == strncmp(eeprom_data+20,"Picolo",7))
+ type = BTTV_EURESYS_PICOLO;
+ else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0)
+ type = BTTV_HAUPPAUGE; /* old bt848 */
+
+ if (-1 != type) {
+ btv->type = type;
+ printk("bttv%d: detected by eeprom: %s [card=%d]\n",
+ btv->nr, bttv_tvcards[btv->type].name, btv->type);
}
- return 0;
}
static void flyvideo_gpio(struct bttv *btv)
if (btv->type == BTTV_PINNACLE)
btv->type = BTTV_PINNACLEPRO;
}
- printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+ printk(KERN_INFO
+ "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
btv->nr, id+1, btv->tuner_type,
!btv->has_radio ? "no" :
(btv->has_matchbox ? "matchbox" : "fmtuner"),
info = "oops: unknown card";
break;
}
+ if (-1 != msp)
+ btv->type = BTTV_PINNACLEPRO;
printk(KERN_INFO
"bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
btv->nr, id, info, btv->has_radio ? "yes" : "no");
- btv->tuner_type = 33;
- if (autoload)
- request_module("tda9887");
- bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,&id);
+ btv->tuner_type = 33;
+ btv->pinnacle_id = id;
}
}
case BTTV_VOODOOTV_FM:
boot_msp34xx(btv,20);
break;
+ case BTTV_AVERMEDIA98:
+ boot_msp34xx(btv,11);
+ break;
case BTTV_HAUPPAUGEPVR:
pvr_boot(btv);
break;
btv->tuner_type = -1;
if (BTTV_UNKNOWN == btv->type) {
- printk("bttv%d: Looking for eeprom\n",btv->nr);
bttv_readee(btv,eeprom_data,0xa0);
- if(is_MM20xPCTV(eeprom_data)) {
- btv->type = BTTV_MODTEC_205;
- printk("bttv%d: Autodetect by eeprom:(%s) [card=%d]\n",
- btv->nr, bttv_tvcards[btv->type].name, btv->type);
- }
+ identify_by_eeprom(btv,eeprom_data);
}
switch (btv->type) {
btv->pll.pll_current = -1;
/* tuner configuration (from card list / autodetect / insmod option) */
- if (-1 != bttv_tvcards[btv->type].tuner_type)
- if( -1 == btv->tuner_type)
+ if (UNSET != bttv_tvcards[btv->type].tuner_type)
+ if(UNSET == btv->tuner_type)
btv->tuner_type = bttv_tvcards[btv->type].tuner_type;
- if (-1 != tuner[btv->nr])
+ if (UNSET != tuner[btv->nr])
btv->tuner_type = tuner[btv->nr];
- if (btv->tuner_type != -1)
- bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
printk("bttv%d: using tuner=%d\n",btv->nr,btv->tuner_type);
+ if (btv->pinnacle_id != UNSET)
+ bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
+ &btv->pinnacle_id);
+ if (btv->tuner_type != UNSET)
+ bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
if (bttv_tvcards[btv->type].has_radio)
btv->has_radio=1;
-
if (bttv_tvcards[btv->type].audio_hook)
btv->audio_hook=bttv_tvcards[btv->type].audio_hook;
request_module("msp3400");
}
+ if (bttv_tvcards[btv->type].msp34xx_alt &&
+ bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) {
+ if (autoload)
+ request_module("msp3400");
+ }
+
if (!bttv_tvcards[btv->type].no_tda9875 &&
bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
if (autoload)
request_module("tvaudio");
}
- if (bttv_tvcards[btv->type].tuner != -1) {
+ /* tuner modules */
+ if (btv->pinnacle_id != UNSET) {
+ if (autoload)
+ request_module("tda9887");
+ }
+ if (btv->tuner_type != UNSET) {
if (autoload)
request_module("tuner");
}
{ TUNER_TEMIC_4046FM5, "Temic 4046FM5" },
{ TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
{ TUNER_ABSENT, "Philips TD1536D_FH_44"},
- { TUNER_LG_NTSC_FM, "LG TP18NSR01F"},
- { TUNER_LG_PAL_FM, "LG TP18PSB01D"},
- { TUNER_LG_PAL, "LG TP18PSB11D"},
+ { TUNER_LG_NTSC_FM, "LG TPI8NSR01F"},
+ { TUNER_LG_PAL_FM, "LG TPI8PSB01D"},
+ { TUNER_LG_PAL, "LG TPI8PSB11D"},
{ TUNER_LG_PAL_I_FM, "LG TAPC-I001D"},
{ TUNER_LG_PAL_I, "LG TAPC-I701D"}
};
{
if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
- printk("bttv Modtec: Tuner autodetected %s\n",&eeprom_data[0x1e]);
+ printk("bttv Modtec: Tuner autodetected %s\n",
+ &eeprom_data[0x1e]);
+ } else {
+ printk("bttv Modtec: Unknown TunerString:%s\n",
+ &eeprom_data[0x1e]);
}
- else
- printk("bttv Modtec: Unknown TunerString:%s\n",&eeprom_data[0x1e]);
}
static void __devinit hauppauge_eeprom(struct bttv *btv)
{
- int blk2,tuner,radio,model;
+ unsigned int blk2,tuner,radio,model;
if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n",
tuner = eeprom_data[9];
radio = eeprom_data[blk2-1] & 0x01;
- if (tuner >= ARRAY_SIZE(hauppauge_tuner))
- tuner = 0;
- btv->tuner_type = hauppauge_tuner[tuner].id;
+ if (tuner < ARRAY_SIZE(hauppauge_tuner))
+ btv->tuner_type = hauppauge_tuner[tuner].id;
if (radio)
btv->has_radio = 1;
* a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be
* unpacked with unzip).
*/
-static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
-MODULE_PARM(firm_altera,"s");
-MODULE_PARM_DESC(firm_altera,"WinTV/PVR firmware "
- "(driver CD => unzip pvr45xxx.exe => hcwamc.rbf)");
-
-/* drivers/sound/sound_firmware.c => soundcore.o */
-extern int mod_firmware_load(const char *fn, char **fp);
-
#define PVR_GPIO_DELAY 10
#define BTTV_ALT_DATA 0x000001
return 0;
}
+#ifndef CONFIG_FW_LOADER
+/* old 2.4.x way -- via soundcore's mod_firmware_load */
+
+static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
+MODULE_PARM(firm_altera,"s");
+MODULE_PARM_DESC(firm_altera,"WinTV/PVR firmware "
+ "(driver CD => unzip pvr45xxx.exe => hcwamc.rbf)");
+
+extern int mod_firmware_load(const char *fn, char **fp);
+
int __devinit pvr_boot(struct bttv *btv)
{
u32 microlen;
int result;
microlen = mod_firmware_load(firm_altera, (char**) µ);
- if (!microlen)
+ if (!microlen) {
+ printk(KERN_WARNING "bttv%d: altera firmware not found [%s]\n",
+ btv->nr, firm_altera);
return -1;
+ }
printk(KERN_INFO "bttv%d: uploading altera firmware [%s] ...\n",
btv->nr, firm_altera);
vfree(micro);
return result;
}
+#else
+/* new 2.5.x way -- via hotplug firmware loader */
+
+int __devinit pvr_boot(struct bttv *btv)
+{
+ const struct firmware *fw_entry;
+ struct device *dev = &btv->dev->dev;
+ int rc;
+
+ rc = request_firmware(&fw_entry, "hcwamc.rbf", dev);
+ if (rc != 0) {
+ printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n",
+ btv->nr);
+ return rc;
+ }
+ rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
+ printk(KERN_INFO "bttv%d: altera firmware upload %s\n",
+ btv->nr, (rc < 0) ? "failed" : "ok");
+ release_firmware(fw_entry);
+ return rc;
+}
+#endif
/* ----------------------------------------------------------------------- */
/* some osprey specific stuff */
static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x00 };
- int i,tmp;
-
+ unsigned int i;
+ int tmp;
+ u32 val;
+
/* Initialise GPIO-connevted stuff */
btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */
btwrite(0,BT848_GPIO_DATA);
setting BT848_ADC_AGC_EN disable the AGC
tboult@eecs.lehigh.edu
*/
+
btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
/* Initialise MAX517 DAC */
* same chips - but the R/W bit is included in the address
* argument so the numbers are different */
+
printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
- for (i = 0; i < sizeof(vals)/sizeof(int); i++) {
- tmp=bttv_I2CWrite(btv,0x1E,vals[i],0,1);
- printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n",
- tmp,bttv_I2CRead(btv,0x1F,NULL));
+ /* First of all, enable the clock line. This is used in the PXC200-F */
+ val = btread(BT848_GPIO_DMA_CTL);
+ val |= BT848_GPIO_DMA_CTL_GPCLKMODE;
+ btwrite(val, BT848_GPIO_DMA_CTL);
+
+ /* Then, push to 0 the reset pin long enough to reset the *
+ * device same as above for the reset line, but not the same
+ * value sent to the GPIO-connected stuff
+ * which one is the good one? */
+ btwrite( (1<<2), BT848_GPIO_OUT_EN); /* only the reset pin */
+ btwrite(0, BT848_GPIO_DATA);
+ udelay(10);
+ btwrite(1<<2, BT848_GPIO_DATA);
+
+ for (i = 0; i < ARRAY_SIZE(vals); i++) {
+ tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
+ if (tmp != -1) {
+ printk(KERN_INFO
+ "I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+ vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
+ }
}
+
printk(KERN_INFO "PXC200 Initialised.\n");
}
+
/* ----------------------------------------------------------------------- */
/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
/*
/* Low-level stuff */
static int tea5757_read(struct bttv *btv)
{
- int value = 0;
unsigned long timeout;
+ int value = 0;
int i;
/* better safe than sorry */
void tea5757_set_freq(struct bttv *btv, unsigned short freq)
{
- int value;
-
dprintk("tea5757_set_freq %d\n",freq);
tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
+#if 0
+ /* breaks Miro PCTV */
value = tea5757_read(btv);
- dprintk("bttv%d: tea5757 readback =0x%x\n",btv->nr,value);
+ dprintk("bttv%d: tea5757 readback=0x%x\n",btv->nr,value);
+#endif
}
}
}
+/*
+ * sound control for AD-TVK503
+ * Hiroshi Takekawa <sian@big.or.jp>
+ */
+static void
+adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
+{
+ unsigned int con = 0xffffff;
+
+ //btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN);
+
+ if (set) {
+ //btor(***, BT848_GPIO_OUT_EN);
+ if (v->mode & VIDEO_SOUND_LANG1)
+ con = 0x00000000;
+ if (v->mode & VIDEO_SOUND_LANG2)
+ con = 0x00180000;
+ if (v->mode & VIDEO_SOUND_STEREO)
+ con = 0x00000000;
+ if (v->mode & VIDEO_SOUND_MONO)
+ con = 0x00060000;
+ if (con != 0xffffff) {
+ btaor(con, ~0x1e0000, BT848_GPIO_DATA);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "adtvk503");
+ }
+ } else {
+ v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
+ VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+ }
+}
+
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
*
* This is needed because rv605 don't use a normal multiplex, but a crosspoint
mdelay(1);
}
+// The Grandtec X-Guard framegrabber card uses two Dual 4-channel
+// video multiplexers to provide up to 16 video inputs. These
+// multiplexers are controlled by the lower 8 GPIO pins of the
+// bt878. The multiplexers probably Pericom PI5V331Q or similar.
+
+// xxx0 is pin xxx of multiplexer U5,
+// yyy1 is pin yyy of multiplexer U2
+
+#define ENA0 0x01
+#define ENB0 0x02
+#define ENA1 0x04
+#define ENB1 0x08
+
+#define IN10 0x10
+#define IN00 0x20
+#define IN11 0x40
+#define IN01 0x80
+
+static void xguard_muxsel(struct bttv *btv, unsigned int input)
+{
+ static const int masks[] = {
+ ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10,
+ ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10,
+ ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11,
+ ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11,
+ };
+ btwrite(masks[input%16], BT848_GPIO_DATA);
+}
/* ----------------------------------------------------------------------- */
/* motherboard chipset specific stuff */
printk(KERN_INFO "bttv: Host bridge needs VSFX enabled.\n");
if (pcipci_fail) {
printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
- if (-1 == no_overlay) {
+ if (UNSET == no_overlay) {
printk(KERN_WARNING "bttv: going to disable overlay.\n");
no_overlay = 1;
}
}
- if (-1 != latency)
+ if (UNSET != latency)
printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
{
unsigned char command;
- if (!triton1 && !vsfx && -1 == latency)
+ if (!triton1 && !vsfx && UNSET == latency)
return 0;
if (bttv_verbose) {
printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->nr);
if (vsfx && btv->id >= 878)
printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->nr);
- if (-1 != latency)
+ if (UNSET != latency)
printk(KERN_INFO "bttv%d: setting pci timer to %d\n",
btv->nr,latency);
}
command |= BT878_EN_VSFX;
pci_write_config_byte(btv->dev, BT878_DEVCTRL, command);
}
- if (-1 != latency)
+ if (UNSET != latency)
pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency);
return 0;
}
*/
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kdev_t.h>
#include <asm/io.h>
+#include <asm/byteorder.h>
#include "bttvp.h"
-int bttv_num; /* number of Bt848s in use */
+unsigned int bttv_num; /* number of Bt848s in use */
struct bttv bttvs[BTTV_MAX];
unsigned int bttv_debug = 0;
unsigned int bttv_gpio = 0;
/* config variables */
-#if defined(__sparc__) || defined(__powerpc__) || defined(__hppa__)
+#ifdef __BIG_ENDIAN
static unsigned int bigendian=1;
#else
static unsigned int bigendian=0;
#endif
-static unsigned int radio[4];
+static unsigned int radio[BTTV_MAX];
static unsigned int irq_debug = 0;
static unsigned int gbuffers = 8;
static unsigned int gbufsize = 0x208000;
.vdelay = 0x16,
.vbipack = 144,
.sram = -1,
+ },{
+ /* that one hopefully works with the strange timing
+ * which video recorders produce when playing a NTSC
+ * tape on a PAL TV ... */
+ .v4l2_id = V4L2_STD_PAL_60,
+ .name = "PAL-60",
+ .Fsc = 35468950,
+ .swidth = 924,
+ .sheight = 480,
+ .totalwidth = 1135,
+ .adelay = 0x7f,
+ .bdelay = 0x72,
+ .iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ .scaledtwidth = 1135,
+ .hdelayx1 = 186,
+ .hactivex1 = 924,
+ .vdelay = 0x1a,
+ .vbipack = 255,
+ .vtotal = 524,
+ .sram = -1,
}
};
-const int BTTV_TVNORMS = (sizeof(bttv_tvnorms)/sizeof(struct bttv_tvnorm));
+const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
/* ----------------------------------------------------------------------- */
/* bttv format list
.flags = FORMAT_FLAGS_RAW,
}
};
-const int BTTV_FORMATS = (sizeof(bttv_formats)/sizeof(struct bttv_format));
+const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
/* ----------------------------------------------------------------------- */
.type = V4L2_CTRL_TYPE_BOOLEAN,
}
};
-const int BTTV_CTLS = (sizeof(bttv_ctls)/sizeof(struct v4l2_queryctrl));
+const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
/* ----------------------------------------------------------------------- */
/* resource management */
break;
case V4L2_CID_AUDIO_MUTE:
- c->value = (VIDEO_AUDIO_MUTE == va.flags) ? 1 : 0;
+ c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
break;
case V4L2_CID_AUDIO_VOLUME:
c->value = va.volume;
static const struct bttv_format*
format_by_palette(int palette)
{
- int i;
+ unsigned int i;
for (i = 0; i < BTTV_FORMATS; i++) {
if (-1 == bttv_formats[i].palette)
static const struct bttv_format*
format_by_fourcc(int fourcc)
{
- int i;
+ unsigned int i;
for (i = 0; i < BTTV_FORMATS; i++) {
if (-1 == bttv_formats[i].fourcc)
unsigned long flags;
int retval = 0;
+ dprintk("switch_overlay: enter [new=%p]\n",new);
if (new)
new->vb.state = STATE_DONE;
spin_lock_irqsave(&btv->s_lock,flags);
spin_unlock_irqrestore(&btv->s_lock,flags);
if (NULL == new)
free_btres(btv,fh,RESOURCE_OVERLAY);
- if (NULL != old)
+ if (NULL != old) {
+ dprintk("switch_overlay: old=%p state is %d\n",old,old->vb.state);
bttv_dma_free(btv, old);
+ kfree(old);
+ }
+ dprintk("switch_overlay: done\n");
return retval;
}
static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf,
const struct bttv_format *fmt,
- int width, int height,
+ unsigned int width, unsigned int height,
enum v4l2_field field)
{
int redo_dma_risc = 0;
redo_dma_risc = 1;
}
-#if 0
- if (STATE_NEEDS_INIT == buf->vb.state) {
- if (redo_dma_risc)
- bttv_dma_free(btv,buf);
- }
-#endif
-
/* alloc risc memory */
if (STATE_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
"SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS (sizeof(v4l1_ioctls)/sizeof(char*))
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
{
{
struct video_tuner *v = arg;
- if (-1 == bttv_tvcards[btv->type].tuner)
+ if (UNSET == bttv_tvcards[btv->type].tuner)
return -EINVAL;
if (v->tuner) /* Only tuner 0 */
return -EINVAL;
case VIDIOCGCHAN:
{
struct video_channel *v = arg;
+ unsigned int channel = v->channel;
- if (v->channel >= bttv_tvcards[btv->type].video_inputs)
+ if (channel >= bttv_tvcards[btv->type].video_inputs)
return -EINVAL;
v->tuners=0;
v->flags = VIDEO_VC_AUDIO;
v->type = VIDEO_TYPE_CAMERA;
v->norm = btv->tvnorm;
- if(v->channel == bttv_tvcards[btv->type].tuner) {
+ if (channel == bttv_tvcards[btv->type].tuner) {
strcpy(v->name,"Television");
v->flags|=VIDEO_VC_TUNER;
v->type=VIDEO_TYPE_TV;
v->tuners=1;
- } else if (v->channel == bttv_tvcards[btv->type].svhs) {
+ } else if (channel == bttv_tvcards[btv->type].svhs) {
strcpy(v->name,"S-Video");
} else {
- sprintf(v->name,"Composite%d",v->channel);
+ sprintf(v->name,"Composite%d",channel);
}
return 0;
}
case VIDIOCSCHAN:
{
struct video_channel *v = arg;
+ unsigned int channel = v->channel;
- if (v->channel < 0 ||
- v->channel >= bttv_tvcards[btv->type].video_inputs)
+ if (channel >= bttv_tvcards[btv->type].video_inputs)
return -EINVAL;
if (v->norm >= BTTV_TVNORMS)
return -EINVAL;
down(&btv->lock);
- if (v->channel == btv->input &&
- v->norm == btv->tvnorm) {
+ if (channel == btv->input &&
+ v->norm == btv->tvnorm) {
/* nothing to do */
up(&btv->lock);
return 0;
case VIDIOCSAUDIO:
{
struct video_audio *v = arg;
+ unsigned int audio = v->audio;
- if(v->audio < 0 ||
- v->audio >= bttv_tvcards[btv->type].audio_inputs)
+ if (audio >= bttv_tvcards[btv->type].audio_inputs)
return -EINVAL;
down(&btv->lock);
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *e = arg;
+ unsigned int index = e->index;
- if (e->index < 0 || e->index >= BTTV_TVNORMS)
+ if (index >= BTTV_TVNORMS)
return -EINVAL;
v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
bttv_tvnorms[e->index].name);
+ e->index = index;
return 0;
}
case VIDIOC_G_STD:
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
- int i;
+ unsigned int i;
for (i = 0; i < BTTV_TVNORMS; i++)
if (*id & bttv_tvnorms[i].v4l2_id)
case VIDIOC_ENUMINPUT:
{
struct v4l2_input *i = arg;
- int n;
+ unsigned int n;
n = i->index;
if (n >= bttv_tvcards[btv->type].video_inputs)
}
case VIDIOC_S_INPUT:
{
- int *i = arg;
+ unsigned int *i = arg;
- if (*i < 0 || *i > bttv_tvcards[btv->type].video_inputs)
+ if (*i > bttv_tvcards[btv->type].video_inputs)
return -EINVAL;
down(&btv->lock);
set_input(btv,*i);
{
struct v4l2_tuner *t = arg;
- if (-1 == bttv_tvcards[btv->type].tuner)
+ if (UNSET == bttv_tvcards[btv->type].tuner)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
memset(t,0,sizeof(*t));
strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
- t->capability = V4L2_TUNER_CAP_NORM;
t->rangehigh = 0xffffffffUL;
+ t->capability = V4L2_TUNER_CAP_NORM;
t->rxsubchans = V4L2_TUNER_SUB_MONO;
if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
t->signal = 0xffff;
bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
if (btv->audio_hook)
btv->audio_hook(btv,&va,0);
- if(va.mode & VIDEO_SOUND_STEREO)
+ if(va.mode & VIDEO_SOUND_STEREO) {
+ t->audmode = V4L2_TUNER_MODE_STEREO;
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
- if(va.mode & VIDEO_SOUND_LANG1)
- t->rxsubchans |= V4L2_TUNER_SUB_LANG1;
- if(va.mode & VIDEO_SOUND_LANG2)
- t->rxsubchans |= V4L2_TUNER_SUB_LANG2;
+ }
+ if(va.mode & VIDEO_SOUND_LANG1) {
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_LANG1
+ | V4L2_TUNER_SUB_LANG2;
+ }
}
/* FIXME: fill capability+audmode */
up(&btv->lock);
{
struct v4l2_tuner *t = arg;
- if (-1 == bttv_tvcards[btv->type].tuner)
+ if (UNSET == bttv_tvcards[btv->type].tuner)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
{
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
+ bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
if (t->audmode == V4L2_TUNER_MODE_MONO)
va.mode = VIDEO_SOUND_MONO;
else if (t->audmode == V4L2_TUNER_MODE_STEREO)
{
enum v4l2_field field;
int maxw, maxh;
-
+
if (win->w.width < 48 || win->w.height < 32)
return -EINVAL;
if (win->clipcount > 2048)
if (!fixup && (win->w.width > maxw || win->w.height > maxh))
return -EINVAL;
- if (1 /* depth < 4bpp */) {
- /* adjust and align writes */
- int left = (win->w.left + 3) & ~3;
- int width = win->w.width & ~3;
- while (left + width > win->w.left + win->w.width)
- width -= 4;
- win->w.left = left;
- win->w.width = width;
- }
if (win->w.width > maxw)
win->w.width = maxw;
if (win->w.height > maxh)
struct v4l2_clip *clips = NULL;
int n,size,retval = 0;
+ if (NULL == fh->ovfmt)
+ return -EINVAL;
retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
if (0 != retval)
return retval;
/* copy clips -- luckily v4l1 + v4l2 are binary
compatible here ...*/
n = win->clipcount;
- size = sizeof(struct video_clip)*(n+4);
+ size = sizeof(*clips)*(n+4);
clips = kmalloc(size,GFP_KERNEL);
if (NULL == clips)
return -ENOMEM;
if (n > 0) {
- if (copy_from_user(clips,win->clips,
- sizeof(struct v4l2_clip)*win->clipcount)) {
+ if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
kfree(clips);
return -EFAULT;
}
}
/* clip against screen */
if (NULL != btv->fbuf.base)
- n = bttv_screen_clips(btv->fbuf.width, btv->fbuf.width,
+ n = btcx_screen_clips(btv->fbuf.width, btv->fbuf.width,
&win->w, clips, n);
- bttv_sort_clips(clips,n);
+ btcx_sort_clips(clips,n);
+
+ /* 4-byte alignments */
+ switch (fh->ovfmt->depth) {
+ case 8:
+ case 24:
+ btcx_align(&win->w, clips, n, 3);
+ break;
+ case 16:
+ btcx_align(&win->w, clips, n, 1);
+ break;
+ case 32:
+ /* no alignment fixups needed */
+ break;
+ default:
+ BUG();
+ }
down(&fh->cap.lock);
if (fh->ov.clips)
kfree(fh->ov.clips);
- fh->ov.clips = clips;
- fh->ov.nclips = n;
+ fh->ov.clips = clips;
+ fh->ov.nclips = n;
- fh->ov.w = win->w;
- fh->ov.field = win->field;
+ fh->ov.w = win->w;
+ fh->ov.field = win->field;
+ fh->ov.setup_ok = 1;
btv->init.ov.w.width = win->w.width;
btv->init.ov.w.height = win->w.height;
+ btv->init.ov.field = win->field;
/* update overlay if needed */
retval = 0;
f->fmt.pix.height = fh->height;
f->fmt.pix.field = fh->cap.field;
f->fmt.pix.pixelformat = fh->fmt->fourcc;
- f->fmt.pix.sizeimage =
- (fh->width * fh->height * fh->fmt->depth)/8;
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.width * fh->fmt->depth) >> 3;
+ f->fmt.pix.sizeimage =
+ f->fmt.pix.height * f->fmt.pix.bytesperline;
return 0;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
memset(&f->fmt.win,0,sizeof(struct v4l2_window));
f->fmt.win.field = fh->ov.field;
return 0;
case V4L2_BUF_TYPE_VBI_CAPTURE:
- bttv_vbi_fmt(fh,f);
+ bttv_vbi_get_fmt(fh,f);
return 0;
default:
return -EINVAL;
{
const struct bttv_format *fmt;
enum v4l2_field field;
- int maxw,maxh;
+ unsigned int maxw,maxh;
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (NULL == fmt)
return -EINVAL;
- if (0 != f->fmt.pix.bytesperline)
- /* FIXME -- not implemented yet */
- return -EINVAL;
/* fixup format */
maxw = bttv_tvnorms[btv->tvnorm].swidth;
switch (field) {
case V4L2_FIELD_TOP:
case V4L2_FIELD_BOTTOM:
+ case V4L2_FIELD_ALTERNATE:
maxh = maxh/2;
break;
case V4L2_FIELD_INTERLACED:
case V4L2_FIELD_SEQ_TB:
if (fmt->flags & FORMAT_FLAGS_PLANAR)
return -EINVAL;
+ break;
default:
return -EINVAL;
}
f->fmt.pix.width = maxw;
if (f->fmt.pix.height > maxh)
f->fmt.pix.height = maxh;
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
- (fh->width * fh->height * fmt->depth)/8;
+ f->fmt.pix.height * f->fmt.pix.bytesperline;
return 0;
}
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
return verify_window(&bttv_tvnorms[btv->tvnorm],
&f->fmt.win, 1);
-#if 0
case V4L2_BUF_TYPE_VBI_CAPTURE:
- retval = bttv_switch_type(fh,f->type);
- if (0 != retval)
- return retval;
- if (fh->vbi.reading || fh->vbi.streaming)
- return -EBUSY;
- bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
- bttv_vbi_fmt(fh,f);
+ bttv_vbi_try_fmt(fh,f);
return 0;
-#endif
default:
return -EINVAL;
}
down(&fh->cap.lock);
fh->fmt = fmt;
fh->cap.field = f->fmt.pix.field;
+ fh->cap.last = V4L2_FIELD_NONE;
fh->width = f->fmt.pix.width;
fh->height = f->fmt.pix.height;
btv->init.fmt = fmt;
retval = bttv_switch_type(fh,f->type);
if (0 != retval)
return retval;
- if (fh->vbi.reading || fh->vbi.streaming)
- return -EBUSY;
+ if (locked_btres(fh->btv, RESOURCE_VBI))
+ return -EBUSY;
+ bttv_vbi_try_fmt(fh,f);
bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]);
- bttv_vbi_fmt(fh,f);
+ bttv_vbi_get_fmt(fh,f);
return 0;
default:
return -EINVAL;
struct bttv_fh *fh = file->private_data;
struct bttv *btv = fh->btv;
unsigned long flags;
- int retval;
+ int retval = 0;
if (bttv_debug > 1) {
switch (_IOC_TYPE(cmd)) {
if (NULL == fmt)
return -EINVAL;
down(&fh->cap.lock);
- retval = -EINVAL;
- if (fmt->depth != pic->depth && !sloppy)
+ if (fmt->depth != pic->depth && !sloppy) {
+ retval = -EINVAL;
goto fh_unlock_and_return;
+ }
fh->ovfmt = fmt;
fh->fmt = fmt;
btv->init.ovfmt = fmt;
struct video_window *win = arg;
struct v4l2_window w2;
- w2.field = V4L2_FIELD_ANY;
+ w2.field = V4L2_FIELD_ANY;
w2.w.left = win->x;
w2.w.top = win->y;
w2.w.width = win->width;
/* verify args */
if (NULL == btv->fbuf.base)
return -EINVAL;
- if (fh->ov.w.width <48 ||
- fh->ov.w.height<32 ||
- fh->ov.w.width >bttv_tvnorms[btv->tvnorm].swidth ||
- fh->ov.w.height>bttv_tvnorms[btv->tvnorm].sheight||
- NULL == fh->ovfmt)
+ if (!fh->ov.setup_ok) {
+ dprintk("bttv%d: overlay: !setup_ok\n",btv->nr);
return -EINVAL;
+ }
}
if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
case VIDIOCGMBUF:
{
struct video_mbuf *mbuf = arg;
- int i;
+ unsigned int i;
down(&fh->cap.lock);
retval = videobuf_mmap_setup(file,&fh->cap,gbuffers,gbufsize);
return retval;
}
+ case VIDIOCGVBIFMT:
+ {
+ struct vbi_format *fmt = (void *) arg;
+ struct v4l2_format fmt2;
+
+ if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {
+ retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
+ if (0 != retval)
+ return retval;
+ }
+ bttv_vbi_get_fmt(fh, &fmt2);
+
+ memset(fmt,0,sizeof(*fmt));
+ fmt->sampling_rate = fmt2.fmt.vbi.sampling_rate;
+ fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;
+ fmt->sample_format = VIDEO_PALETTE_RAW;
+ fmt->start[0] = fmt2.fmt.vbi.start[0];
+ fmt->count[0] = fmt2.fmt.vbi.count[0];
+ fmt->start[1] = fmt2.fmt.vbi.start[1];
+ fmt->count[1] = fmt2.fmt.vbi.count[1];
+ if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
+ fmt->flags |= V4L2_VBI_UNSYNC;
+ if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
+ fmt->flags |= V4L2_VBI_INTERLACED;
+ return 0;
+ }
+ case VIDIOCSVBIFMT:
+ {
+ struct vbi_format *fmt = (void *) arg;
+ struct v4l2_format fmt2;
+
+ retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
+ if (0 != retval)
+ return retval;
+ bttv_vbi_get_fmt(fh, &fmt2);
+
+ if (fmt->sampling_rate != fmt2.fmt.vbi.sampling_rate ||
+ fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line ||
+ fmt->sample_format != VIDEO_PALETTE_RAW ||
+ fmt->start[0] != fmt2.fmt.vbi.start[0] ||
+ fmt->start[1] != fmt2.fmt.vbi.start[1] ||
+ fmt->count[0] != fmt->count[1] ||
+ fmt->count[0] < 1 ||
+ fmt->count[0] > 32 /* VBI_MAXLINES */)
+ return -EINVAL;
+
+ bttv_vbi_setlines(fh,btv,fmt->count[0]);
+ return 0;
+ }
+
case BTTV_VERSION:
case VIDIOCGFREQ:
case VIDIOCSFREQ:
{
struct v4l2_fmtdesc *f = arg;
enum v4l2_buf_type type;
- int i, index;
+ unsigned int i;
+ int index;
type = f->type;
if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
for (i = 0; i < BTTV_FORMATS; i++) {
if (bttv_formats[i].fourcc != -1)
index++;
- if (index == f->index)
+ if ((unsigned int)index == f->index)
break;
}
if (BTTV_FORMATS == i)
if (fh->btv->errors)
bttv_reinit_bt848(fh->btv);
- dprintk("read count=%d type=%s\n",
- (int)count,v4l2_type_names[fh->type]);
+ dprintk("bttv%d: read count=%d type=%s\n",
+ fh->btv->nr,(int)count,v4l2_type_names[fh->type]);
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
struct bttv_fh *fh = file->private_data;
struct bttv_buffer *buf;
+ enum v4l2_field field;
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
up(&fh->cap.lock);
return POLLERR;
}
- if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,fh->cap.field)) {
+ field = videobuf_next_field(&fh->cap);
+ if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,field)) {
up(&fh->cap.lock);
return POLLERR;
}
static int bttv_open(struct inode *inode, struct file *file)
{
- unsigned int minor = minor(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct bttv *btv = NULL;
struct bttv_fh *fh;
enum v4l2_buf_type type = 0;
- int i;
+ unsigned int i;
dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
file->private_data = fh;
*fh = btv->init;
fh->type = type;
+ fh->ov.setup_ok = 0;
videobuf_queue_init(&fh->cap, &bttv_video_qops,
btv->dev, &btv->s_lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
i2c_vidiocschan(btv);
btv->users++;
+ if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
+ bttv_vbi_setlines(fh,btv,16);
bttv_field_count(btv);
return 0;
}
static int radio_open(struct inode *inode, struct file *file)
{
- unsigned int minor = minor(inode->i_rdev);
+ int minor = minor(inode->i_rdev);
struct bttv *btv = NULL;
- unsigned long v = 400*16;
- int i;
+ u32 v = 400*16;
+ unsigned int i;
dprintk("bttv: open minor=%d\n",minor);
static void bttv_print_irqbits(u32 print, u32 mark)
{
- int i;
+ unsigned int i;
printk("bits:");
- for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) {
+ for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
if (print & (1 << i))
printk(" %s",irq_name[i]);
if (mark & (1 << i))
printk(" main: %08Lx\n",
(unsigned long long)btv->main.dma);
printk(" vbi : o=%08Lx e=%08Lx\n",
- btv->vcurr ? (unsigned long long)btv->vcurr->top.dma : 0,
- btv->vcurr ? (unsigned long long)btv->vcurr->bottom.dma : 0);
+ btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0,
+ btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0);
printk(" cap : o=%08Lx e=%08Lx\n",
- btv->top ? (unsigned long long)btv->top->top.dma : 0,
- btv->bottom ? (unsigned long long)btv->bottom->bottom.dma : 0);
+ btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
+ btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
printk(" scr : o=%08Lx e=%08Lx\n",
btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
}
-static void bttv_irq_timeout(unsigned long data)
-{
- struct bttv *btv = (struct bttv *)data;
- struct bttv_buffer *o_bottom,*o_top,*o_vcurr;
- struct bttv_buffer *capture;
-
- if (bttv_verbose) {
- printk(KERN_INFO "bttv%d: timeout: risc=%08x, ",
- btv->nr,btread(BT848_RISC_COUNT));
- bttv_print_irqbits(btread(BT848_INT_STAT),0);
- printk("\n");
- }
-
- spin_lock(&btv->s_lock);
- o_top = btv->top;
- o_bottom = btv->bottom;
- o_vcurr = btv->vcurr;
- btv->top = NULL;
- btv->bottom = NULL;
- btv->vcurr = NULL;
-
- /* deactivate stuff */
- bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
- bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
- bttv_set_dma(btv, 0, 0);
-
- /* wake up + free */
- if (o_top == o_bottom) {
- if (NULL != o_top) {
- o_top->vb.state = STATE_ERROR;
- wake_up(&o_top->vb.done);
- }
- } else {
- if (NULL != o_top) {
- o_top->vb.state = STATE_ERROR;
- wake_up(&o_top->vb.done);
- }
- if (NULL != o_bottom) {
- o_bottom->vb.state = STATE_ERROR;
- wake_up(&o_bottom->vb.done);
- }
- }
- if (NULL != o_vcurr) {
- o_vcurr->vb.state = STATE_ERROR;
- wake_up(&o_vcurr->vb.done);
- }
-
- /* cancel all outstanding capture / vbi requests */
- while (!list_empty(&btv->capture)) {
- capture = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
- list_del(&capture->vb.queue);
- capture->vb.state = STATE_ERROR;
- wake_up(&capture->vb.done);
- }
- while (!list_empty(&btv->vcapture)) {
- capture = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
- list_del(&capture->vb.queue);
- capture->vb.state = STATE_ERROR;
- wake_up(&capture->vb.done);
- }
-
- btv->errors++;
- spin_unlock(&btv->s_lock);
-}
-
-static void
-bttv_irq_switch_fields(struct bttv *btv)
+static int
+bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set)
{
- struct bttv_buffer *o_bottom,*o_top,*o_vcurr;
- struct bttv_buffer *capture;
- dma_addr_t rc;
- int irqflags = 0;
- struct timeval ts;
+ struct bttv_buffer *item;
- spin_lock(&btv->s_lock);
- o_top = btv->top;
- o_bottom = btv->bottom;
- o_vcurr = btv->vcurr;
- btv->top = NULL;
- btv->bottom = NULL;
- btv->vcurr = NULL;
+ memset(set,0,sizeof(*set));
/* vbi request ? */
if (!list_empty(&btv->vcapture)) {
- irqflags = 1;
- btv->vcurr = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
- list_del(&btv->vcurr->vb.queue);
+ set->irqflags = 1;
+ set->vbi = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
}
/* capture request ? */
if (!list_empty(&btv->capture)) {
- irqflags = 1;
- capture = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
- list_del(&capture->vb.queue);
- if (V4L2_FIELD_HAS_TOP(capture->vb.field))
- btv->top = capture;
- if (V4L2_FIELD_HAS_BOTTOM(capture->vb.field))
- btv->bottom = capture;
+ set->irqflags = 1;
+ item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
+ if (V4L2_FIELD_HAS_TOP(item->vb.field))
+ set->top = item;
+ if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
+ set->bottom = item;
/* capture request for other field ? */
- if (!V4L2_FIELD_HAS_BOTH(capture->vb.field) &&
- !list_empty(&btv->capture)) {
- capture = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
- if (!V4L2_FIELD_HAS_BOTH(capture->vb.field)) {
- if (NULL == btv->top &&
- V4L2_FIELD_TOP == capture->vb.field) {
- btv->top = capture;
- list_del(&capture->vb.queue);
+ if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
+ (item->vb.queue.next != &btv->capture)) {
+ item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
+ if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
+ if (NULL == set->top &&
+ V4L2_FIELD_TOP == item->vb.field) {
+ set->top = item;
}
- if (NULL == btv->bottom &&
- V4L2_FIELD_BOTTOM == capture->vb.field) {
- btv->bottom = capture;
- list_del(&capture->vb.queue);
+ if (NULL == set->bottom &&
+ V4L2_FIELD_BOTTOM == item->vb.field) {
+ set->bottom = item;
}
+ if (NULL != set->top && NULL != set->bottom)
+ set->topirq = 2;
}
}
}
/* screen overlay ? */
if (NULL != btv->screen) {
if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
- if (NULL == btv->top && NULL == btv->bottom) {
- btv->top = btv->screen;
- btv->bottom = btv->screen;
+ if (NULL == set->top && NULL == set->bottom) {
+ set->top = btv->screen;
+ set->bottom = btv->screen;
}
} else {
if (V4L2_FIELD_TOP == btv->screen->vb.field &&
- NULL == btv->top) {
- btv->top = btv->screen;
+ NULL == set->top) {
+ set->top = btv->screen;
}
if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
- NULL == btv->bottom) {
- btv->bottom = btv->screen;
+ NULL == set->bottom) {
+ set->bottom = btv->screen;
}
}
}
- if (irq_debug)
- printk(KERN_DEBUG "bttv%d: irq top=0x%08x bottom=0x%08x"
- " vbi=0x%08x/0x%08x\n", btv->nr,
- btv->top ? btv->top->top.dma : 0,
- btv->bottom ? btv->bottom->bottom.dma : 0,
- btv->vcurr ? btv->vcurr->top.dma : 0,
- btv->vcurr ? btv->vcurr->bottom.dma : 0);
+ dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p "
+ "[screen=%p,irq=%d,%d]\n",
+ btv->nr,set->top, set->bottom, set->vbi,
+ btv->screen,set->irqflags,set->topirq);
+ return 0;
+}
+
+static void
+bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup,
+ struct bttv_buffer_set *curr, unsigned int state)
+{
+ struct timeval ts;
- rc = btread(BT848_RISC_COUNT);
- if (rc < btv->main.dma || rc > btv->main.dma + 0x100)
- printk("bttv%d: Huh? IRQ latency? main=0x%x rc=0x%x\n",
- btv->nr,btv->main.dma,rc);
-
- /* activate new fields */
- bttv_buffer_activate(btv,btv->top,btv->bottom);
- if (btv->vcurr) {
- btv->vcurr->vb.state = STATE_ACTIVE;
- bttv_risc_hook(btv, RISC_SLOT_O_VBI, &btv->vcurr->top, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_VBI, &btv->vcurr->bottom, 0);
- } else {
- bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
- }
- bttv_set_dma(btv, 0, irqflags);
-
- /* wake up + free */
do_gettimeofday(&ts);
- if (o_top == o_bottom) {
- if (NULL != o_top && btv->top != o_top) {
- o_top->vb.ts = ts;
- o_top->vb.field_count = btv->field_count;
- o_top->vb.state = STATE_DONE;
- wake_up(&o_top->vb.done);
+
+ if (NULL != wakeup->vbi) {
+ wakeup->vbi->vb.ts = ts;
+ wakeup->vbi->vb.field_count = btv->field_count;
+ wakeup->vbi->vb.state = state;
+ wake_up(&wakeup->vbi->vb.done);
+ }
+ if (wakeup->top == wakeup->bottom) {
+ if (NULL != wakeup->top && curr->top != wakeup->top) {
+ if (irq_debug)
+ printk("bttv%d: wakeup: both=%p\n",btv->nr,wakeup->top);
+ wakeup->top->vb.ts = ts;
+ wakeup->top->vb.field_count = btv->field_count;
+ wakeup->top->vb.state = state;
+ wake_up(&wakeup->top->vb.done);
}
} else {
- if (NULL != o_top && btv->top != o_top) {
- o_top->vb.ts = ts;
- o_top->vb.field_count = btv->field_count;
- o_top->vb.state = STATE_DONE;
- wake_up(&o_top->vb.done);
+ if (NULL != wakeup->top && curr->top != wakeup->top) {
+ if (irq_debug)
+ printk("bttv%d: wakeup: top=%p\n",btv->nr,wakeup->top);
+ wakeup->top->vb.ts = ts;
+ wakeup->top->vb.field_count = btv->field_count;
+ wakeup->top->vb.state = state;
+ wake_up(&wakeup->top->vb.done);
}
- if (NULL != o_bottom && btv->bottom != o_bottom) {
- o_bottom->vb.ts = ts;
- o_bottom->vb.field_count = btv->field_count;
- o_bottom->vb.state = STATE_DONE;
- wake_up(&o_bottom->vb.done);
+ if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
+ if (irq_debug)
+ printk("bttv%d: wakeup: bottom=%p\n",btv->nr,wakeup->bottom);
+ wakeup->bottom->vb.ts = ts;
+ wakeup->bottom->vb.field_count = btv->field_count;
+ wakeup->bottom->vb.state = state;
+ wake_up(&wakeup->bottom->vb.done);
}
}
- if (NULL != o_vcurr) {
- o_vcurr->vb.ts = ts;
- o_vcurr->vb.field_count = btv->field_count;
- o_vcurr->vb.state = STATE_DONE;
- wake_up(&o_vcurr->vb.done);
+}
+
+static void bttv_irq_timeout(unsigned long data)
+{
+ struct bttv *btv = (struct bttv *)data;
+ struct bttv_buffer_set old,new;
+ struct bttv_buffer *item;
+
+ if (bttv_verbose) {
+ printk(KERN_INFO "bttv%d: timeout: risc=%08x, ",
+ btv->nr,btread(BT848_RISC_COUNT));
+ bttv_print_irqbits(btread(BT848_INT_STAT),0);
+ printk("\n");
+ }
+
+ spin_lock(&btv->s_lock);
+
+ /* deactivate stuff */
+ memset(&new,0,sizeof(new));
+ old = btv->curr;
+ btv->curr = new;
+ bttv_buffer_set_activate(btv, &new);
+ bttv_set_dma(btv, 0, 0);
+
+ /* wake up */
+ bttv_irq_wakeup_set(btv, &old, &new, STATE_ERROR);
+
+ /* cancel all outstanding capture / vbi requests */
+ while (!list_empty(&btv->capture)) {
+ item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
+ list_del(&item->vb.queue);
+ item->vb.state = STATE_ERROR;
+ wake_up(&item->vb.done);
}
+ while (!list_empty(&btv->vcapture)) {
+ item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
+ list_del(&item->vb.queue);
+ item->vb.state = STATE_ERROR;
+ wake_up(&item->vb.done);
+ }
+
+ btv->errors++;
+ spin_unlock(&btv->s_lock);
+}
+
+static void
+bttv_irq_wakeup_top(struct bttv *btv)
+{
+ struct bttv_buffer *wakeup = btv->curr.top;
+
+ if (NULL == wakeup)
+ return;
+
+ spin_lock(&btv->s_lock);
+ btv->curr.topirq = 0;
+ btv->curr.top = NULL;
+ bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+
+ do_gettimeofday(&wakeup->vb.ts);
+ wakeup->vb.field_count = btv->field_count;
+ wakeup->vb.state = STATE_DONE;
+ wake_up(&wakeup->vb.done);
+ spin_unlock(&btv->s_lock);
+}
+
+static void
+bttv_irq_switch_fields(struct bttv *btv)
+{
+ struct bttv_buffer_set new;
+ struct bttv_buffer_set old;
+ dma_addr_t rc;
+
+ spin_lock(&btv->s_lock);
+
+ /* new buffer set */
+ bttv_irq_next_set(btv, &new);
+ rc = btread(BT848_RISC_COUNT);
+ if (rc < btv->main.dma || rc > btv->main.dma + 0x100) {
+ if (1 /* irq_debug */)
+ printk("bttv%d: skipped frame. no signal? high irq latency?\n",
+ btv->nr);
+ spin_unlock(&btv->s_lock);
+ return;
+ }
+
+ /* switch over */
+ old = btv->curr;
+ btv->curr = new;
+ bttv_buffer_set_activate(btv, &new);
+ bttv_set_dma(btv, 0, new.irqflags);
+
+ /* wake up finished buffers */
+ bttv_irq_wakeup_set(btv, &old, &new, STATE_DONE);
spin_unlock(&btv->s_lock);
}
/* get device status bits */
dstat=btread(BT848_DSTATUS);
- if (irq_debug) {
+ if (0 /*irq_debug*/) {
printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d "
"riscs=%x, riscc=%08x, ",
btv->nr, count, btv->field_count,
if (astat & BT848_INT_GPINT)
wake_up(&btv->gpioq);
-
+
+ if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
+ bttv_irq_wakeup_top(btv);
+
if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
bttv_irq_switch_fields(btv);
btv->timeout.data = (unsigned long)btv;
btv->i2c_rc = -1;
- btv->tuner_type = -1;
+ btv->tuner_type = UNSET;
+ btv->pinnacle_id = UNSET;
memcpy(&btv->video_dev, &bttv_video_template, sizeof(bttv_video_template));
memcpy(&btv->radio_dev, &radio_template, sizeof(radio_template));
video_unregister_device(&btv->vbi_dev);
/* free allocated memory */
- bttv_riscmem_free(btv->dev,&btv->main);
+ btcx_riscmem_free(btv->dev,&btv->main);
/* free ressources */
free_irq(btv->dev->irq,btv);
static int bttv_init_module(void)
{
+ int rc;
bttv_num = 0;
printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
bttv_check_chipset();
- return pci_module_init(&bttv_pci_driver);
+ rc = pci_module_init(&bttv_pci_driver);
+ if (-ENODEV == rc) {
+ /* plenty of people trying to use bttv for the cx2388x ... */
+ if (NULL != pci_find_device(0x14f1, 0x8800, NULL))
+ printk("bttv doesn't support your Conexant 2388x card.\n");
+ }
+ return rc;
}
static void bttv_cleanup_module(void)
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
if (btv->tuner_type != UNSET)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
+ if (btv->pinnacle_id != UNSET)
+ bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
+ &btv->pinnacle_id);
if (bttv_debug)
printk("bttv%d: i2c attach [client=%s]\n",
static struct i2c_adapter bttv_i2c_adap_template = {
.owner = THIS_MODULE,
+ .class = I2C_ADAP_CLASS_TV_ANALOG,
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
- .class = I2C_ADAP_CLASS_TV_ANALOG,
.client_register = attach_inform,
};
sizeof(struct i2c_client));
sprintf(btv->i2c_adap.dev.name, "bt848 #%d", btv->nr);
+ btv->i2c_adap.dev.parent = &btv->dev->dev;
btv->i2c_algo.data = btv;
i2c_set_adapdata(&btv->i2c_adap, btv);
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include "bttvp.h"
-/* ---------------------------------------------------------- */
-/* allocate/free risc memory */
-
-int bttv_riscmem_alloc(struct pci_dev *pci,
- struct bttv_riscmem *risc,
- unsigned int size)
-{
- u32 *cpu;
- dma_addr_t dma;
-
- cpu = pci_alloc_consistent(pci, size, &dma);
- if (NULL == cpu)
- return -ENOMEM;
- memset(cpu,0,size);
-
- if (risc->cpu && risc->size < size) {
- /* realloc (enlarge buffer) -- copy old stuff */
- memcpy(cpu,risc->cpu,risc->size);
- bttv_riscmem_free(pci,risc);
- }
- risc->cpu = cpu;
- risc->dma = dma;
- risc->size = size;
-
- return 0;
-}
-
-void bttv_riscmem_free(struct pci_dev *pci,
- struct bttv_riscmem *risc)
-{
- if (NULL == risc->cpu)
- return;
- pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
- memset(risc,0,sizeof(*risc));
-}
-
/* ---------------------------------------------------------- */
/* risc code generators */
int
-bttv_risc_packed(struct bttv *btv, struct bttv_riscmem *risc,
+bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
struct scatterlist *sglist,
- int offset, int bpl, int padding, int lines)
+ unsigned int offset, unsigned int bpl,
+ unsigned int padding, unsigned int lines)
{
- int instructions,rc,line,todo;
+ u32 instructions,line,todo;
struct scatterlist *sg;
u32 *rp;
+ int rc;
/* estimate risc mem: worst case is one write per page border +
one write per scan line + sync + jump (all 2 dwords) */
instructions = (bpl * lines) / PAGE_SIZE + lines;
instructions += 2;
- if ((rc = bttv_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
+ if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
return rc;
/* sync instruction */
}
offset += padding;
}
+ dprintk("bttv%d: risc planar: %d sglist elems\n", btv->nr, (int)(sg-sglist));
/* save pointer to jmp instruction address */
risc->jmp = rp;
}
int
-bttv_risc_planar(struct bttv *btv, struct bttv_riscmem *risc,
+bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
struct scatterlist *sglist,
- int yoffset, int ybpl, int ypadding, int ylines,
- int uoffset, int voffset, int hshift, int vshift,
- int cpadding)
+ unsigned int yoffset, unsigned int ybpl,
+ unsigned int ypadding, unsigned int ylines,
+ unsigned int uoffset, unsigned int voffset,
+ unsigned int hshift, unsigned int vshift,
+ unsigned int cpadding)
{
- int instructions,rc,line,todo,ylen,chroma;
+ unsigned int instructions,line,todo,ylen,chroma;
u32 *rp,ri;
struct scatterlist *ysg;
struct scatterlist *usg;
struct scatterlist *vsg;
+ int rc;
/* estimate risc mem: worst case is one write per page border +
one write per scan line (5 dwords)
plus sync + jump (2 dwords) */
instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
instructions += 2;
- if ((rc = bttv_riscmem_alloc(btv->dev,risc,instructions*4*5)) < 0)
+ if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*4*5)) < 0)
return rc;
/* sync instruction */
return 0;
}
-/* ---------------------------------------------------------- */
-
-struct SKIPLIST {
- int start;
- int end;
-};
-
-int
-bttv_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
- struct v4l2_clip *clips, int n)
-{
- if (win->left < 0) {
- /* left */
- clips[n].c.left = 0;
- clips[n].c.top = 0;
- clips[n].c.width = -win->left;
- clips[n].c.height = win->height;
- n++;
- }
- if (win->left + win->width > swidth) {
- /* right */
- clips[n].c.left = swidth - win->left;
- clips[n].c.top = 0;
- clips[n].c.width = win->width - clips[n].c.left;
- clips[n].c.height = win->height;
- n++;
- }
- if (win->top < 0) {
- /* top */
- clips[n].c.left = 0;
- clips[n].c.top = 0;
- clips[n].c.width = win->width;
- clips[n].c.height = -win->top;
- n++;
- }
- if (win->top + win->height > sheight) {
- /* bottom */
- clips[n].c.left = 0;
- clips[n].c.top = sheight - win->top;
- clips[n].c.width = win->width;
- clips[n].c.height = win->height - clips[n].c.top;
- n++;
- }
- return n;
-}
-
-void
-bttv_sort_clips(struct v4l2_clip *clips, int nclips)
-{
- struct v4l2_clip swap;
- int i,j,n;
-
- for (i = nclips-2; i >= 0; i--) {
- for (n = 0, j = 0; j <= i; j++) {
- if (clips[j].c.left > clips[j+1].c.left) {
- swap = clips[j];
- clips[j] = clips[j+1];
- clips[j+1] = swap;
- n++;
- }
- }
- if (0 == n)
- break;
- }
-}
-
-static void
-calc_skips(int line, int width, int *maxy,
- struct SKIPLIST *skips, int *nskips,
- const struct v4l2_clip *clips, int nclips)
-{
- int clip,skip,maxline,end;
-
- skip=0;
- maxline = 9999;
- for (clip = 0; clip < nclips; clip++) {
-
- /* sanity checks */
- if (clips[clip].c.left + clips[clip].c.width <= 0)
- continue;
- if (clips[clip].c.left > width)
- break;
-
- /* vertical range */
- if (line > clips[clip].c.top+clips[clip].c.height-1)
- continue;
- if (line < clips[clip].c.top) {
- if (maxline > clips[clip].c.top-1)
- maxline = clips[clip].c.top-1;
- continue;
- }
- if (maxline > clips[clip].c.top+clips[clip].c.height-1)
- maxline = clips[clip].c.top+clips[clip].c.height-1;
-
- /* horizontal range */
- if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
- /* new one */
- skips[skip].start = clips[clip].c.left;
- if (skips[skip].start < 0)
- skips[skip].start = 0;
- skips[skip].end = clips[clip].c.left + clips[clip].c.width;
- if (skips[skip].end > width)
- skips[skip].end = width;
- skip++;
- } else {
- /* overlaps -- expand last one */
- end = clips[clip].c.left + clips[clip].c.width;
- if (skips[skip-1].end < end)
- skips[skip-1].end = end;
- if (skips[skip-1].end > width)
- skips[skip-1].end = width;
- }
- }
- *nskips = skip;
- *maxy = maxline;
-
- if (bttv_debug) {
- printk(KERN_DEBUG "bttv: skips line %d-%d:",line,maxline);
- for (skip = 0; skip < *nskips; skip++) {
- printk(" %d-%d",skips[skip].start,skips[skip].end);
- }
- printk("\n");
- }
-}
-
int
-bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
+bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
const struct bttv_format *fmt, struct bttv_overlay *ov,
int skip_even, int skip_odd)
{
int instructions,rc,line,maxy,start,end,skip,nskips;
- struct SKIPLIST *skips;
+ struct btcx_skiplist *skips;
u32 *rp,ri,ra;
u32 addr;
instructions = (ov->nclips + 1) *
((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
instructions += 2;
- if ((rc = bttv_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
+ if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0)
return rc;
/* sync instruction */
/* calculate clipping */
if (line > maxy)
- calc_skips(line, ov->w.width, &maxy,
- skips, &nskips, ov->clips, ov->nclips);
+ btcx_calc_skips(line, ov->w.width, &maxy,
+ skips, &nskips, ov->clips, ov->nclips);
/* write out risc code */
for (start = 0, skip = 0; start < ov->w.width; start = end) {
/* save pointer to jmp instruction address */
risc->jmp = rp;
-
kfree(skips);
return 0;
}
geo->vdelay = vdelay;
geo->width = width;
geo->sheight = tvnorm->sheight;
+ geo->vtotal = tvnorm->vtotal;
if (btv->opt_combfilter) {
geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
btwrite(geo->crop, BT848_E_CROP+off);
+ btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
+ btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
}
/* ---------------------------------------------------------- */
int capctl;
btv->cap_ctl = 0;
- if (NULL != btv->top) btv->cap_ctl |= 0x02;
- if (NULL != btv->bottom) btv->cap_ctl |= 0x01;
- if (NULL != btv->vcurr) btv->cap_ctl |= 0x0c;
+ if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
+ if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
+ if (NULL != btv->curr.vbi) btv->cap_ctl |= 0x0c;
capctl = 0;
capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
d2printk(KERN_DEBUG
"bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
btv->nr,capctl,irqflags,
- btv->vcurr ? (unsigned long long)btv->vcurr->top.dma : 0,
- btv->top ? (unsigned long long)btv->top->top.dma : 0,
- btv->vcurr ? (unsigned long long)btv->vcurr->bottom.dma : 0,
- btv->bottom ? (unsigned long long)btv->bottom->bottom.dma : 0);
+ btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0,
+ btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
+ btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0,
+ btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
cmd = BT848_RISC_JUMP;
if (irqflags) {
- cmd |= BT848_RISC_IRQ | (irqflags << 16);
+ cmd |= BT848_RISC_IRQ;
+ cmd |= (irqflags & 0x0f) << 16;
+ cmd |= (~irqflags & 0x0f) << 20;
mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
} else {
del_timer(&btv->timeout);
{
int rc;
- if ((rc = bttv_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0)
+ if ((rc = btcx_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0)
return rc;
dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
btv->nr,(unsigned long long)btv->main.dma);
}
int
-bttv_risc_hook(struct bttv *btv, int slot, struct bttv_riscmem *risc,
+bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
int irqflags)
{
unsigned long cmd;
d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
btv->nr,risc,slot,(unsigned long long)risc->dma,irqflags);
cmd = BT848_RISC_JUMP;
- if (irqflags)
- cmd |= BT848_RISC_IRQ | (irqflags << 16);
+ if (irqflags) {
+ cmd |= BT848_RISC_IRQ;
+ cmd |= (irqflags & 0x0f) << 16;
+ cmd |= (~irqflags & 0x0f) << 20;
+ }
risc->jmp[0] = cpu_to_le32(cmd);
risc->jmp[1] = cpu_to_le32(next);
btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
videobuf_waiton(&buf->vb,0,0);
videobuf_dma_pci_unmap(btv->dev, &buf->vb.dma);
videobuf_dma_free(&buf->vb.dma);
- bttv_riscmem_free(btv->dev,&buf->bottom);
- bttv_riscmem_free(btv->dev,&buf->top);
+ btcx_riscmem_free(btv->dev,&buf->bottom);
+ btcx_riscmem_free(btv->dev,&buf->top);
buf->vb.state = STATE_NEEDS_INIT;
}
int
-bttv_buffer_activate(struct bttv *btv,
- struct bttv_buffer *top,
- struct bttv_buffer *bottom)
+bttv_buffer_set_activate(struct bttv *btv,
+ struct bttv_buffer_set *set)
{
- if (NULL != top && NULL != bottom) {
- top->vb.state = STATE_ACTIVE;
- bottom->vb.state = STATE_ACTIVE;
- bttv_apply_geo(btv, &top->geo, 1);
- bttv_apply_geo(btv, &bottom->geo,0);
- bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &top->top, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &bottom->bottom, 0);
- btaor((top->btformat & 0xf0) | (bottom->btformat & 0x0f),
+ /* vbi capture */
+ if (set->vbi) {
+ set->vbi->vb.state = STATE_ACTIVE;
+ list_del(&set->vbi->vb.queue);
+ bttv_risc_hook(btv, RISC_SLOT_O_VBI, &set->vbi->top, 0);
+ bttv_risc_hook(btv, RISC_SLOT_E_VBI, &set->vbi->bottom, 0);
+ } else {
+ bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
+ bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
+ }
+
+ /* video capture */
+ if (NULL != set->top && NULL != set->bottom) {
+ if (set->top == set->bottom) {
+ set->top->vb.state = STATE_ACTIVE;
+ if (set->top->vb.queue.next)
+ list_del(&set->top->vb.queue);
+ } else {
+ set->top->vb.state = STATE_ACTIVE;
+ set->bottom->vb.state = STATE_ACTIVE;
+ if (set->top->vb.queue.next)
+ list_del(&set->top->vb.queue);
+ if (set->bottom->vb.queue.next)
+ list_del(&set->bottom->vb.queue);
+ }
+ bttv_apply_geo(btv, &set->top->geo, 1);
+ bttv_apply_geo(btv, &set->bottom->geo,0);
+ bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, set->topirq);
+ bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0);
+ btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
~0xff, BT848_COLOR_FMT);
- btaor((top->btswap & 0x0a) | (bottom->btswap & 0x05),
+ btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
~0x0f, BT848_COLOR_CTL);
- } else if (NULL != top) {
- top->vb.state = STATE_ACTIVE;
- bttv_apply_geo(btv, &top->geo,1);
- bttv_apply_geo(btv, &top->geo,0);
- bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &top->top, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
- btaor(top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
- btaor(top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
- } else if (NULL != bottom) {
- bottom->vb.state = STATE_ACTIVE;
- bttv_apply_geo(btv, &bottom->geo,1);
- bttv_apply_geo(btv, &bottom->geo,0);
- bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
- bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &bottom->bottom, 0);
- btaor(bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
- btaor(bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
+ } else if (NULL != set->top) {
+ set->top->vb.state = STATE_ACTIVE;
+ if (set->top->vb.queue.next)
+ list_del(&set->top->vb.queue);
+ bttv_apply_geo(btv, &set->top->geo,1);
+ bttv_apply_geo(btv, &set->top->geo,0);
+ bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, 0);
+ bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
+ btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
+ btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
+ } else if (NULL != set->bottom) {
+ set->bottom->vb.state = STATE_ACTIVE;
+ if (set->bottom->vb.queue.next)
+ list_del(&set->bottom->vb.queue);
+ bttv_apply_geo(btv, &set->bottom->geo,1);
+ bttv_apply_geo(btv, &set->bottom->geo,0);
+ bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+ bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0);
+ btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
+ btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
} else {
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
/* Y-Cr-Cb plane order */
uoffset >>= buf->fmt->hshift;
uoffset >>= buf->fmt->vshift;
- uoffset += voffset;
+ uoffset += voffset;
} else {
/* Y-Cb-Cr plane order */
voffset >>= buf->fmt->hshift;
voffset >>= buf->fmt->vshift;
- voffset += uoffset;
+ voffset += uoffset;
}
switch (buf->vb.field) {
buf->fmt->vshift,
cpadding);
break;
+ case V4L2_FIELD_SEQ_TB:
+ bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+ buf->vb.height,1,buf->tvnorm);
+ lines = buf->vb.height >> 1;
+ ypadding = buf->vb.width;
+ cpadding = buf->vb.width >> buf->fmt->hshift;
+ bttv_risc_planar(btv,&buf->top,
+ buf->vb.dma.sglist,
+ 0,buf->vb.width,0,lines,
+ uoffset >> 1,
+ voffset >> 1,
+ buf->fmt->hshift,
+ buf->fmt->vshift,
+ 0);
+ bttv_risc_planar(btv,&buf->bottom,
+ buf->vb.dma.sglist,
+ lines * ypadding,buf->vb.width,0,lines,
+ lines * ypadding + (uoffset >> 1),
+ lines * ypadding + (voffset >> 1),
+ buf->fmt->hshift,
+ buf->fmt->vshift,
+ 0);
+ break;
default:
BUG();
}
/* build risc code */
switch (ov->field) {
case V4L2_FIELD_TOP:
- bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
+ bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
break;
case V4L2_FIELD_BOTTOM:
bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
}
static int vbi_buffer_setup(struct file *file,
- unsigned int *count, unsigned int *size)
+ unsigned int *count, unsigned int *size)
{
struct bttv_fh *fh = file->private_data;
struct bttv *btv = fh->btv;
}
}
-void bttv_vbi_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
{
+ const struct bttv_tvnorm *tvnorm;
+ u32 start0,start1;
+ s32 count0,count1,count;
+
+ tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
+ f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ f->fmt.vbi.sampling_rate = tvnorm->Fsc;
+ f->fmt.vbi.samples_per_line = 2048;
+ f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+ f->fmt.vbi.offset = 244;
+ f->fmt.vbi.flags = 0;
+ switch (fh->btv->tvnorm) {
+ case 1: /* NTSC */
+ start0 = 10;
+ start1 = 273;
+ break;
+ case 0: /* PAL */
+ case 2: /* SECAM */
+ default:
+ start0 = 7;
+ start1 = 319;
+ }
+
+ count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0;
+ count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1;
+ count = max(count0,count1);
+ if (count > VBI_MAXLINES)
+ count = VBI_MAXLINES;
+ if (count < 1)
+ count = 1;
+
+ f->fmt.vbi.start[0] = start0;
+ f->fmt.vbi.start[1] = start1;
+ f->fmt.vbi.count[0] = count;
+ f->fmt.vbi.count[1] = count;
+}
+
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+{
+ const struct bttv_tvnorm *tvnorm;
+
+ tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
memset(f,0,sizeof(*f));
f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- f->fmt.vbi.sampling_rate = 35468950;
+ f->fmt.vbi.sampling_rate = tvnorm->Fsc;
f->fmt.vbi.samples_per_line = 2048;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
f->fmt.vbi.offset = 244;
#define BTTV_SENSORAY311 0x49
#define BTTV_RV605 0x4a
#define BTTV_WINDVR 0x4c
+#define BTTV_GRANDTEC 0x4d
#define BTTV_KWORLD 0x4e
#define BTTV_HAUPPAUGEPVR 0x50
#define BTTV_GVBCTV5PCI 0x51
#define BTTV_PINNACLESAT 0x5e
#define BTTV_FORMAC_PROTV 0x5f
#define BTTV_EURESYS_PICOLO 0x61
+#define BTTV_PV150 0x62
+#define BTTV_AD_TVK503 0x63
+#define BTTV_IVC200 0x66
+#define BTTV_XGUARD 0x67
+#define BTTV_NEBULA_DIGITV 0x68
+#define BTTV_PV143 0x69
/* i2c address list */
#define I2C_TSA5522 0xc2
#define I2C_STBEE 0xae
#define I2C_VHX 0xc0
#define I2C_MSP3400 0x80
+#define I2C_MSP3400_ALT 0x88
#define I2C_TEA6300 0x80
#define I2C_DPL3518 0x84
#define I2C_TDA9887 0x86
struct tvcard
{
char *name;
- int video_inputs;
- int audio_inputs;
- int tuner;
- int svhs;
- int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
+ unsigned int video_inputs;
+ unsigned int audio_inputs;
+ unsigned int tuner;
+ unsigned int svhs;
+ unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
u32 gpiomask;
u32 muxsel[16];
u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */
u32 gpiomask2; /* GPIO MUX mask */
/* i2c audio flags */
- int no_msp34xx:1;
- int no_tda9875:1;
- int no_tda7432:1;
- int needs_tvaudio:1;
+ unsigned int no_msp34xx:1;
+ unsigned int no_tda9875:1;
+ unsigned int no_tda7432:1;
+ unsigned int needs_tvaudio:1;
+ unsigned int msp34xx_alt:1;
/* other settings */
- int pll;
+ unsigned int pll;
#define PLL_NONE 0
#define PLL_28 1
#define PLL_35 2
- int tuner_type;
- int has_radio;
+ unsigned int tuner_type;
+ unsigned int has_radio;
void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
void (*muxsel_hook)(struct bttv *btv, unsigned int input);
};
extern struct tvcard bttv_tvcards[];
-extern const int bttv_num_tvcards;
+extern const unsigned int bttv_num_tvcards;
/* identification / initialization of the card */
extern void bttv_idcard(struct bttv *btv);
#ifndef _BTTVP_H_
#define _BTTVP_H_
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,4)
+#include <linux/version.h>
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,11)
#include <linux/types.h>
#include <linux/wait.h>
#include "bt848.h"
#include "bttv.h"
+#include "btcx-risc.h"
#ifdef __KERNEL__
/* ---------------------------------------------------------- */
-struct bttv_tvnorm
-{
+struct bttv_tvnorm {
int v4l2_id;
char *name;
u32 Fsc;
u16 hdelayx1, hactivex1;
u16 vdelay;
u8 vbipack;
+ u16 vtotal;
int sram;
};
extern const struct bttv_tvnorm bttv_tvnorms[];
-extern const int BTTV_TVNORMS;
+extern const unsigned int BTTV_TVNORMS;
struct bttv_format {
char *name;
int hshift,vshift; /* for planar modes */
};
extern const struct bttv_format bttv_formats[];
-extern const int BTTV_FORMATS;
+extern const unsigned int BTTV_FORMATS;
/* ---------------------------------------------------------- */
struct bttv_geometry {
u8 vtc,crop,comb;
u16 width,hscale,hdelay;
- u16 sheight,vscale,vdelay;
-};
-
-struct bttv_riscmem {
- unsigned int size;
- u32 *cpu;
- u32 *jmp;
- dma_addr_t dma;
+ u16 sheight,vscale,vdelay,vtotal;
};
struct bttv_buffer {
int btformat;
int btswap;
struct bttv_geometry geo;
- struct bttv_riscmem top;
- struct bttv_riscmem bottom;
+ struct btcx_riscmem top;
+ struct btcx_riscmem bottom;
+};
+
+struct bttv_buffer_set {
+ struct bttv_buffer *top; /* top field buffer */
+ struct bttv_buffer *bottom; /* bottom field buffer */
+ struct bttv_buffer *vbi; /* vbi buffer */
+ unsigned int irqflags;
+ unsigned int topirq;
};
struct bttv_overlay {
- int tvnorm;
+ int tvnorm;
struct v4l2_rect w;
enum v4l2_field field;
struct v4l2_clip *clips;
int nclips;
+ int setup_ok;
};
struct bttv_fh {
/* video capture */
struct videobuf_queue cap;
- /* struct bttv_buffer buf; */
const struct bttv_format *fmt;
int width;
int height;
/* ---------------------------------------------------------- */
/* bttv-risc.c */
-/* alloc/free memory */
-int bttv_riscmem_alloc(struct pci_dev *pci,
- struct bttv_riscmem *risc,
- unsigned int size);
-void bttv_riscmem_free(struct pci_dev *pci,
- struct bttv_riscmem *risc);
-
/* risc code generators - capture */
-int bttv_risc_packed(struct bttv *btv, struct bttv_riscmem *risc,
+int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
struct scatterlist *sglist,
- int offset, int bpl, int pitch, int lines);
-int bttv_risc_planar(struct bttv *btv, struct bttv_riscmem *risc,
+ unsigned int offset, unsigned int bpl,
+ unsigned int pitch, unsigned int lines);
+int bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
struct scatterlist *sglist,
- int yoffset, int ybpl, int ypadding, int ylines,
- int uoffset, int voffset, int hshift, int vshift,
- int cpadding);
-
-/* risc code generator + helpers - screen overlay */
-int bttv_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
- struct v4l2_clip *clips, int n);
-void bttv_sort_clips(struct v4l2_clip *clips, int nclips);
-int bttv_risc_overlay(struct bttv *btv, struct bttv_riscmem *risc,
+ unsigned int yoffset, unsigned int ybpl,
+ unsigned int ypadding, unsigned int ylines,
+ unsigned int uoffset, unsigned int voffset,
+ unsigned int hshift, unsigned int vshift,
+ unsigned int cpadding);
+int bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
const struct bttv_format *fmt,
struct bttv_overlay *ov,
int skip_top, int skip_bottom);
/* control dma register + risc main loop */
void bttv_set_dma(struct bttv *btv, int override, int irqflags);
int bttv_risc_init_main(struct bttv *btv);
-int bttv_risc_hook(struct bttv *btv, int slot, struct bttv_riscmem *risc,
+int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
int irqflags);
/* capture buffer handling */
int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
-int bttv_buffer_activate(struct bttv *btv, struct bttv_buffer *top,
- struct bttv_buffer *bottom);
+int bttv_buffer_set_activate(struct bttv *btv,
+ struct bttv_buffer_set *set);
void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf);
/* overlay handling */
/* ---------------------------------------------------------- */
/* bttv-vbi.c */
-void bttv_vbi_fmt(struct bttv_fh *fh, struct v4l2_format *f);
+void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f);
+void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f);
void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines);
extern struct videobuf_queue_ops bttv_vbi_qops;
#define d2printk if (bttv_debug >= 2) printk
/* our devices */
-#define BTTV_MAX 4
-extern int bttv_num;
+#define BTTV_MAX 16
+extern unsigned int bttv_num;
extern struct bttv bttvs[BTTV_MAX];
#define BTTV_MAX_FBUF 0x208000
unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */
char name[8]; /* dev name */
unsigned int cardid; /* pci subsystem id (bt878 based ones) */
- int type; /* card type (pointer into tvcards[]) */
- int tuner_type; /* tuner chip type */
+ unsigned int type; /* card type (pointer into tvcards[]) */
+ unsigned int tuner_type; /* tuner chip type */
+ unsigned int pinnacle_id;
struct bttv_pll_info pll;
int triton1;
struct semaphore reslock;
/* video state */
- int input;
- int audio;
+ unsigned int input;
+ unsigned int audio;
unsigned long freq;
int tvnorm,hue,contrast,bright,saturation;
struct video_buffer fbuf;
- int field_count;
+ unsigned int field_count;
/* various options */
int opt_combfilter;
/* risc memory management data
- must aquire s_lock before changing these
- - only the irq handler is supported to touch odd + even */
- struct bttv_riscmem main;
- struct bttv_buffer *top; /* current active top field */
- struct bttv_buffer *bottom; /* current active bottom field */
- struct bttv_buffer *screen; /* overlay */
- struct list_head capture; /* capture buffer queue */
- struct bttv_buffer *vcurr;
- struct list_head vcapture;
+ - only the irq handler is supported to touch top + bottom + vcurr */
+ struct btcx_riscmem main;
+ struct bttv_buffer *screen; /* overlay */
+ struct list_head capture; /* video capture queue */
+ struct list_head vcapture; /* vbi capture queue */
+ struct bttv_buffer_set curr; /* active buffers */
unsigned long cap_ctl;
unsigned long dma_on;
struct timer_list timeout;
- int errors;
+ unsigned int errors;
- int users;
+ unsigned int users;
struct bttv_fh init;
};