diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
commit | 86464aed71025541805e7b1515541aee89879e33 (patch) | |
tree | e01a457a4912a8553bc65524aa3125d51f29f810 /drivers/char/bttv.c | |
parent | 88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff) |
Merge with Linux 2.2.1.
Diffstat (limited to 'drivers/char/bttv.c')
-rw-r--r-- | drivers/char/bttv.c | 1295 |
1 files changed, 986 insertions, 309 deletions
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index de2d25b0e..90c117467 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -17,66 +17,87 @@ 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. - - Modified to put the RISC code writer in the kernel and to fit a - common (and I hope safe) kernel interface. When we have an X extension - all will now be really sweet. - - TODO: - - * move norm from tuner to channel struct!? - composite source from a satellite tuner can deliver different norms - depending on tuned channel - * mmap VBI data? - * fix RAW Composite grabbing for NTSC - * fix VBI reading double frames when grabbing is active - * allow for different VDELAYs - * extra modules for tda9850, tda8425, any volunteers??? */ #include <linux/module.h> +#include <linux/version.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/malloc.h> -#include <linux/vmalloc.h> #include <linux/mm.h> +#if LINUX_VERSION_CODE >= 0x020100 +#include <linux/poll.h> +#endif #include <linux/pci.h> #include <linux/signal.h> #include <asm/io.h> +#include <linux/ioport.h> #include <asm/pgtable.h> #include <asm/page.h> #include <linux/sched.h> #include <asm/segment.h> #include <linux/types.h> #include <linux/wrapper.h> - -#include <linux/videodev.h> +#include <linux/interrupt.h> #include <linux/version.h> + +#if LINUX_VERSION_CODE >= 0x020100 #include <asm/uaccess.h> +#include <linux/vmalloc.h> +#else +#include <linux/bios32.h> +#define mdelay(x) udelay((x)*1000) +#define signal_pending(current) (current->signal & ~current->blocked) +#define sigfillset(set) + +static inline int time_before(unsigned long a, unsigned long b) +{ + return((long)((a) - (b)) < 0L); +} +static inline unsigned long +copy_to_user(void *to, const void *from, unsigned long n) +{ + memcpy_tofs(to,from,n); + return 0; +} + +static inline unsigned long +copy_from_user(void *to, const void *from, unsigned long n) +{ + memcpy_fromfs(to,from,n); + return 0; +} +#define ioremap vremap +#define iounmap vfree +#endif + +#include <linux/videodev.h> #include <linux/i2c.h> #include "bttv.h" #include "tuner.h" -#define DEBUG(x) /* Debug driver */ +#define DEBUG(x) /* Debug driver */ #define IDEBUG(x) /* Debug interrupt handler */ +#if LINUX_VERSION_CODE >= 0x020117 MODULE_PARM(vidmem,"i"); MODULE_PARM(triton1,"i"); MODULE_PARM(remap,"1-4i"); MODULE_PARM(radio,"1-4i"); MODULE_PARM(card,"1-4i"); MODULE_PARM(pll,"1-4i"); - -static int find_vga(void); -static void bt848_set_risc_jmps(struct bttv *btv); +#endif /* Anybody who uses more than four? */ #define BTTV_MAX 4 +static int find_vga(void); +static void bt848_set_risc_jmps(struct bttv *btv); + static unsigned int vidmem=0; /* manually set video mem address */ static int triton1=0; #ifndef USE_PLL @@ -103,9 +124,11 @@ static struct bttv bttvs[BTTV_MAX]; { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); } #define I2C_GET() (btread(BT848_I2C)&1) -#define EEPROM_WRITE_DELAY 20000 +#define EEPROM_WRITE_DELAY 20000 #define BURSTOFFSET 76 + + /*******************************/ /* Memory management functions */ /*******************************/ @@ -190,6 +213,8 @@ static void rvfree(void * mem, unsigned long size) } } + + /* * Create the giant waste of buffer space we need for now * until we get DMA to user space sorted out (probably 2.3.x) @@ -387,7 +412,9 @@ static struct i2c_bus bttv_i2c_bus_template = I2C_BUSID_BT848, NULL, +#if LINUX_VERSION_CODE >= 0x020100 SPIN_LOCK_UNLOCKED, +#endif attach_inform, detach_inform, @@ -399,6 +426,70 @@ static struct i2c_bus bttv_i2c_bus_template = }; /* ----------------------------------------------------------------------- */ +/* some hauppauge specific stuff */ + +static unsigned char eeprom_data[256]; +static struct HAUPPAUGE_TUNER +{ + int id; + char *name; +} +hauppauge_tuner[] = +{ + { TUNER_ABSENT, "" }, + { TUNER_ABSENT, "External" }, + { TUNER_ABSENT, "Unspecified" }, + { TUNER_ABSENT, "Philips FI1216" }, + { TUNER_ABSENT, "Philips FI1216MF" }, + { TUNER_PHILIPS_NTSC, "Philips FI1236" }, + { TUNER_ABSENT, "Philips FI1246" }, + { TUNER_ABSENT, "Philips FI1256" }, + { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" }, + { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" }, + { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" }, + { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" }, + { TUNER_ABSENT, "Philips FI1256 MK2" }, + { TUNER_ABSENT, "Temic 4032FY5" }, + { TUNER_TEMIC_PAL, "Temic 4002FH5" }, + { TUNER_TEMIC_PAL_I, "Temic 4062FY5" }, + { TUNER_ABSENT, "Philips FR1216 MK2" }, + { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" }, + { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" }, + { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" }, + { TUNER_ABSENT, "Philips FR1256 MK2" }, + { TUNER_PHILIPS_PAL, "Philips FM1216" }, + { TUNER_ABSENT, "Philips FM1216MF" }, + { TUNER_PHILIPS_NTSC, "Philips FM1236" }, +}; + +static void +hauppauge_eeprom(struct i2c_bus *bus) +{ + struct bttv *btv = (struct bttv*)bus->data; + + readee(bus, eeprom_data); + if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) + { + btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id; + printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr, + hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type); + } +} + +static void +hauppauge_msp_reset(struct bttv *btv) +{ + /* Reset the MSP on some Hauppauge cards */ + /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */ + /* Can this hurt cards without one? What about Miros with MSP? */ + btaor(32, ~32, BT848_GPIO_OUT_EN); + btaor(0, ~32, BT848_GPIO_DATA); + udelay(2500); + btaor(32, ~32, BT848_GPIO_DATA); + /* btaor(0, ~32, BT848_GPIO_OUT_EN); */ +} + +/* ----------------------------------------------------------------------- */ struct tvcard @@ -436,25 +527,19 @@ static struct tvcard tvcards[] = {0, 0xc00, 0x800, 0x400, 0xc00, 0}}, /* TurboTV */ { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}}, - /* Newer Hauppauge (bt878) */ + /* Newer Hauppauge (bt878) */ { 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}}, - /* MIRO PCTV pro */ - { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}}, + /* MIRO PCTV pro */ + { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}}, /* ADS Technologies Channel Surfer TV (and maybe TV+FM) */ - { - 3, 4, 0, 2, 0x0F, - { 0x02, 0x03, 0x01, 0x01}, - { 0x0D, 0x0E, 0x0B, 0x07, 0x00, 0x00}, - 0x00 - }, + { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0}, + /* AVerMedia TVCapture 98 */ + { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0}, + /* Aimslab VHX */ + { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}}, }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) - -/* - * Tuner, Radio, internal, external and mute - */ - static void audio(struct bttv *btv, int mode) { btaor(tvcards[btv->type].gpiomask, ~tvcards[btv->type].gpiomask, @@ -542,16 +627,16 @@ static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout) fout*=12; fi=fout/fin; - fout=(fout-fin*fi)*256; + fout=(fout%fin)*256; fh=fout/fin; - fout=(fout-fin*fh)*256; + fout=(fout%fin)*256; fl=fout/fin; /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/ - btwrite(fl,BT848_PLL_F_LO); - btwrite(fh,BT848_PLL_F_HI); - btwrite(fi|BT848_PLL_X,BT848_PLL_XCI); + btwrite(fl, BT848_PLL_F_LO); + btwrite(fh, BT848_PLL_F_HI); + btwrite(fi|BT848_PLL_X, BT848_PLL_XCI); } static int set_pll(struct bttv *btv) @@ -593,7 +678,7 @@ static int set_pll(struct bttv *btv) } while(time_before(jiffies,tv)); - for (i=0; i<100; i++) + for (i=0; i<10; i++) { if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK)) btwrite(0,BT848_DSTATUS); @@ -614,13 +699,14 @@ static int set_pll(struct bttv *btv) static void bt848_muxsel(struct bttv *btv, unsigned int input) { btaor(tvcards[btv->type].gpiomask2,~tvcards[btv->type].gpiomask2, - BT848_GPIO_OUT_EN); + BT848_GPIO_OUT_EN); /* This seems to get rid of some synchronization problems */ btand(~(3<<5), BT848_IFORM); mdelay(10); - - input %= tvcards[btv->type].video_inputs; + + + input %= tvcards[btv->type].video_inputs; if (input==tvcards[btv->type].svhs) { btor(BT848_CONTROL_COMP, BT848_E_CONTROL); @@ -638,13 +724,83 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input) ~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA); } +/* + * Set the registers for the size we have specified. Don't bother + * trying to understand this without the BT848 manual in front of + * you [AC]. + * + * PS: The manual is free for download in .pdf format from + * www.brooktree.com - nicely done those folks. + */ + +struct tvnorm +{ + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ + u16 totalwidth; + u8 adelay, bdelay, iform; + u32 scaledtwidth; + u16 hdelayx1, hactivex1; + u16 vdelay; + u8 vbipack; +}; -#define VBIBUF_SIZE 65536 - -/* Maximum sample number per VBI line is 2044, NTSC delivers 1600 - Note that we write 2048-aligned to keep alignment to memory pages - VBI_RISC is written so that it applies to either 2044 or 1600 +static struct tvnorm tvnorms[] = { + /* PAL-BDGHI */ + /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ + /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ +#ifdef VIDEODAT + { 35468950, + 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + 1135, 186, 924, 0x20, 255}, +#else + { 35468950, + 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + 1135, 186, 924, 0x20, 255}, +#endif +/* + { 35468950, + 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), + 944, 186, 922, 0x20, 255}, */ + /* NTSC */ + { 28636363, + 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), + 910, 128, 910, 0x1a, 144}, +/* + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), + 780, 122, 754, 0x1a, 144}, +*/ +#if 0 + /* SECAM EAST */ + { 35468950, + 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), + 944, 186, 922, 0x20, 255}, +#else + /* SECAM L */ + { 35468950, + 924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), + 1135, 186, 922, 0x20, 255}, +#endif + /* PAL-NC */ + { 28636363, + 640, 576, 910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), + 780, 130, 734, 0x1a, 144}, + /* PAL-M */ + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), + 780, 135, 754, 0x1a, 144}, + /* PAL-N */ + { 35468950, + 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1), + 944, 186, 922, 0x20, 144}, + /* NTSC-Japan */ + { 28636363, + 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), + 780, 135, 754, 0x16, 144}, +}; +#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) #define VBI_SPL 2044 /* RISC command to write one VBI data line */ @@ -660,7 +816,7 @@ static void make_vbitab(struct bttv *btv) DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even)); DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po)); DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe)); - + *(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0; for (i=0; i<16; i++) { @@ -696,12 +852,14 @@ int palette2fmt[] = { BT848_COLOR_FMT_RGB15, BT848_COLOR_FMT_YUY2, BT848_COLOR_FMT_BtYUV, - 0, - 0, - 0, + -1, + -1, + -1, BT848_COLOR_FMT_RAW, BT848_COLOR_FMT_YCrCb422, BT848_COLOR_FMT_YCrCb411, + BT848_COLOR_FMT_YCrCb422, + BT848_COLOR_FMT_YCrCb411, }; #define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int)) @@ -737,11 +895,120 @@ static int make_rawrisctab(struct bttv *btv, unsigned int *ro, } -static int make_vrisctab(struct bttv *btv, unsigned int *ro, +static int make_prisctab(struct bttv *btv, unsigned int *ro, unsigned int *re, unsigned int *vbuf, unsigned short width, unsigned short height, unsigned short fmt) { + unsigned long line, lmask; + unsigned long bl, blcr, blcb, rcmd; + unsigned long todo; + unsigned int **rp; + int inter; + unsigned long cbadr, cradr; + unsigned long vadr=(unsigned long) vbuf; + int shift, csize; + + + switch(fmt) + { + case VIDEO_PALETTE_YUV422P: + csize=(width*height)>>1; + shift=1; + lmask=0; + break; + + case VIDEO_PALETTE_YUV411P: + csize=(width*height)>>2; + shift=2; + lmask=0; + break; + + case VIDEO_PALETTE_YUV420P: + csize=(width*height)>>2; + shift=1; + lmask=1; + break; + + case VIDEO_PALETTE_YUV410P: + csize=(width*height)>>4; + shift=2; + lmask=3; + break; + + default: + return -1; + } + cbadr=vadr+(width*height); + cradr=cbadr+csize; + inter = (height>btv->win.cropheight/2) ? 1 : 0; + + *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(ro++)=0; + *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(re++)=0; + + for (line=0; line < (height<<(1^inter)); line++) + { + if(line==height) + { + vadr+=csize<<1; + cbadr=vadr+(width*height); + cradr=cbadr+csize; + } + if (inter) + rp= (line&1) ? &re : &ro; + else + rp= (line>=height) ? &re : &ro; + + + if(line&lmask) + rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL; + else + rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL; + + todo=width; + while(todo) + { + bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); + blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<<shift; + blcb=(PAGE_SIZE-((PAGE_SIZE-1)&cbadr))<<shift; + bl=(blcr<bl) ? blcr : bl; + bl=(blcb<bl) ? blcb : bl; + bl=(bl>todo) ? todo : bl; + blcr=bl>>shift; + blcb=blcr; + /* bl now containts the longest row that can be written */ + todo-=bl; + if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */ + + *((*rp)++)=rcmd|bl; + *((*rp)++)=blcb|(blcr<<16); + *((*rp)++)=kvirt_to_bus(vadr); + vadr+=bl; + if((rcmd&(15<<28))==BT848_RISC_WRITE123) + { + *((*rp)++)=kvirt_to_bus(cbadr); + cbadr+=blcb; + *((*rp)++)=kvirt_to_bus(cradr); + cradr+=blcr; + } + + rcmd&=~BT848_RISC_SOL; /* only the first has SOL */ + } + } + + *(ro++)=BT848_RISC_JUMP; + *(ro++)=btv->bus_vbi_even; + *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16); + *(re++)=btv->bus_vbi_odd; + + return 0; +} + +static int make_vrisctab(struct bttv *btv, unsigned int *ro, + unsigned int *re, + unsigned int *vbuf, unsigned short width, + unsigned short height, unsigned short palette) +{ unsigned long line; unsigned long bpl; /* bytes per line */ unsigned long bl; @@ -750,11 +1017,14 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro, int inter; unsigned long vadr=(unsigned long) vbuf; - if (btv->gfmt==BT848_COLOR_FMT_RAW) + if (palette==VIDEO_PALETTE_RAW) return make_rawrisctab(btv, ro, re, vbuf); + if (palette>=VIDEO_PALETTE_PLANAR) + return make_prisctab(btv, ro, re, vbuf, width, height, palette); + inter = (height>btv->win.cropheight/2) ? 1 : 0; - bpl=width*fmtbppx2[fmt&0xf]/2; + bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0; *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0; @@ -764,7 +1034,7 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro, if (inter) rp= (line&1) ? &re : &ro; else - rp= (line>height) ? &re : &ro; + rp= (line>=height) ? &re : &ro; bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); if (bpl<=bl) @@ -802,16 +1072,62 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro, return 0; } +static unsigned char lmaskt[8] = +{ 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; +static unsigned char rmaskt[8] = +{ 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h) { - int i, j; + unsigned char lmask, rmask, *p; + int W, l, r; + int i; /* bitmap is fixed width, 128 bytes (1024 pixels represented) */ - if (x < 0 || y < 0 || w < 0 || h < 0) /* catch bad clips */ + if (x<0) + { + w+=x; + x=0; + } + if (y<0) + { + h+=y; + y=0; + } + if (w < 0 || h < 0) /* catch bad clips */ return; /* out of range data should just fall through */ - for (i = y; i < y + h && i < 625; i++) - for (j = x; j < x + w && j < 1024; j++) - clipmap[(i<<7)+(j>>3)] |= (1<<(j&7)); + if (y+h>=625) + h=625-y; + if (x+w>=1024) + w=1024-x; + + l=x>>3; + r=(x+w)>>3; + W=r-l-1; + lmask=lmaskt[x&7]; + rmask=rmaskt[(x+w)&7]; + p=clipmap+128*y+l; + + if (W>0) + { + for (i=0; i<h; i++, p+=128) + { + *p|=lmask; + memset(p+1, 0xff, W); + p[W+1]|=rmask; + } + } else if (!W) { + for (i=0; i<h; i++, p+=128) + { + p[0]|=lmask; + p[1]|=rmask; + } + } else { + for (i=0; i<h; i++, p+=128) + p[0]|=lmask&rmask; + } + + } static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) @@ -903,73 +1219,6 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) *(re++)=btv->bus_vbi_odd; } - -/* - * Set the registers for the size we have specified. Don't bother - * trying to understand this without the BT848 manual in front of - * you [AC]. - * - * PS: The manual is free for download in .pdf format from - * www.brooktree.com - nicely done those folks. - */ - -struct tvnorm -{ - u32 Fsc; - u16 swidth, sheight; /* scaled standard width, height */ - u16 totalwidth; - u8 adelay, bdelay, iform; - u32 scaledtwidth; - u16 hdelayx1, hactivex1; - u16 vdelay; - u8 vbipack; -}; - -static struct tvnorm tvnorms[] = { - /* PAL-BDGHI */ - /* max pal/secam is actually 922, but 924 is divisible by 4 and 3! */ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ - { 35468950, - 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), - 1135, 178, 924, 0x20, 255}, -/* - { 35468950, - 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1), - 944, 178, 922, 0x20, 255}, -*/ - /* NTSC */ - { 28636363, - 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), - 910, 128, 754, 0x1a, 144}, -/* - { 28636363, - 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0), - 780, 122, 754, 0x1a, 144}, -*/ - /* SECAM - phase means nothing in SECAM, bdelay is useless */ - { 35468950, - 924, 576,1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1), - 1135, 178, 924, 0x20, 255}, - /* PAL-M */ - { 28636363, - 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0), - 780, 122, 754, 0x1a, 144}, - /* PAL-N */ - { 35468950, - 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1), - 944, 178, 922, 0x20, 255}, - /* PAL-NC */ - { 35468950, - 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0), - 944, 178, 922, 0x20, 255}, - /* NTSC-Japan */ - { 28636363, - 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0), - 780, 122, 754, 0x1a, 144}, -}; -#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm)) - - /* set geometry for even/odd frames just if you are wondering: handling of even and odd frames will be separated, e.g. for grabbing @@ -1030,10 +1279,11 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) btwrite(tvn->adelay, BT848_ADELAY); btwrite(tvn->bdelay, BT848_BDELAY); btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM); - btwrite(1, BT848_VBI_PACK_DEL); btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE); - - set_pll(btv); + btwrite(1, BT848_VBI_PACK_DEL); + + btv->pll.pll_ofreq = tvn->Fsc; + set_pll(btv); btwrite(fmt, BT848_COLOR_FMT); hactive=width; @@ -1064,7 +1314,6 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt) hdelay, vdelay, crop); bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive, hdelay, vdelay, crop); - } @@ -1104,35 +1353,34 @@ static void set_freq(struct bttv *btv, unsigned short freq) { int fixme = freq; /* XXX */ - if (btv->radio) - { - if (btv->have_tuner) + /* mute */ + if (btv->have_msp3400) + i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400, + MSP_SWITCH_MUTE,0); + + /* switch channel */ + if (btv->have_tuner) { + if (btv->radio) { i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_RADIOFREQ,&fixme); - - if (btv->have_msp3400) { - i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400, - MSP_SET_RADIO,0); - i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400, - MSP_NEWCHANNEL,0); - } - } - else - { - if (btv->have_tuner) + } else { i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ,&fixme); + } + } - if (btv->have_msp3400) { + if (btv->have_msp3400) { + if (btv->radio) { + i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400, + MSP_SET_RADIO,0); + } else { i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400, MSP_SET_TVNORM,&(btv->win.norm)); i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400, MSP_NEWCHANNEL,0); - } - } - + } + } } - /* * Grab into virtual memory. @@ -1171,12 +1419,12 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) */ if (mp->format >= PALETTEFMT_MAX) return -EINVAL; - if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2 - > BTTV_MAX_FBUF) + if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2 + > BTTV_MAX_FBUF) return -EINVAL; - if (!palette2fmt[mp->format]) + if(-1 == palette2fmt[mp->format]) return -EINVAL; - + /* * FIXME: Check the format of the grab here. This is probably * also less restrictive than the normal overlay grabs. Stuff @@ -1192,7 +1440,7 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) return -EAGAIN;*/ ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0); re=ro+2048; - make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, palette2fmt[mp->format]); + make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); /* bt848_set_risc_jmps(btv); */ btv->frame_stat[mp->frame] = GBUFFER_GRABBING; if (btv->grabbing) { @@ -1210,8 +1458,13 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) btv->gre=virt_to_bus(re); btv->grf=mp->frame; } - if (!(btv->grabbing++)) + if (!(btv->grabbing++)) { + if(mp->format>=VIDEO_PALETTE_COMPONENT) { + btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI); + btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI); + } btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ; + } btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); /* interruptible_sleep_on(&btv->capq); */ @@ -1227,7 +1480,7 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in { struct bttv *btv= (struct bttv *)v; int q,todo; - + /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */ todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { @@ -1275,36 +1528,27 @@ static int bttv_open(struct video_device *dev, int flags) struct bttv *btv = (struct bttv *)dev; int users, i; - switch (flags) - { - case 0: - if (btv->user) - return -EBUSY; - btv->user++; - audio(btv, AUDIO_UNMUTE); - for (i=users=0; i<bttv_num; i++) - users+=bttvs[i].user; - if (users==1) - find_vga(); - btv->fbuffer=NULL; - if (!btv->fbuffer) - btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF); - if (!btv->fbuffer) - { - btv->user--; - return -EINVAL; - } - btv->grabbing = 0; - btv->grab = 0; - btv->lastgrab = 0; - for (i = 0; i < MAX_GBUFFERS; i++) - btv->frame_stat[i] = GBUFFER_UNUSED; - break; - case 1: - break; - } - MOD_INC_USE_COUNT; - return 0; + if (btv->user) + return -EBUSY; + audio(btv, AUDIO_UNMUTE); + for (i=users=0; i<bttv_num; i++) + users+=bttvs[i].user; + if (users==1) + find_vga(); + btv->fbuffer=NULL; + if (!btv->fbuffer) + btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF); + if (!btv->fbuffer) + return -EINVAL; + btv->grabbing = 0; + btv->grab = 0; + btv->lastgrab = 0; + for (i = 0; i < MAX_GBUFFERS; i++) + btv->frame_stat[i] = GBUFFER_UNUSED; + + btv->user++; + MOD_INC_USE_COUNT; + return 0; } static void bttv_close(struct video_device *dev) @@ -1393,8 +1637,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) VID_TYPE_SCALES; b.channels = tvcards[btv->type].video_inputs; b.audios = tvcards[btv->type].audio_inputs; - b.maxwidth = 768; - b.maxheight = 576; + b.maxwidth = tvnorms[btv->win.norm].swidth; + b.maxheight = tvnorms[btv->win.norm].sheight; b.minwidth = 32; b.minheight = 32; if(copy_to_user(arg,&b,sizeof(b))) @@ -1420,7 +1664,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.tuners=1; } else if(v.channel==tvcards[btv->type].svhs) - strcpy(v.name,"SVHS"); + strcpy(v.name,"S-Video"); else sprintf(v.name,"Composite%d",v.channel); @@ -1437,14 +1681,14 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if(copy_from_user(&v, arg,sizeof(v))) return -EFAULT; - if (v.channel>=tvcards[btv->type].video_inputs) + if (v.channel>tvcards[btv->type].video_inputs) return -EINVAL; bt848_muxsel(btv, v.channel); if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC &&v.norm!=VIDEO_MODE_SECAM) return -EOPNOTSUPP; btv->win.norm = v.norm; - make_vbitab(btv); + make_vbitab(btv); bt848_set_winsize(btv); btv->channel=v.channel; return 0; @@ -1460,6 +1704,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.rangelow=0; v.rangehigh=0xFFFFFFFF; v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; + if (btv->audio_chip == TDA9840) { + v.flags |= VIDEO_AUDIO_VOLUME; + v.mode = VIDEO_SOUND_MONO|VIDEO_SOUND_STEREO; + v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2; + } + if (btv->audio_chip == TDA9850) { + unsigned char ALR1; + ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1); + if (ALR1 & 32) + v.flags |= VIDEO_TUNER_STEREO_ON; + } v.mode = btv->win.norm; v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; if(copy_to_user(arg,&v,sizeof(v))) @@ -1472,7 +1727,6 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) struct video_tuner v; if(copy_from_user(&v, arg, sizeof(v))) return -EFAULT; - /* Only one channel has a tuner */ if(v.tuner!=tvcards[btv->type].tuner) return -EINVAL; @@ -1536,13 +1790,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if(copy_from_user(&vw,arg,sizeof(vw))) return -EFAULT; - if(vw.flags || vw.width < 16 || vw.height < 16) { - bt848_cap(btv,0); + if(vw.flags || vw.width < 16 || vw.height < 16) + { + bt848_cap(btv,0); return -EINVAL; - } - if (btv->win.bpp < 4) { /* adjust and align writes */ + } + if (btv->win.bpp < 4) + { /* 32-bit align start and adjust width */ + int i = vw.x; vw.x = (vw.x + 3) & ~3; - vw.width = (vw.width - 3) & ~3; + i = vw.x - i; + vw.width -= i; } btv->win.x=vw.x; btv->win.y=vw.y; @@ -1584,7 +1842,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) make_clip_tab(btv, vcp, vw.clipcount); if (vw.clipcount != 0) vfree(vcp); - if(on && btv->win.vidadr != 0) + if(on && btv->win.vidadr!=0) bt848_cap(btv,1); return 0; } @@ -1638,7 +1896,11 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) case VIDIOCSFBUF: { struct video_buffer v; +#if LINUX_VERSION_CODE >= 0x020100 if(!capable(CAP_SYS_ADMIN)) +#else + if(!suser()) +#endif return -EPERM; if(copy_from_user(&v, arg,sizeof(v))) return -EFAULT; @@ -1646,7 +1908,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.depth!=24 && v.depth!=32 && v.width > 16 && v.height > 16 && v.bytesperline > 16) return -EINVAL; - btv->win.vidadr=(unsigned long)v.base; + if (v.base) + { + if ((unsigned long)v.base&1) + btv->win.vidadr=(unsigned long)(PAGE_OFFSET|uvirt_to_bus((unsigned long)v.base)); + else + btv->win.vidadr=(unsigned long)v.base; + } btv->win.sheight=v.height; btv->win.swidth=v.width; btv->win.bpp=((v.depth+7)&0x38)/8; @@ -1687,6 +1955,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE); v.flags|=VIDEO_AUDIO_MUTABLE; strcpy(v.name,"TV"); + if (btv->audio_chip == TDA9850) { + unsigned char ALR1; + ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1); + v.mode = VIDEO_SOUND_MONO; + v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0; + v.mode |= (ALR1 & 64) ? VIDEO_SOUND_LANG1:0; + } if (btv->have_msp3400) { v.flags|=VIDEO_AUDIO_VOLUME | @@ -1719,13 +1994,21 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) audio(btv, AUDIO_MUTE); /* One audio source per tuner */ /* if(v.audio!=0) */ - /* Nope... I have three on my ADSTech TV card. The*/ - /* ADSTech TV+FM prolly has 4 <rriggs@tesser.com> */ - if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs) + /* ADSTech TV card has more than one */ + if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs) return -EINVAL; bt848_muxsel(btv,v.audio); if(!(v.flags&VIDEO_AUDIO_MUTE)) audio(btv, AUDIO_UNMUTE); + if (btv->audio_chip == TDA9850) { + unsigned char con3 = 0; + if (v.mode & VIDEO_SOUND_LANG1) + con3 = 0x80; /* sap */ + if (v.mode & VIDEO_SOUND_STEREO) + con3 = 0x40; /* stereo */ + I2CWrite(&(btv->i2c), I2C_TDA9850, + TDA9850_CON3, con3, 1); + } if (btv->have_msp3400) { i2c_control_device(&(btv->i2c), @@ -1748,13 +2031,18 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) case VIDIOCSYNC: if(copy_from_user((void *)&i,arg,sizeof(int))) return -EFAULT; - if (i>1 || i<0) - return -EINVAL; +/* if(i>1 || i<0) + return -EINVAL; +*/ switch (btv->frame_stat[i]) { case GBUFFER_UNUSED: return -EINVAL; case GBUFFER_GRABBING: - interruptible_sleep_on(&btv->capq); + while(btv->frame_stat[i]==GBUFFER_GRABBING) { + interruptible_sleep_on(&btv->capq); + if(signal_pending(current)) + return -EINTR; + } /* fall */ case GBUFFER_DONE: btv->frame_stat[i] = GBUFFER_UNUSED; @@ -1763,7 +2051,11 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return 0; case BTTV_WRITEE: +#if LINUX_VERSION_CODE >= 0x020100 if(!capable(CAP_SYS_ADMIN)) +#else + if(!suser()) +#endif return -EPERM; if(copy_from_user((void *) eedata, (void *) arg, 256)) return -EFAULT; @@ -1771,32 +2063,39 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return 0; case BTTV_READEE: +#if LINUX_VERSION_CODE >= 0x020100 if(!capable(CAP_SYS_ADMIN)) +#else + if(!suser()) +#endif return -EPERM; readee(&(btv->i2c), eedata); if(copy_to_user((void *) arg, (void *) eedata, 256)) return -EFAULT; break; - case BTTV_FIELDNR: + case BTTV_FIELDNR: if(copy_to_user((void *) arg, (void *) &btv->last_field, sizeof(btv->last_field))) return -EFAULT; break; - - case BTTV_PLLSET: - { - struct bttv_pll_info p; + + case BTTV_PLLSET: { + struct bttv_pll_info p; +#if LINUX_VERSION_CODE >= 0x020100 if(!capable(CAP_SYS_ADMIN)) - return -EPERM; - if(copy_from_user(&p , (void *) arg, sizeof(btv->pll))) +#else + if(!suser()) +#endif + return -EPERM; + if(copy_from_user(&p , (void *) arg, sizeof(btv->pll))) return -EFAULT; - btv->pll.pll_ifreq = p.pll_ifreq; - btv->pll.pll_ofreq = p.pll_ofreq; - btv->pll.pll_crystal = p.pll_crystal; - break; - } + btv->pll.pll_ifreq = p.pll_ifreq; + btv->pll.pll_ofreq = p.pll_ofreq; + btv->pll.pll_crystal = p.pll_crystal; + break; + } case VIDIOCMCAPTURE: { struct video_mmap vm; @@ -1840,7 +2139,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return -EFAULT; return 0; } - + case BTTV_BURST_ON: { tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2; @@ -1855,9 +2154,14 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) return 0; } + case BTTV_VERSION: + { + return BTTV_VERSION_CODE; + } + case BTTV_PICNR: { - /* return picture */ + /* return picture;*/ return 0; } @@ -1916,7 +2220,9 @@ static struct video_device bttv_template= bttv_close, bttv_read, bttv_write, +#if LINUX_VERSION_CODE >= 0x020100 NULL, /* poll */ +#endif bttv_ioctl, bttv_mmap, bttv_init_done, @@ -1970,6 +2276,7 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, return count; } +#if LINUX_VERSION_CODE >= 0x020100 static unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) { @@ -1983,6 +2290,7 @@ static unsigned int vbi_poll(struct video_device *dev, struct file *file, return mask; } +#endif static int vbi_open(struct video_device *dev, int flags) { @@ -2021,7 +2329,9 @@ static struct video_device vbi_template= vbi_close, vbi_read, bttv_write, +#if LINUX_VERSION_CODE >= 0x020100 vbi_poll, +#endif vbi_ioctl, NULL, /* no mmap yet */ bttv_init_done, @@ -2131,7 +2441,9 @@ static struct video_device radio_template= radio_close, radio_read, /* just returns -EINVAL */ bttv_write, /* just returns -EINVAL */ +#if LINUX_VERSION_CODE >= 0x020100 NULL, /* no poll */ +#endif radio_ioctl, NULL, /* no mmap */ bttv_init_done, /* just returns 0 */ @@ -2149,14 +2461,14 @@ struct vidbases }; static struct vidbases vbs[] = { - { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D, - "Alliance AT3D", PCI_BASE_ADDRESS_0}, + { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D, + "Alliance AT3D", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222, "ATI MACH64 CT", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX, "ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT, - "ATI MACH64 GT", PCI_BASE_ADDRESS_0}, + "ATI MACH64 GT", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_CIRRUS, 0, "Cirrus Logic", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, "DEC DC21030", PCI_BASE_ADDRESS_0}, @@ -2167,6 +2479,7 @@ static struct vidbases vbs[] = { { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP, "Matrox Millennium II AGP", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1}, + { PCI_VENDOR_ID_MATROX, 0x0521, "Matrox G200", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, "Number Nine Imagine 128", PCI_BASE_ADDRESS_0}, { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128_2, @@ -2192,6 +2505,8 @@ static uint dec_offsets[4] = { /* Scan for PCI display adapter if more than one card is present the last one is used for now */ +#if LINUX_VERSION_CODE >= 0x020100 + static int find_vga(void) { unsigned short badr; @@ -2271,6 +2586,99 @@ static int find_vga(void) return found; } +#else +static int find_vga(void) +{ + unsigned int devfn, class, vendev; + unsigned short vendor, device, badr; + int found=0, bus=0, i, tga_type; + unsigned int vidadr=0; + + + for (devfn = 0; devfn < 0xff; devfn++) + { + if (PCI_FUNC(devfn) != 0) + continue; + pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendev); + if (vendev == 0xffffffff || vendev == 0x00000000) + continue; + pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &device); + pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class); + class = class >> 16; +/* if (class == PCI_CLASS_DISPLAY_VGA) {*/ + if ((class>>8) == PCI_BASE_CLASS_DISPLAY || + /* Number 9 GXE64Pro needs this */ + class == PCI_CLASS_NOT_DEFINED_VGA) + { + badr=0; + printk(KERN_INFO "bttv: PCI display adapter: "); + for (i=0; i<NR_CARDS; i++) + { + if (vendor==vbs[i].vendor) + { + if (vbs[i].device) + if (vbs[i].device!=device) + continue; + printk("%s.\n", vbs[i].name); + badr=vbs[i].badr; + break; + } + } + if (NR_CARDS == i) + printk("UNKNOWN.\n"); + if (!badr) + { + printk(KERN_ERR "bttv: Unknown video memory base address.\n"); + continue; + } + pcibios_read_config_dword(bus, devfn, badr, &vidadr); + if (vidadr & PCI_BASE_ADDRESS_SPACE_IO) + { + printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n"); + printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n"); + continue; + } + vidadr &= PCI_BASE_ADDRESS_MEM_MASK; + if (!vidadr) + { + printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!\n"); + continue; + } + + if (vendor==PCI_VENDOR_ID_DEC) + if (device==PCI_DEVICE_ID_DEC_TGA) + { + tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f; + if (tga_type != 0 && tga_type != 1 && tga_type != 3) + { + printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type); + found--; + } + vidadr+=dec_offsets[tga_type]; + } + + DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr)); + DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", devfn)); + found++; + } + } + + if (vidmem) + { + if (vidmem < 0x1000) + vidadr=vidmem<<20; + else + vidadr=vidmem; + printk(KERN_INFO "bttv: Video memory override: 0x%08x\n", vidadr); + found=1; + } + for (i=0; i<BTTV_MAX; i++) + bttvs[i].win.vidadr=vidadr; + + return found; +} +#endif #define TRITON_PCON 0x50 @@ -2279,6 +2687,9 @@ static int find_vga(void) #define TRITON_WRITE_BURST (1<<2) #define TRITON_PEER_CONCURRENCY (1<<3) + +#if LINUX_VERSION_CODE >= 0x020100 + static void handle_chipset(void) { struct pci_dev *dev = NULL; @@ -2342,6 +2753,78 @@ static void handle_chipset(void) #endif } } +#else +static void handle_chipset(void) +{ + int index; + + for (index = 0; index < 8; index++) + { + unsigned char bus, devfn; + unsigned char b; + + /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */ + + if (!pcibios_find_device(PCI_VENDOR_ID_SI, + PCI_DEVICE_ID_SI_496, + index, &bus, &devfn)) + { + printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n"); + } + + if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82441, + index, &bus, &devfn)) + { + pcibios_read_config_byte(bus, devfn, 0x53, &b); + DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, ")); + DEBUG(printk("bufcon=0x%02x\n",b)); + } + + if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, + index, &bus, &devfn)) + { + printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n"); + triton1=BT848_INT_ETBF; + +#if 0 + /* The ETBF bit SHOULD make all this unnecessary */ + /* 430FX (Triton I) freezes with bus concurrency on -> switch it off */ + { + unsigned char bo; + + pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b); + bo=b; + DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b)); + + if(!(b & TRITON_BUS_CONCURRENCY)) + { + printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n"); + b |= TRITON_BUS_CONCURRENCY; + } + + if(b & TRITON_PEER_CONCURRENCY) + { + printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n"); + b &= ~TRITON_PEER_CONCURRENCY; + } + if(!(b & TRITON_STREAMING)) + { + printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n"); + b |= TRITON_STREAMING; + } + + if (b!=bo) + { + pcibios_write_config_byte(bus, devfn, TRITON_PCON, b); + printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b); + } + } +#endif + } + } +} +#endif static void init_tda8425(struct i2c_bus *bus) { @@ -2349,9 +2832,13 @@ static void init_tda8425(struct i2c_bus *bus) I2CWrite(bus, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */ I2CWrite(bus, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */ I2CWrite(bus, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */ - I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */ + I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */ } +static void init_tda9840(struct i2c_bus *bus) +{ + I2CWrite(bus, I2C_TDA9840, TDA9840_SW, 0x2A, 1); /* Sound mode switching */ +} static void init_tda9850(struct i2c_bus *bus) { @@ -2372,7 +2859,6 @@ static void idcard(int i) { struct bttv *btv = &bttvs[i]; - int tunertype; btwrite(0, BT848_GPIO_OUT_EN); DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA))); @@ -2385,95 +2871,123 @@ static void idcard(int i) */ if (btv->type == BTTV_UNKNOWN) { - btv->type=BTTV_MIRO; - - if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) { + if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) + { if(btv->id>849) btv->type=BTTV_HAUPPAUGE878; else - btv->type=BTTV_HAUPPAUGE; + btv->type=BTTV_HAUPPAUGE; + + } else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) { + btv->type=BTTV_STB; + } else + if (I2CRead(&(btv->i2c), I2C_VHX)>=0) { + btv->type=BTTV_VHX; + } else { + if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */ + btv->type = BTTV_MIROPRO; + else + btv->type=BTTV_MIRO; } - else - if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) - btv->type=BTTV_STB; - - if (btv->type == BTTV_MIRO) { - /* auto detect tuner for MIRO cards */ - btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; - } } + /* board specific initialisations */ + if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) { + /* auto detect tuner for MIRO cards */ + btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; + } + if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) { + hauppauge_msp_reset(btv); + hauppauge_eeprom(&(btv->i2c)); + if (btv->type == BTTV_HAUPPAUGE878) { + /* all bt878 hauppauge boards use this ... */ + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; + } + } + if(btv->type==BTTV_AVERMEDIA98) + { + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; + } + + if (btv->have_tuner && btv->tuner_type != -1) + i2c_control_device(&(btv->i2c), + I2C_DRIVERID_TUNER, + TUNER_SET_TYPE,&btv->tuner_type); + + + if (I2CRead(&(btv->i2c), I2C_TDA9840) >=0) + { + btv->audio_chip = TDA9840; + printk(KERN_INFO "bttv%d: audio chip: TDA9840\n", btv->nr); + } + if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0) { - btv->audio_chip = TDA9850; - printk(KERN_INFO "bttv%d: audio chip: TDA9850\n", i); + btv->audio_chip = TDA9850; + printk(KERN_INFO "bttv%d: audio chip: TDA9850\n",btv->nr); } if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0) { - btv->audio_chip = TDA8425; - printk("bttv%d: audio chip: TDA8425\n", i); + btv->audio_chip = TDA8425; + printk(KERN_INFO "bttv%d: audio chip: TDA8425\n",btv->nr); } switch(btv->audio_chip) { case TDA9850: init_tda9850(&(btv->i2c)); - break; - case TDA8425: + break; + case TDA9840: + init_tda9840(&(btv->i2c)); + break; + case TDA8425: init_tda8425(&(btv->i2c)); break; } + + printk(KERN_INFO "bttv%d: model: ",btv->nr); - /* How do I detect the tuner type for other cards but Miro ??? */ - printk(KERN_INFO "bttv%d: model: ", btv->nr); sprintf(btv->video_dev.name,"BT%d",btv->id); switch (btv->type) { - case BTTV_MIRO: - case BTTV_MIROPRO: - printk("MIRO\n"); - if (btv->have_tuner) - { - tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7; - i2c_control_device(&(btv->i2c), - I2C_DRIVERID_TUNER, - TUNER_SET_TYPE,&tunertype); - } - strcat(btv->video_dev.name,"(Miro)"); + case BTTV_MIRO: + case BTTV_MIROPRO: + strcat(btv->video_dev.name, + (btv->type == BTTV_MIRO) ? "(Miro)" : "(Miro pro)"); break; case BTTV_HAUPPAUGE: + strcat(btv->video_dev.name,"(Hauppauge old)"); + break; case BTTV_HAUPPAUGE878: - printk("HAUPPAUGE\n"); - strcat(btv->video_dev.name,"(Hauppauge)"); + strcat(btv->video_dev.name,"(Hauppauge new)"); break; case BTTV_STB: - printk("STB\n"); strcat(btv->video_dev.name,"(STB)"); break; case BTTV_INTEL: - printk("Intel\n"); strcat(btv->video_dev.name,"(Intel)"); break; case BTTV_DIAMOND: - printk("Diamond\n"); strcat(btv->video_dev.name,"(Diamond)"); break; case BTTV_AVERMEDIA: - printk("AVerMedia\n"); strcat(btv->video_dev.name,"(AVerMedia)"); break; case BTTV_MATRIX_VISION: - printk("MATRIX-Vision\n"); strcat(btv->video_dev.name,"(MATRIX-Vision)"); break; - case BTTV_ADSTECH_TV: - printk("ADSTech Channel Surfer TV\n"); - strcat(btv->video_dev.name,"(ADSTech Channel Surfer TV)"); - btv->tuner_type=8; + case BTTV_AVERMEDIA98: + strcat(btv->video_dev.name,"(AVerMedia TVCapture 98)"); break; + case BTTV_VHX: + strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)"); + break; } - audio(btv, AUDIO_INTERN); + printk("%s\n",btv->video_dev.name); + audio(btv, AUDIO_MUTE); } @@ -2522,7 +3036,7 @@ static void bt848_set_risc_jmps(struct bttv *btv) btv->risc_jmp[12]=BT848_RISC_JUMP; btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp); - /* enable capturing and DMA */ + /* enable cpaturing and DMA */ btaor(flags, ~0x0f, BT848_CAP_CTL); if (flags&0x0f) bt848_dma(btv, 3); @@ -2530,7 +3044,6 @@ static void bt848_set_risc_jmps(struct bttv *btv) bt848_dma(btv, 0); } - static int init_bt848(int i) { struct bttv *btv = &bttvs[i]; @@ -2541,19 +3054,7 @@ static int init_bt848(int i) btwrite(0, BT848_SRESET); DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem)); -#ifdef RESET_MSP_HAUPPAUGE - /* Reset the MSP on some Hauppauge cards */ - /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */ - /* Can this hurt cards without one? What about Miros with MSP? */ - btaor(32, ~32, BT848_GPIO_OUT_EN); - btaor(0, ~32, BT848_GPIO_DATA); - udelay(2500); - btaor(32, ~32, BT848_GPIO_DATA); - btaor(0, ~32, BT848_GPIO_OUT_EN); -#endif - /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */ - btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */ btv->win.interlace=1; btv->win.x=0; @@ -2582,7 +3083,10 @@ static int init_bt848(int i) btv->grabcount=0; btv->grab=0; btv->lastgrab=0; - btv->field=btv->last_field=0; + btv->field=btv->last_field=0; + /* cevans - prevents panic if initialization bails due to memory + * alloc failures! + */ btv->video_dev.minor = -1; btv->vbi_dev.minor = -1; btv->radio_dev.minor = -1; @@ -2613,6 +3117,7 @@ static int init_bt848(int i) memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random memory to the user */ + btv->fbuffer=NULL; bt848_muxsel(btv, 1); @@ -2621,7 +3126,7 @@ static int init_bt848(int i) /* btwrite(0, BT848_TDEC); */ btwrite(0x10, BT848_COLOR_CTL); btwrite(0x00, BT848_CAP_CTL); - btwrite(0xfc, BT848_GPIO_DMA_CTL); + btwrite(0xac, BT848_GPIO_DMA_CTL); /* select direct input */ btwrite(0x00, BT848_GPIO_REG_INP); @@ -2671,6 +3176,7 @@ static int init_bt848(int i) memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template)); memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template)); + idcard(i); if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0) @@ -2730,7 +3236,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (astat&BT848_INT_VSYNC) { IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr)); - btv->field++; + btv->field++; } if (astat&BT848_INT_SCERR) { IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr)); @@ -2756,8 +3262,9 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) /* captured full frame */ if (stat&(2<<28)) { + wake_up_interruptible(&btv->capq); btv->last_field=btv->field; - btv->grab++; + btv->grab++; btv->frame_stat[btv->grf] = GBUFFER_DONE; if ((--btv->grabbing)) { @@ -2774,7 +3281,9 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) btv->gfmt); } else { bt848_set_risc_jmps(btv); - bt848_set_geo(btv, btv->win.width, + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI); + btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI); + bt848_set_geo(btv, btv->win.width, btv->win.height, btv->win.color_fmt); } @@ -2820,12 +3329,10 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (astat&BT848_INT_HLOCK) { -#if 0 if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio)) audio(btv, AUDIO_ON); else audio(btv, AUDIO_OFF); -#endif } if (astat&BT848_INT_I2CDONE) @@ -2834,7 +3341,8 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) count++; if (count > 10) - printk (KERN_WARNING "bttv%d: irq loop %d\n", btv->nr, count); + printk (KERN_WARNING "bttv%d: irq loop %d\n", + btv->nr,count); if (count > 20) { btwrite(0, BT848_INT_MASK); @@ -2850,17 +3358,16 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) * Scan for a Bt848 card, request the irq and map the io memory */ +#if LINUX_VERSION_CODE >= 0x020100 int configure_bt848(struct pci_dev *dev, int bttv_num) { int result; - unsigned char bus, devfn, command; + unsigned char command; struct bttv *btv; btv=&bttvs[bttv_num]; btv->dev=dev; btv->nr = bttv_num; - btv->bus=bus=dev->bus->number; - btv->devfn=devfn=dev->devfn; btv->bt848_mem=NULL; btv->vbibuf=NULL; btv->risc_jmp=NULL; @@ -2896,15 +3403,14 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ", bttv_num,btv->id, btv->revision); - printk("bus: %d, devfn: %d, ", - btv->bus, btv->devfn); + printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn); printk("irq: %d, ",btv->irq); printk("memory: 0x%08x.\n", btv->bt848_adr); - - btv->pll.pll_ifreq=0; - btv->pll.pll_ofreq=0; - btv->pll.pll_crystal=0; - btv->pll.pll_current=0; + + btv->pll.pll_crystal = 0; + btv->pll.pll_ifreq = 0; + btv->pll.pll_ofreq = 0; + btv->pll.pll_current = 0; if (!(btv->id==848 && btv->revision==0x11)) { switch (pll[btv->nr]) { case 0: @@ -2922,10 +3428,10 @@ int configure_bt848(struct pci_dev *dev, int bttv_num) break; } } - + btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000); - /* clear interrupt mask */ + /* clear interrupt mask */ btwrite(0, BT848_INT_MASK); result = request_irq(btv->irq, bttv_irq, @@ -2988,7 +3494,170 @@ static int find_bt848(void) printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num); return bttv_num; } - +#else +static int find_bt848(void) +{ + short pci_index; + unsigned char command, latency; + int result; + unsigned char bus, devfn; + struct bttv *btv; + + bttv_num=0; + + if (!pcibios_present()) + { + DEBUG(printk(KERN_DEBUG "bttv%d: PCI-BIOS not present or not accessable!\n",bttv_num)); + return 0; + } + + for (pci_index = 0; + !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, + pci_index, &bus, &devfn) + ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + pci_index, &bus, &devfn) + ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, + pci_index, &bus, &devfn) + ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, + pci_index, &bus, &devfn); + ++pci_index) + { + btv=&bttvs[bttv_num]; + btv->nr = bttv_num; + btv->bus=bus; + btv->devfn=devfn; + btv->bt848_mem=NULL; + btv->vbibuf=NULL; + btv->risc_jmp=NULL; + btv->vbi_odd=NULL; + btv->vbi_even=NULL; + btv->vbiq=NULL; + btv->capq=NULL; + btv->capqo=NULL; + btv->capqe=NULL; + + btv->vbip=VBIBUF_SIZE; + + pcibios_read_config_word(btv->bus, btv->devfn, PCI_DEVICE_ID, + &btv->id); + pcibios_read_config_byte(btv->bus, btv->devfn, + PCI_INTERRUPT_LINE, &btv->irq); + pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0, + &btv->bt848_adr); + if (btv->id >= 878) + btv->i2c_command = 0x83; + else + btv->i2c_command= + (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA); + + if (remap[bttv_num]) + { + if (remap[bttv_num] < 0x1000) + remap[bttv_num]<<=20; + remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK; + printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n", + bttv_num,remap[bttv_num]); + remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK); + pcibios_write_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0, + remap[bttv_num]); + pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0, + &btv->bt848_adr); + } + + btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK; + pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION, + &btv->revision); + printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ", + bttv_num,btv->id, btv->revision); + printk("bus: %d, devfn: %d, ", + btv->bus, btv->devfn); + printk("irq: %d, ",btv->irq); + printk("memory: 0x%08x.\n", btv->bt848_adr); + + btv->pll.pll_crystal = 0; + btv->pll.pll_ifreq = 0; + btv->pll.pll_ofreq = 0; + btv->pll.pll_current = 0; + if (!(btv->id==848 && btv->revision==0x11)) { + switch (pll[btv->nr]) { + case 0: + /* off */ + break; + case 1: + /* 28 MHz crystal installed */ + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; + break; + case 2: + /* 35 MHz crystal installed */ + btv->pll.pll_ifreq=35468950; + btv->pll.pll_crystal=BT848_IFORM_XT1; + break; + } + } + + btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000); + + result = request_irq(btv->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv); + if (result==-EINVAL) + { + printk(KERN_ERR "bttv%d: Bad irq number or handler\n", + bttv_num); + return -EINVAL; + } + if (result==-EBUSY) + { + printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq); + return result; + } + if (result < 0) + return result; + + /* Enable bus-mastering */ + pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command); + command|=PCI_COMMAND_MASTER; + pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command); + pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command); + if (!(command&PCI_COMMAND_MASTER)) + { + printk(KERN_ERR "bttv%d: PCI bus-mastering could not be enabled\n",bttv_num); + return -1; + } + pcibios_read_config_byte(btv->bus, btv->devfn, PCI_LATENCY_TIMER, + &latency); + if (!latency) + { + latency=32; + pcibios_write_config_byte(btv->bus, btv->devfn, + PCI_LATENCY_TIMER, latency); + } + DEBUG(printk(KERN_DEBUG "bttv%d: latency: %02x\n", + bttv_num, latency)); + + btv->triton1=triton1 ? BT848_INT_ETBF : 0; + if (triton1 && btv->id >= 878) + { + triton1 = 0; + printk("bttv: Enabling 430FX compatibilty for bt878\n"); + pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command); + command|=BT878_EN_TBFX; + pcibios_write_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, command); + pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command); + if (!(command&BT878_EN_TBFX)) + { + printk("bttv: 430FX compatibility could not be enabled\n"); + return -1; + } + } + + bttv_num++; + } + if(bttv_num) + printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num); + return bttv_num; +} +#endif static void release_bttv(void) { @@ -3013,10 +3682,17 @@ static void release_bttv(void) i2c_unregister_bus((&btv->i2c)); /* disable PCI bus-mastering */ +#if LINUX_VERSION_CODE >= 0x020100 pci_read_config_byte(btv->dev, PCI_COMMAND, &command); /* Should this be &=~ ?? */ - command|=PCI_COMMAND_MASTER; + command&=~PCI_COMMAND_MASTER; pci_write_config_byte(btv->dev, PCI_COMMAND, command); +#else + pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command); + command&=~PCI_COMMAND_MASTER; + pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command); + +#endif /* unmap and free memory */ if (btv->grisc) @@ -3046,7 +3722,7 @@ static void release_bttv(void) video_unregister_device(&btv->video_dev); if(btv->vbi_dev.minor!=-1) video_unregister_device(&btv->vbi_dev); - if (radio && btv->radio_dev.minor != -1) + if (radio[btv->nr] && btv->radio_dev.minor != -1) video_unregister_device(&btv->radio_dev); } } @@ -3074,6 +3750,7 @@ int init_bttv_cards(struct video_init *unused) return -EIO; } } + return 0; } |