This is a major bttv driver update. It was missed for some reason on the last batch of v4l driver updates. Not mailed to lkml because it is very big, alot of changes accumulated over time ... Changes: * 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. * splitted 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. 25-akpm/drivers/media/video/Makefile | 2 25-akpm/drivers/media/video/bt848.h | 38 - 25-akpm/drivers/media/video/btcx-risc.c | 265 ++++++++++++ 25-akpm/drivers/media/video/btcx-risc.h | 33 + 25-akpm/drivers/media/video/bttv-cards.c | 530 ++++++++++++++++++++---- 25-akpm/drivers/media/video/bttv-driver.c | 648 +++++++++++++++++------------- 25-akpm/drivers/media/video/bttv-if.c | 7 25-akpm/drivers/media/video/bttv-risc.c | 347 +++++----------- 25-akpm/drivers/media/video/bttv-vbi.c | 49 ++ 25-akpm/drivers/media/video/bttv.h | 35 + 25-akpm/drivers/media/video/bttvp.h | 108 ++--- 11 files changed, 1383 insertions(+), 679 deletions(-) diff -puN drivers/media/video/bt848.h~bttv-driver-update drivers/media/video/bt848.h --- 25/drivers/media/video/bt848.h~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bt848.h Mon Jul 28 16:23:01 2003 @@ -204,6 +204,9 @@ #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) @@ -311,29 +314,28 @@ /* 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_WRITE123 (0x09<<28) -#define BT848_RISC_SKIP123 (0x0a<<28) -#define BT848_RISC_WRITE1S23 (0x0b<<28) +#define BT848_RISC_SOL (1U<<27) +#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 !! */ diff -puN /dev/null drivers/media/video/btcx-risc.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/drivers/media/video/btcx-risc.c Mon Jul 28 16:23:01 2003 @@ -0,0 +1,265 @@ +/* + btcx-risc.c + + bt848/bt878/cx2388x risc code generator. + + (c) 2000-03 Gerd Knorr [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 +#include +#include +#include +#include +#include +#include + +#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: + */ diff -puN /dev/null drivers/media/video/btcx-risc.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/drivers/media/video/btcx-risc.h Mon Jul 28 16:23:01 2003 @@ -0,0 +1,33 @@ + +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: + */ diff -puN drivers/media/video/bttv-cards.c~bttv-driver-update drivers/media/video/bttv-cards.c --- 25/drivers/media/video/bttv-cards.c~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttv-cards.c Mon Jul 28 16:23:01 2003 @@ -21,15 +21,16 @@ 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 +#include #include #include #include #include #include +#include #include @@ -55,32 +56,34 @@ static void winfast2000_audio(struct btt 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"); @@ -149,13 +152,16 @@ static struct CARD { { 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" }, @@ -163,6 +169,7 @@ static struct CARD { { 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" }, @@ -192,6 +199,30 @@ static struct CARD { { 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" }, @@ -202,7 +233,10 @@ static struct CARD { { 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 } }; @@ -307,7 +341,7 @@ struct tvcard bttv_tvcards[] = { },{ /* ---- 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, @@ -376,6 +410,7 @@ struct tvcard bttv_tvcards[] = { .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, },{ @@ -613,7 +648,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, },{ - .name = "Formac iProTV", + .name = "Formac iProTV, Formac ProTV I (bt848)", .video_inputs = 4, .audio_inputs = 1, .tuner = 0, @@ -721,7 +756,7 @@ struct tvcard bttv_tvcards[] = { .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, @@ -763,6 +798,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = -1, .has_radio = 1, + .audio_hook = avermedia_tvphone_audio, },{ .name = "ProVideo PV951", /* pic16c54 */ .video_inputs = 3, @@ -904,10 +940,10 @@ struct tvcard bttv_tvcards[] = { /* ---- card 0x34 ---------------------------------- */ /* David Härdeman */ .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}, @@ -1531,11 +1567,13 @@ struct tvcard bttv_tvcards[] = { .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, @@ -1554,8 +1592,8 @@ struct tvcard bttv_tvcards[] = { not soldered here, though unknown wiring. Card lacks: external audio in, pci subsystem id. */ - },{ + /* ---- card 0x60 ---------------------------------- */ .name = "MachTV", .video_inputs = 3, @@ -1580,9 +1618,190 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .muxsel = { 2, 0, 1}, .pll = PLL_28, +},{ + /* Luc Van Hoeylandt */ + .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 */ + /* 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 */ + .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 */ + .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); /* ----------------------------------------------------------------------- */ @@ -1614,19 +1833,21 @@ void __devinit bttv_idcard(struct bttv * 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 */ @@ -1636,14 +1857,14 @@ void __devinit bttv_idcard(struct bttv * 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]; @@ -1655,7 +1876,7 @@ void __devinit bttv_idcard(struct bttv * 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++) { @@ -1669,13 +1890,22 @@ void __devinit bttv_idcard(struct bttv * */ /* 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) @@ -1779,7 +2009,8 @@ static void miro_pinnacle_gpio(struct bt 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"), @@ -1813,13 +2044,13 @@ static void miro_pinnacle_gpio(struct bt 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; } } @@ -1885,6 +2116,9 @@ void __devinit bttv_init_card1(struct bt case BTTV_VOODOOTV_FM: boot_msp34xx(btv,20); break; + case BTTV_AVERMEDIA98: + boot_msp34xx(btv,11); + break; case BTTV_HAUPPAUGEPVR: pvr_boot(btv); break; @@ -1897,13 +2131,8 @@ void __devinit bttv_init_card2(struct bt 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) { @@ -2027,18 +2256,20 @@ void __devinit bttv_init_card2(struct bt 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; @@ -2056,6 +2287,12 @@ void __devinit bttv_init_card2(struct bt 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) @@ -2073,7 +2310,12 @@ void __devinit bttv_init_card2(struct bt 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"); } @@ -2136,9 +2378,9 @@ hauppauge_tuner[] __devinitdata = { 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"} }; @@ -2147,15 +2389,17 @@ static void modtec_eeprom(struct bttv *b { 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", @@ -2169,9 +2413,8 @@ static void __devinit hauppauge_eeprom(s 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; @@ -2222,14 +2465,6 @@ static int terratec_active_radio_upgrade * 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 @@ -2274,6 +2509,16 @@ static int __devinit pvr_altera_load(str 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; @@ -2281,8 +2526,11 @@ int __devinit pvr_boot(struct bttv *btv) 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); @@ -2292,6 +2540,26 @@ int __devinit pvr_boot(struct bttv *btv) 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 result; + + result = request_firmware(&fw_entry, "hcwamc.rbf", dev); + if (result != 0) { + printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", + btv->nr); + return rc; + } + result = pvr_altera_load(btv, fw_entry->data, fw_entry->size); + release_firmware(fw_entry); + return result; +} +#endif /* ----------------------------------------------------------------------- */ /* some osprey specific stuff */ @@ -2540,7 +2808,9 @@ static void __devinit init_PXC200(struct 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 */ @@ -2560,6 +2830,7 @@ static void __devinit init_PXC200(struct 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 */ @@ -2571,16 +2842,36 @@ static void __devinit init_PXC200(struct * 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 */ /* @@ -2670,8 +2961,8 @@ int bus_in(struct bttv *btv, int bit) /* 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 */ @@ -2754,12 +3045,13 @@ static int tea5757_write(struct bttv *bt 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 } @@ -3051,6 +3343,38 @@ windvr_audio(struct bttv *btv, struct vi } } +/* + * sound control for AD-TVK503 + * Hiroshi Takekawa + */ +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 @@ -3091,6 +3415,34 @@ static void rv605_muxsel(struct bttv *bt 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 */ @@ -3122,12 +3474,12 @@ void __devinit bttv_check_chipset(void) 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, @@ -3144,7 +3496,7 @@ int __devinit bttv_handle_chipset(struct { unsigned char command; - if (!triton1 && !vsfx && -1 == latency) + if (!triton1 && !vsfx && UNSET == latency) return 0; if (bttv_verbose) { @@ -3152,7 +3504,7 @@ int __devinit bttv_handle_chipset(struct 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); } @@ -3170,7 +3522,7 @@ int __devinit bttv_handle_chipset(struct 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; } diff -puN drivers/media/video/bttv-driver.c~bttv-driver-update drivers/media/video/bttv-driver.c --- 25/drivers/media/video/bttv-driver.c~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttv-driver.c Mon Jul 28 16:23:01 2003 @@ -24,7 +24,6 @@ */ #include -#include #include #include #include @@ -35,10 +34,11 @@ #include #include +#include #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; @@ -46,12 +46,12 @@ unsigned int bttv_verbose = 1; 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; @@ -275,9 +275,29 @@ const struct bttv_tvnorm bttv_tvnorms[] .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 @@ -434,7 +454,7 @@ const struct bttv_format bttv_formats[] .flags = FORMAT_FLAGS_RAW, } }; -const int BTTV_FORMATS = (sizeof(bttv_formats)/sizeof(struct bttv_format)); +const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats); /* ----------------------------------------------------------------------- */ @@ -557,7 +577,7 @@ static const struct v4l2_queryctrl bttv_ .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 */ @@ -1002,7 +1022,7 @@ static int get_control(struct bttv *btv, 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; @@ -1159,7 +1179,7 @@ void bttv_field_count(struct bttv *btv) 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) @@ -1173,7 +1193,7 @@ format_by_palette(int 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) @@ -1195,6 +1215,7 @@ bttv_switch_overlay(struct bttv *btv, st 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); @@ -1204,8 +1225,12 @@ bttv_switch_overlay(struct bttv *btv, st 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; } @@ -1214,7 +1239,7 @@ bttv_switch_overlay(struct bttv *btv, st 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; @@ -1252,13 +1277,6 @@ static int bttv_prepare_buffer(struct bt 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; @@ -1334,7 +1352,7 @@ static const char *v4l1_ioctls[] = { "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) { @@ -1365,7 +1383,7 @@ int bttv_common_ioctls(struct bttv *btv, { 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; @@ -1397,38 +1415,39 @@ int bttv_common_ioctls(struct bttv *btv, 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; @@ -1462,9 +1481,9 @@ int bttv_common_ioctls(struct bttv *btv, 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); @@ -1483,11 +1502,13 @@ int bttv_common_ioctls(struct bttv *btv, 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: @@ -1499,7 +1520,7 @@ int bttv_common_ioctls(struct bttv *btv, 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) @@ -1527,7 +1548,7 @@ int bttv_common_ioctls(struct bttv *btv, case VIDIOC_ENUMINPUT: { struct v4l2_input *i = arg; - int n; + unsigned int n; n = i->index; if (n >= bttv_tvcards[btv->type].video_inputs) @@ -1564,9 +1585,9 @@ int bttv_common_ioctls(struct bttv *btv, } 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); @@ -1579,7 +1600,7 @@ int bttv_common_ioctls(struct bttv *btv, { 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; @@ -1587,8 +1608,8 @@ int bttv_common_ioctls(struct bttv *btv, 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; @@ -1599,12 +1620,15 @@ int bttv_common_ioctls(struct bttv *btv, 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); @@ -1614,7 +1638,7 @@ int bttv_common_ioctls(struct bttv *btv, { 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; @@ -1622,6 +1646,7 @@ int bttv_common_ioctls(struct bttv *btv, { 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) @@ -1676,7 +1701,7 @@ static int verify_window(const struct bt { enum v4l2_field field; int maxw, maxh; - + if (win->w.width < 48 || win->w.height < 32) return -EINVAL; if (win->clipcount > 2048) @@ -1705,15 +1730,6 @@ static int verify_window(const struct bt 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) @@ -1728,6 +1744,8 @@ static int setup_window(struct bttv_fh * 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; @@ -1735,33 +1753,50 @@ static int setup_window(struct bttv_fh * /* 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; @@ -1834,8 +1869,10 @@ static int bttv_g_fmt(struct bttv_fh *fh 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)); @@ -1843,7 +1880,7 @@ static int bttv_g_fmt(struct bttv_fh *fh 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; @@ -1858,14 +1895,11 @@ static int bttv_try_fmt(struct bttv_fh * { 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; @@ -1880,6 +1914,7 @@ static int bttv_try_fmt(struct bttv_fh * switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: + case V4L2_FIELD_ALTERNATE: maxh = maxh/2; break; case V4L2_FIELD_INTERLACED: @@ -1887,6 +1922,7 @@ static int bttv_try_fmt(struct bttv_fh * case V4L2_FIELD_SEQ_TB: if (fmt->flags & FORMAT_FLAGS_PLANAR) return -EINVAL; + break; default: return -EINVAL; } @@ -1901,25 +1937,19 @@ static int bttv_try_fmt(struct bttv_fh * 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; } @@ -1947,6 +1977,7 @@ static int bttv_s_fmt(struct bttv_fh *fh 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; @@ -1962,10 +1993,11 @@ static int bttv_s_fmt(struct bttv_fh *fh 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; @@ -1978,7 +2010,7 @@ static int bttv_do_ioctl(struct inode *i 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)) { @@ -2052,9 +2084,10 @@ static int bttv_do_ioctl(struct inode *i 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; @@ -2092,7 +2125,7 @@ static int bttv_do_ioctl(struct inode *i 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; @@ -2181,12 +2214,10 @@ static int bttv_do_ioctl(struct inode *i /* 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)) @@ -2210,7 +2241,7 @@ static int bttv_do_ioctl(struct inode *i 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); @@ -2290,6 +2321,56 @@ static int bttv_do_ioctl(struct inode *i 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: @@ -2326,7 +2407,8 @@ static int bttv_do_ioctl(struct inode *i { 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) { @@ -2347,7 +2429,7 @@ static int bttv_do_ioctl(struct inode *i 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) @@ -2604,8 +2686,8 @@ static ssize_t bttv_read(struct file *fi 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: @@ -2628,6 +2710,7 @@ static unsigned int bttv_poll(struct fil { 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)) @@ -2654,7 +2737,8 @@ static unsigned int bttv_poll(struct fil 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; } @@ -2674,11 +2758,11 @@ static unsigned int bttv_poll(struct fil 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); @@ -2707,6 +2791,7 @@ static int bttv_open(struct inode *inode 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, @@ -2720,6 +2805,8 @@ static int bttv_open(struct inode *inode 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; } @@ -2807,10 +2894,10 @@ struct video_device bttv_vbi_template = 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); @@ -2934,10 +3021,10 @@ static char *irq_name[] = { "FMTCHG", "V 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)) @@ -2950,21 +3037,131 @@ static void bttv_print_riscaddr(struct b printk(" main: %08Lx\n", (u64)btv->main.dma); printk(" vbi : o=%08Lx e=%08Lx\n", - btv->vcurr ? (u64)btv->vcurr->top.dma : 0, - btv->vcurr ? (u64)btv->vcurr->bottom.dma : 0); + btv->curr.vbi ? (u64)btv->curr.vbi->top.dma : 0, + btv->curr.vbi ? (u64)btv->curr.vbi->bottom.dma : 0); printk(" cap : o=%08Lx e=%08Lx\n", - btv->top ? (u64)btv->top->top.dma : 0, - btv->bottom ? (u64)btv->bottom->bottom.dma : 0); + btv->curr.top ? (u64)btv->curr.top->top.dma : 0, + btv->curr.bottom ? (u64)btv->curr.bottom->bottom.dma : 0); printk(" scr : o=%08Lx e=%08Lx\n", btv->screen ? (u64)btv->screen->top.dma : 0, btv->screen ? (u64)btv->screen->bottom.dma : 0); } +static int +bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set) +{ + struct bttv_buffer *item; + + memset(set,0,sizeof(*set)); + + /* vbi request ? */ + if (!list_empty(&btv->vcapture)) { + set->irqflags = 1; + set->vbi = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); + } + + /* capture request ? */ + if (!list_empty(&btv->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(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 == 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 == set->top && NULL == set->bottom) { + set->top = btv->screen; + set->bottom = btv->screen; + } + } else { + if (V4L2_FIELD_TOP == btv->screen->vb.field && + NULL == set->top) { + set->top = btv->screen; + } + if (V4L2_FIELD_BOTTOM == btv->screen->vb.field && + NULL == set->bottom) { + set->bottom = btv->screen; + } + } + } + + 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; + + do_gettimeofday(&ts); + + 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 != 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 != 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); + } + } +} + 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; + struct bttv_buffer_set old,new; + struct bttv_buffer *item; if (bttv_verbose) { printk(KERN_INFO "bttv%d: timeout: risc=%08x, ", @@ -2974,53 +3171,29 @@ static void bttv_irq_timeout(unsigned lo } 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); + 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 + 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); - } + /* wake up */ + bttv_irq_wakeup_set(btv, &old, &new, STATE_ERROR); /* 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); + 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)) { - 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); + 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++; @@ -3028,131 +3201,53 @@ static void bttv_irq_timeout(unsigned lo } static void -bttv_irq_switch_fields(struct bttv *btv) +bttv_irq_wakeup_top(struct bttv *btv) { - 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 *wakeup = btv->curr.top; - 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; + if (NULL == wakeup) + return; - /* 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); - } - - /* 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; + spin_lock(&btv->s_lock); + btv->curr.topirq = 0; + btv->curr.top = NULL; + bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); - /* 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 (NULL == btv->bottom && - V4L2_FIELD_BOTTOM == capture->vb.field) { - btv->bottom = capture; - list_del(&capture->vb.queue); - } - } - } - } + 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); +} - /* 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; - } - } else { - if (V4L2_FIELD_TOP == btv->screen->vb.field && - NULL == btv->top) { - btv->top = btv->screen; - } - if (V4L2_FIELD_BOTTOM == btv->screen->vb.field && - NULL == btv->bottom) { - btv->bottom = btv->screen; - } - } - } +static void +bttv_irq_switch_fields(struct bttv *btv) +{ + struct bttv_buffer_set new; + struct bttv_buffer_set old; + dma_addr_t rc; - 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); + 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) - 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); - } - } 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 != 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 != 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); - } + 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); } @@ -3178,7 +3273,7 @@ static irqreturn_t bttv_irq(int irq, voi /* 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, @@ -3201,7 +3296,10 @@ static irqreturn_t bttv_irq(int irq, voi 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); @@ -3308,7 +3406,8 @@ static int __devinit bttv_probe(struct p 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)); @@ -3485,7 +3584,7 @@ static void __devexit bttv_remove(struct 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); @@ -3519,6 +3618,7 @@ static struct pci_driver bttv_pci_driver static int bttv_init_module(void) { + int rc; bttv_num = 0; printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", @@ -3536,7 +3636,13 @@ static int bttv_init_module(void) 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) diff -puN drivers/media/video/bttv.h~bttv-driver-update drivers/media/video/bttv.h --- 25/drivers/media/video/bttv.h~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttv.h Mon Jul 28 16:23:01 2003 @@ -90,6 +90,7 @@ #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 @@ -108,6 +109,12 @@ #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 @@ -123,6 +130,7 @@ #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 @@ -145,36 +153,37 @@ struct bttv; 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); diff -puN drivers/media/video/bttv-if.c~bttv-driver-update drivers/media/video/bttv-if.c --- 25/drivers/media/video/bttv-if.c~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttv-if.c Mon Jul 28 16:23:01 2003 @@ -25,7 +25,6 @@ */ -#include #include #include @@ -198,6 +197,9 @@ static int attach_inform(struct i2c_clie 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", @@ -231,9 +233,9 @@ static struct i2c_algo_bit_data bttv_i2c 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, }; @@ -314,6 +316,7 @@ int __devinit init_bttv_i2c(struct bttv 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); diff -puN drivers/media/video/bttvp.h~bttv-driver-update drivers/media/video/bttvp.h --- 25/drivers/media/video/bttvp.h~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttvp.h Mon Jul 28 16:23:01 2003 @@ -24,7 +24,8 @@ #ifndef _BTTVP_H_ #define _BTTVP_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,4) +#include +#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,11) #include #include @@ -40,6 +41,7 @@ #include "bt848.h" #include "bttv.h" +#include "btcx-risc.h" #ifdef __KERNEL__ @@ -66,8 +68,7 @@ /* ---------------------------------------------------------- */ -struct bttv_tvnorm -{ +struct bttv_tvnorm { int v4l2_id; char *name; u32 Fsc; @@ -78,10 +79,11 @@ struct bttv_tvnorm 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; @@ -94,21 +96,14 @@ struct bttv_format { 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 { @@ -121,16 +116,25 @@ 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 { @@ -140,7 +144,6 @@ struct bttv_fh { /* video capture */ struct videobuf_queue cap; - /* struct bttv_buffer buf; */ const struct bttv_format *fmt; int width; int height; @@ -157,28 +160,19 @@ struct bttv_fh { /* ---------------------------------------------------------- */ /* 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); @@ -191,13 +185,13 @@ void bttv_apply_geo(struct bttv *btv, st /* 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 */ @@ -209,7 +203,8 @@ int bttv_overlay_risc(struct bttv *btv, /* ---------------------------------------------------------- */ /* 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; @@ -235,8 +230,8 @@ extern void bttv_field_count(struct bttv #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 @@ -263,8 +258,9 @@ struct bttv { 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; @@ -291,12 +287,12 @@ struct bttv { 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; @@ -325,21 +321,19 @@ struct bttv { /* 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; }; diff -puN drivers/media/video/bttv-risc.c~bttv-driver-update drivers/media/video/bttv-risc.c --- 25/drivers/media/video/bttv-risc.c~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttv-risc.c Mon Jul 28 16:23:01 2003 @@ -23,7 +23,6 @@ */ -#include #include #include #include @@ -35,58 +34,24 @@ #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 */ @@ -130,6 +95,7 @@ bttv_risc_packed(struct bttv *btv, struc } 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; @@ -137,24 +103,27 @@ bttv_risc_packed(struct bttv *btv, struc } 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 */ @@ -231,138 +200,13 @@ bttv_risc_planar(struct bttv *btv, struc 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; @@ -375,7 +219,7 @@ bttv_risc_overlay(struct bttv *btv, stru 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 */ @@ -397,8 +241,8 @@ bttv_risc_overlay(struct bttv *btv, stru /* 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) { @@ -432,7 +276,6 @@ bttv_risc_overlay(struct bttv *btv, stru /* save pointer to jmp instruction address */ risc->jmp = rp; - kfree(skips); return 0; } @@ -476,6 +319,7 @@ bttv_calc_geo(struct bttv *btv, struct b 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); @@ -506,6 +350,8 @@ bttv_apply_geo(struct bttv *btv, struct 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); } /* ---------------------------------------------------------- */ @@ -518,9 +364,9 @@ bttv_set_dma(struct bttv *btv, int overr 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 */ @@ -530,14 +376,16 @@ bttv_set_dma(struct bttv *btv, int overr d2printk(KERN_DEBUG "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", btv->nr,capctl,irqflags, - btv->vcurr ? (u64)btv->vcurr->top.dma : 0, - btv->top ? (u64)btv->top->top.dma : 0, - btv->vcurr ? (u64)btv->vcurr->bottom.dma : 0, - btv->bottom ? (u64)btv->bottom->bottom.dma : 0); + btv->curr.vbi ? (u64)btv->curr.vbi->top.dma : 0, + btv->curr.top ? (u64)btv->curr.top->top.dma : 0, + btv->curr.vbi ? (u64)btv->curr.vbi->bottom.dma : 0, + btv->curr.bottom ? (u64)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); @@ -565,7 +413,7 @@ bttv_risc_init_main(struct bttv *btv) { 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,(u64)btv->main.dma); @@ -600,7 +448,7 @@ bttv_risc_init_main(struct bttv *btv) } 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; @@ -614,8 +462,11 @@ bttv_risc_hook(struct bttv *btv, int slo d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n", btv->nr,risc,slot,(u64)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); @@ -631,43 +482,68 @@ bttv_dma_free(struct bttv *btv, struct b 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) -{ - 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), +bttv_buffer_set_activate(struct bttv *btv, + struct bttv_buffer_set *set) +{ + /* 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); @@ -734,12 +610,12 @@ bttv_buffer_risc(struct bttv *btv, struc /* 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) { @@ -781,6 +657,29 @@ bttv_buffer_risc(struct bttv *btv, struc 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(); } @@ -826,7 +725,7 @@ bttv_overlay_risc(struct bttv *btv, /* 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); diff -puN drivers/media/video/bttv-vbi.c~bttv-driver-update drivers/media/video/bttv-vbi.c --- 25/drivers/media/video/bttv-vbi.c~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/bttv-vbi.c Mon Jul 28 16:23:01 2003 @@ -19,7 +19,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include @@ -63,7 +62,7 @@ vbi_buffer_risc(struct bttv *btv, struct } 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; @@ -155,11 +154,53 @@ void bttv_vbi_setlines(struct bttv_fh *f } } -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; diff -puN drivers/media/video/Makefile~bttv-driver-update drivers/media/video/Makefile --- 25/drivers/media/video/Makefile~bttv-driver-update Mon Jul 28 16:23:01 2003 +++ 25-akpm/drivers/media/video/Makefile Mon Jul 28 16:23:01 2003 @@ -38,4 +38,4 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o obj-$(CONFIG_VIDEO_BUF) += video-buf.o - +obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o _