--- linux-2.3.47/drivers/char/bttv.c Fri Feb 25 17:47:58 2000 +++ linux/drivers/char/bttv.c Fri Feb 25 17:59:20 2000 @@ -3,7 +3,7 @@ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999 Gerd Knorr + (c) 1999,2000 Gerd Knorr 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 @@ -20,6 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include #include #include #include @@ -40,27 +42,28 @@ #include #include #include -#include #include #include -#include -#include -#include - +#ifdef LOCK_I2C_BUS +# error INSTALL ERROR +# error gcc uses the old, obsolete i2c.h include file. Please install the \ + new i2c stack. Please install it by patching the kernel, otherwise \ + gcc will not find the new header files. +#endif #include "bttv.h" #include "tuner.h" #define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ +#define IDEBUG(x) /* Debug interrupt handler */ #define MIN(a,b) (((a)>(b))?(b):(a)) #define MAX(a,b) (((a)>(b))?(a):(b)) /* Anybody who uses more than four? */ #define BTTV_MAX 4 -static void bt848_set_risc_jmps(struct bttv *btv); +static void bt848_set_risc_jmps(struct bttv *btv, int state); static int bttv_num; /* number of Bt848s in use */ static struct bttv bttvs[BTTV_MAX]; @@ -74,7 +77,20 @@ MODULE_PARM(pll,"1-4i"); MODULE_PARM(bigendian,"i"); MODULE_PARM(fieldnr,"i"); +MODULE_PARM(verbose,"i"); +MODULE_PARM(debug,"i"); MODULE_PARM(autoload,"i"); +MODULE_PARM(gbuffers,"i"); +MODULE_PARM(gbufsize,"i"); + +EXPORT_SYMBOL(bttv_get_id); +EXPORT_SYMBOL(bttv_gpio_enable); +EXPORT_SYMBOL(bttv_read_gpio); +EXPORT_SYMBOL(bttv_write_gpio); +EXPORT_SYMBOL(bttv_get_gpio_queue); + +MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards"); +MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); #if defined(__sparc__) || defined(__powerpc__) static unsigned int bigendian=1; @@ -87,7 +103,15 @@ static unsigned int card[BTTV_MAX] = { 0, 0, 0, 0 }; static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0}; static unsigned int fieldnr = 0; +static unsigned int verbose = 1; +static unsigned int debug = 0; +static unsigned int gbuffers = 2; +static unsigned int gbufsize = BTTV_MAX_FBUF; +#ifdef MODULE static unsigned int autoload = 1; +#else +static unsigned int autoload = 0; +#endif #define I2C_TIMING (0x7<<4) @@ -100,6 +124,101 @@ #define BURSTOFFSET 76 +/* ----------------------------------------------------------------------- */ +/* Exported functions - for other modules which want to access the */ +/* gpio ports (IR for example) */ +/* see bttv.h for comments */ + +int bttv_get_id(unsigned int card) +{ + if (card >= bttv_num) { + return -1; + } + + return bttvs[card].type; +} + +int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return -EINVAL; + } + + btv = &bttvs[card]; + down(&btv->lock); + btaor(data, ~mask, BT848_GPIO_OUT_EN); + up(&btv->lock); + + return 0; +} + +int bttv_read_gpio(unsigned int card, unsigned long *data) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return -EINVAL; + } + + btv = &bttvs[card]; + + if(btv->shutdown) { + return -ENODEV; + } + + down(&btv->lock); + +/* prior setting BT848_GPIO_REG_INP is (probably) not needed + because we set direct input on init */ + + *data = btread(BT848_GPIO_DATA); + + up(&btv->lock); + + return 0; +} + +int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return -EINVAL; + } + + btv = &bttvs[card]; + + down(&btv->lock); + +/* prior setting BT848_GPIO_REG_INP is (probably) not needed + because direct input is set on init */ + + btaor(data & mask, ~mask, BT848_GPIO_DATA); + + up(&btv->lock); + + return 0; +} + +WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card) +{ + struct bttv *btv; + + if (card >= bttv_num) { + return NULL; + } + + btv = &bttvs[card]; + + if (bttvs[card].shutdown) { + return NULL; + } + + return &btv->gpioq; +} + /*******************************/ /* Memory management functions */ /*******************************/ @@ -176,11 +295,11 @@ return ret; } -static void * rvmalloc(unsigned long size) +static void * rvmalloc(signed long size) { void * mem; unsigned long adr, page; - + mem=vmalloc(size); if (mem) { @@ -197,7 +316,7 @@ return mem; } -static void rvfree(void * mem, unsigned long size) +static void rvfree(void * mem, signed long size) { unsigned long adr, page; @@ -227,7 +346,7 @@ static int fbuffer_alloc(struct bttv *btv) { if(!btv->fbuffer) - btv->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS*BTTV_MAX_FBUF); + btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize); else printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n", btv->nr); @@ -320,7 +439,8 @@ } if (btv->tuner_type != -1) call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name); + if (verbose) + printk("bttv%d: i2c attach [%s]\n",btv->nr,client->name); return 0; } @@ -328,8 +448,9 @@ { struct bttv *btv = (struct bttv*)client->adapter->data; int i; - - printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name); + + if (verbose) + printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name); for (i = 0; i < I2C_CLIENTS_MAX; i++) { if (NULL != btv->i2c_clients[i] && btv->i2c_clients[i]->driver->id == client->driver->id) { @@ -395,19 +516,20 @@ { unsigned char buffer = 0; - if (NULL != probe_for) + if (verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", btv->nr,probe_for,addr); btv->i2c_client.addr = addr >> 1; if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { - if (NULL != probe_for) - printk("not found\n"); - else + if (NULL != probe_for) { + if (verbose) + printk("not found\n"); + } else printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", btv->nr,addr); return -1; } - if (NULL != probe_for) + if (verbose && NULL != probe_for) printk("found\n"); return buffer; } @@ -481,31 +603,70 @@ { TUNER_PHILIPS_PAL, "Philips FM1216" }, { TUNER_ABSENT, "Philips FM1216MF" }, { TUNER_PHILIPS_NTSC, "Philips FM1236" }, + { TUNER_PHILIPS_PAL_I, "Philips FM1246" }, + { TUNER_ABSENT, "Philips FM1256" }, + { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" }, + { TUNER_ABSENT, "Samsung TCPN9082D" }, + { TUNER_ABSENT, "Samsung TCPM9092P" }, + { TUNER_TEMIC_PAL, "Temic 4006FH5" }, + { TUNER_ABSENT, "Samsung TCPN9085D" }, + { TUNER_ABSENT, "Samsung TCPB9085P" }, + { TUNER_ABSENT, "Samsung TCPL9091P" }, + { TUNER_ABSENT, "Temic 4039FR5" }, + { TUNER_ABSENT, "Philips FQ1216 ME" }, + { TUNER_TEMIC_PAL_I, "Temic 4066FY5" }, + { TUNER_ABSENT, "Philips TD1536" }, + { TUNER_ABSENT, "Philips TD1536D" }, + { TUNER_ABSENT, "Philips FMR1236" }, + { TUNER_ABSENT, "Philips FI1256MP" }, + { TUNER_ABSENT, "Samsung TCPQ9091P" }, + { TUNER_ABSENT, "Temic 4006FN5" }, + { TUNER_ABSENT, "Temic 4009FR5" }, + { TUNER_ABSENT, "Temic 4046FM5" }, }; static void hauppauge_eeprom(struct bttv *btv) { - readee(btv, eeprom_data, 0xa0); 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); + if (verbose) + 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) +hauppauge_boot_msp34xx(struct bttv *btv) { - /* Reset the MSP on some Hauppauge cards */ + int i; + + /* reset/enable 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); */ + + if (verbose) + printk("bttv%d: Hauppauge msp34xx: reset line init\n",btv->nr); + + /* look if the msp3400 driver is already registered */ + for (i = 0; i < I2C_CLIENTS_MAX; i++) { + if (btv->i2c_clients[i] != NULL && + btv->i2c_clients[i]->driver->id == I2C_DRIVERID_MSP3400) { + return; + } + } + + /* if not: look for the chip ... */ + if (I2CRead(btv, I2C_MSP3400, "MSP34xx")) { + /* ... if found re-register to trigger a i2c bus rescan, */ + /* this time with the msp34xx chip activated */ + i2c_bit_del_bus(&btv->i2c_adap); + i2c_bit_add_bus(&btv->i2c_adap); + } } @@ -555,19 +716,34 @@ int id; char *name; } vendors[] = { - { 0x0070, "Hauppauge" }, - { 0x144f, "Askey" }, + { 0x1002, "ATI Technologies Inc" }, + { 0x10b4, "STB Systems Inc" }, + { 0x13eb, "Hauppauge Computer Works Inc" }, + { 0x1461, "Avermedia" }, + { 0x1850, "Chronos" }, + { 0x1852, "Typhoon" }, + { 0x3000, "Askey" }, + { 0x3002, "Askey" }, + { 0x6606, "Leadtek" }, { -1, NULL } }; static struct CARD { - int id; int vid; + int id; int cardnr; char *name; } cards[] = { - { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV Theater" }, - { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" }, + { 0x1002, 0x0001, BTTV_HAUPPAUGE878, "TV Wonder" }, + { 0x10b4, 0x2636, BTTV_HAUPPAUGE878, "???" }, + { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV" }, + { 0x1461, 0x0002, BTTV_AVERMEDIA98, "TVCapture 98" }, + { 0x1850, 0x1851, BTTV_CHRONOS_VS2, "Video Shuttle II" }, + { 0x1852, 0x1852, BTTV_TYPHOON_TVIEW, "TView TV/FM Tuner" }, + { 0x3000, 0x14ff, BTTV_MAGICTVIEW061, "TView 99" }, + { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" }, + { 0x3002, 0x14ff, BTTV_PHOEBE_TVMAS, "TV Master" }, + { 0x6606, 0x217d, BTTV_WINFAST2000, "WinFast TV 2000" }, { -1, -1, -1, NULL } }; @@ -594,7 +770,7 @@ static struct tvcard tvcards[] = { /* 0x00 */ - { "unknown", + { " *** UNKNOWN *** ", 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, 1,1,1,1,0 }, { "MIRO PCTV", @@ -614,7 +790,7 @@ 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0, 1,1,1,1,0 }, { "AVerMedia TVPhone", - 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0},0, + 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0, 1,1,1,1,0 }, { "MATRIX-Vision MV-Delta", 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, @@ -713,16 +889,32 @@ { "Terratec TerraTValue", 3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0, 1,1,1,1,0 }, + { "Leadtek WinFast 2000", + 3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0}, + { 0x621000,0x621000,0x621000,0x621000,0xE21000,0x621000},0, + 1,1,1,1,1 }, + { "Chronos Video Shuttle II", + 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0, + 1,1,1,1,0 }, + + { "Typhoon TView TV/FM Tuner", + 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0, + 1,1,1,1,0 }, + { "PixelView PlayTV pro", + 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, + { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 } }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) static void -dump_eeprom(struct bttv *btv, int addr) +dump_eeprom(struct bttv *btv,int addr) { - int i,id1,id2,n1,n2; + int i; + if (verbose < 2) + return; + /* for debugging: dump eeprom to syslog */ printk(KERN_DEBUG "bttv%d: dump eeprom @ 0x%02x\n",btv->nr,addr); - readee(btv, eeprom_data,addr); for (i = 0; i < 256;) { printk(KERN_DEBUG " %02x:",i); do { @@ -730,35 +922,47 @@ } while (i % 16); printk("\n"); } - id1 = (eeprom_data[252] << 8) | (eeprom_data[253]); - id2 = (eeprom_data[254] << 8) | (eeprom_data[255]); - if (id1 != 0 && id1 != 0xffff && - id2 != 0 && id2 != 0xffff) { - n1 = -1; - n2 = -1; - for (i = 0; vendors[i].id != -1; i++) - if (vendors[i].id == id2) - n2 = i; - for (i = 0; cards[i].id != -1; i++) - if (cards[i].id == id1 && - cards[i].vid == id2) - n1 = i; - if (n1 != -1 && n2 != -1) { - printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n", - cards[n1].name,id1,vendors[n2].name,id2); - printk(KERN_INFO " => card=%d (%s)\n", - cards[n1].cardnr,tvcards[cards[n1].cardnr].name); -#if 1 - /* not yet, but that's the plan for autodetect... */ - btv->type = cards[n1].cardnr; -#endif - } else { - printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n", - (n1 != -1) ? cards[n1].name : "unknown", id1, - (n2 != -1) ? vendors[n2].name : "unknown", id2); - printk(KERN_INFO " please mail card type, id + vendor to "); - printk(" kraxel@goldbach.in-berlin.de\n"); - } +} + +static int +idcard_eeprom(struct bttv *btv) +{ + int i,id1,id2,n1,n2; + + id1 = (eeprom_data[254] << 8) | (eeprom_data[255]); + id2 = (eeprom_data[252] << 8) | (eeprom_data[253]); + if (id1 == 0 || id1 == 0xffff || + id2 == 0 || id2 == 0xffff) + return -1; + + /* look for the card */ + n1 = -1; n2 = -1; + for (i = 0; vendors[i].id != -1; i++) + if (vendors[i].id == id2) + n2 = i; + for (i = 0; cards[i].id != -1; i++) + if (cards[i].id == id1 && + cards[i].vid == id2) + n1 = i; + + if (n1 != -1 && n2 != -1) { + /* found it */ + printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n", + btv->nr,cards[n1].name,id1,vendors[n2].name,id2); + if (verbose) + printk(KERN_INFO "bttv%d: => card=%d (%s)\n", + btv->nr,cards[n1].cardnr, + tvcards[cards[n1].cardnr].name); + return cards[n1].cardnr; + } else { + /* 404 */ + printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n", + btv->nr, "unknown", id1, + (n2 != -1) ? vendors[n2].name : "unknown", id2); + printk(KERN_INFO "please mail id + vendor, board name and " + "the correct card= insmod option to " + "kraxel@goldbach.in-berlin.de\n"); + return -1; } } @@ -810,21 +1014,6 @@ } -static void bt848_cap(struct bttv *btv, uint state) -{ - if (state) - { - btv->cap|=3; - bt848_set_risc_jmps(btv); - } - else - { - btv->cap&=~3; - bt848_set_risc_jmps(btv); - } -} - - /* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/ /* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C @@ -885,9 +1074,10 @@ /* printk("bttv%d: PLL: no change required\n",btv->nr); */ return 1; } - - printk("bttv%d: PLL: %d => %d ... ",btv->nr, - btv->pll.pll_ifreq, btv->pll.pll_ofreq); + + if (verbose) + printk("bttv%d: PLL: %d => %d ... ",btv->nr, + btv->pll.pll_ifreq, btv->pll.pll_ofreq); set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); @@ -907,13 +1097,15 @@ { btwrite(0x08,BT848_TGCTRL); btv->pll.pll_current = btv->pll.pll_ofreq; - printk("ok\n"); + if (verbose) + printk("ok\n"); return 1; } mdelay(10); } btv->pll.pll_current = 0; - printk("oops\n"); + if (verbose) + printk("oops\n"); return -1; } @@ -1010,10 +1202,9 @@ unsigned int *po=(unsigned int *) btv->vbi_odd; unsigned int *pe=(unsigned int *) btv->vbi_even; - DEBUG(printk(KERN_DEBUG "vbiodd: 0x%lx\n",(long)btv->vbi_odd)); - DEBUG(printk(KERN_DEBUG "vbievn: 0x%lx\n",(long)btv->vbi_even)); - DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po)); - DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe)); + if (debug) + printk("bttv%d: vbi: po=%08lx pe=%08lx\n", + btv->nr,virt_to_bus(po), virt_to_bus(pe)); *(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0; for (i=0; i<16; i++) @@ -1036,11 +1227,11 @@ DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe)); } -int fmtbppx2[16] = { +static int fmtbppx2[16] = { 8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 }; -int palette2fmt[] = { +static int palette2fmt[] = { 0, BT848_COLOR_FMT_Y8, BT848_COLOR_FMT_RGB8, @@ -1082,7 +1273,7 @@ *(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); *(ro++)=cpu_to_le32(kvirt_to_bus(vadr)); *(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL); - *(re++)=cpu_to_le32(kvirt_to_bus(vadr+BTTV_MAX_FBUF/2)); + *(re++)=cpu_to_le32(kvirt_to_bus(vadr+gbufsize/2)); vadr+=bpl; } @@ -1108,6 +1299,9 @@ unsigned long vadr=(unsigned long) vbuf; int shift, csize; + if (debug) + printk("bttv%d: prisc: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); switch(fmt) { @@ -1140,7 +1334,7 @@ } cbadr=vadr+(width*height); cradr=cbadr+csize; - inter = (height>btv->win.cropheight/2) ? 1 : 0; + inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(ro++)=0; @@ -1158,7 +1352,7 @@ if (inter) rp= (line&1) ? &re : &ro; else - rp= (line>=height) ? &re : &ro; + rp= (line>=height) ? &ro : &re; if(line&lmask) @@ -1222,9 +1416,12 @@ 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; + + if (debug) + printk("bttv%d: vrisc: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); + + inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); @@ -1237,7 +1434,7 @@ if (inter) rp= (line&1) ? &re : &ro; else - rp= (line>=height) ? &re : &ro; + rp= (line>=height) ? &ro : &re; bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr); if (bpl<=bl) @@ -1335,32 +1532,31 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) { - int i, line, x, y, bpl, width, height, inter; + int i, line, x, y, bpl, width, height, inter, maxw; unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len; unsigned long adr; - unsigned char *clipmap, cbit, lastbit, outofmem; + unsigned char *clipmap, *clipline, cbit, lastbit, outofmem; - if (btv->win.use_yuv) { - /* yuv-to-offscreen (BT848_COLOR_FMT_YUY2) */ - bpp = 2; - bpl = btv->win.win2.pitch; - adr = btv->win.vidadr + btv->win.win2.start; - } else { - bpp=btv->win.bpp; - if (bpp==15) /* handle 15bpp as 16bpp in calculations */ - bpp++; - bpl=btv->win.bpl; - adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl; - } + /* take care: bpp != btv->win.bpp is allowed here */ + bpp = fmtbppx2[btv->win.color_fmt&0xf]/2; + bpl=btv->win.bpl; + adr=btv->win.vidadr + btv->win.x * btv->win.bpp + btv->win.y * bpl; inter=(btv->win.interlace&1)^1; width=btv->win.width; height=btv->win.height; + if (debug) + printk("bttv%d: make_clip: pal=%d size=%dx%d, bpl=%d bpp=%d\n", + btv->nr,btv->picture.palette,width,height,bpl,bpp); if(width > 1023) width = 1023; /* sanity check */ if(height > 625) height = 625; /* sanity check */ - ro=btv->risc_odd; - re=btv->risc_even; + ro=btv->risc_scr_odd; + re=btv->risc_scr_even; + + if (debug) + printk("bttv%d: clip: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) { /* can't clip, don't generate any risc code */ @@ -1380,16 +1576,15 @@ /* clip against viewing window AND screen so we do not have to rely on the user program */ - if (!btv->win.use_yuv) { - clip_draw_rectangle(clipmap,(btv->win.x+width>btv->win.swidth) ? - (btv->win.swidth-btv->win.x) : width, 0, 1024, 768); - clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ? - (btv->win.sheight-btv->win.y) : height,1024,768); - if (btv->win.x<0) - clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768); - if (btv->win.y<0) - clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y)); - } + maxw = (bpl - btv->win.x * btv->win.bpp) / bpp; + clip_draw_rectangle(clipmap, (width > maxw) ? maxw : width, + 0, 1024, 768); + clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ? + (btv->win.sheight-btv->win.y) : height,1024,768); + if (btv->win.x<0) + clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768); + if (btv->win.y<0) + clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y)); *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=cpu_to_le32(0); @@ -1401,12 +1596,30 @@ { y = line>>inter; rp= (line&1) ? &re : &ro; - lastbit=(clipmap[y<<7]&1); - for(x=dx=1,sx=0; x<=width && !outofmem; x++) { - cbit = (clipmap[(y<<7)+(x>>3)] & (1<<(x&7))); - if (x < width && !lastbit == !cbit) + clipline = clipmap + (y<<7); /* running pointers ... */ + lastbit = *clipline & 1; + for(x=dx=0,sx=0; x<=width && !outofmem;) { + if (0 == (x&7)) { + /* check bytes not bits if we can ... */ + if (lastbit) { + while (0xff==*clipline && xrisc_odd > RISCMEM_LEN/2 - 16) + if (ro - btv->risc_scr_odd>RISCMEM_LEN/2 - 16) outofmem++; - if (re - btv->risc_even > RISCMEM_LEN/2 - 16) + if (re - btv->risc_scr_even>RISCMEM_LEN/2 - 16) outofmem++; } + x++; + if (0 == (x&7)) + clipline++; } if ((!inter)||(line&1)) adr+=bpl; @@ -1475,29 +1691,25 @@ } -static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, - u16 fmt, int no_irq_context) +static void bt848_set_geo(struct bttv *btv, + int no_irq_context) { u16 vscale, hscale; u32 xsf, sr; - u16 hdelay, vdelay; - u16 hactive, vactive; + u16 ewidth, eheight, owidth, oheight; + u16 format, bswap; + u16 hdelay; + u16 hactive; u16 inter; u8 crop, vtc; struct tvnorm *tvn; unsigned long flags; - if (!width || !height) - return; - save_flags(flags); cli(); tvn=&tvnorms[btv->win.norm]; - btv->win.cropheight=tvn->sheight; - btv->win.cropwidth=tvn->swidth; - btwrite(tvn->adelay, BT848_ADELAY); btwrite(tvn->bdelay, BT848_BDELAY); btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM); @@ -1508,59 +1720,84 @@ if (no_irq_context) set_pll(btv); - btwrite(fmt, BT848_COLOR_FMT); - if (bigendian && - fmt == BT848_COLOR_FMT_RGB32) { - btwrite((BT848_COLOR_CTL_GAMMA | - BT848_COLOR_CTL_WSWAP_ODD | - BT848_COLOR_CTL_WSWAP_EVEN | - BT848_COLOR_CTL_BSWAP_ODD | - BT848_COLOR_CTL_BSWAP_EVEN), - BT848_COLOR_CTL); - } else if (bigendian && - (fmt == BT848_COLOR_FMT_RGB16 || - fmt == BT848_COLOR_FMT_RGB15)) { - btwrite((BT848_COLOR_CTL_GAMMA | - BT848_COLOR_CTL_BSWAP_ODD | - BT848_COLOR_CTL_BSWAP_EVEN), - BT848_COLOR_CTL); - } else { - btwrite(0x10, BT848_COLOR_CTL); - } - hactive=width; - vtc=0; /* Some people say interpolation looks bad ... */ /* vtc = (hactive < 193) ? 2 : ((hactive < 385) ? 1 : 0); */ - btv->win.interlace = (height>btv->win.cropheight/2) ? 1 : 0; - inter=(btv->win.interlace&1)^1; - vdelay=btv->win.cropy+tvn->vdelay; + btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0; - xsf = (hactive*tvn->scaledtwidth)/btv->win.cropwidth; - hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - - hdelay=tvn->hdelayx1+btv->win.cropx; - hdelay=(hdelay*hactive)/btv->win.cropwidth; - hdelay&=0x3fe; + if (0 == btv->risc_cap_odd && + 0 == btv->risc_cap_even) { + /* overlay only */ + owidth = btv->win.width; + oheight = btv->win.height; + ewidth = btv->win.width; + eheight = btv->win.height; + format = btv->win.color_fmt; + bswap = btv->fb_color_ctl; + } else if (-1 != btv->gq_grab && + 0 == btv->risc_cap_odd && + !btv->win.interlace && + btv->scr_on) { + /* odd field -> overlay, even field -> capture */ + owidth = btv->win.width; + oheight = btv->win.height; + ewidth = btv->gbuf[btv->gq_grab].width; + eheight = btv->gbuf[btv->gq_grab].height; + format = (btv->win.color_fmt & 0xf0) | + (btv->gbuf[btv->gq_grab].fmt & 0x0f); + bswap = btv->fb_color_ctl & 0x0a; + } else { + /* capture only */ + owidth = btv->gbuf[btv->gq_grab].width; + oheight = btv->gbuf[btv->gq_grab].height; + ewidth = btv->gbuf[btv->gq_grab].width; + eheight = btv->gbuf[btv->gq_grab].height; + format = btv->gbuf[btv->gq_grab].fmt; + bswap = 0; + inter = (btv->win.height>tvn->sheight/2) ? 0 : 1; + } - sr=((btv->win.cropheight>>inter)*512)/height-512; + inter = (oheight>tvn->sheight/2) ? 0 : 1; + + /* odd field */ + hactive=owidth; + xsf = (hactive*tvn->scaledtwidth)/tvn->swidth; + hscale = ((tvn->totalwidth*4096UL)/xsf-4096); + hdelay = tvn->hdelayx1; + hdelay = (hdelay*hactive)/tvn->swidth; + hdelay &= 0x3fe; + sr=((tvn->sheight>>inter)*512)/oheight-512; + vscale=(0x10000UL-sr)&0x1fff; + crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)| + ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); + vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; + bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, tvn->sheight, + hdelay, tvn->vdelay, crop); + + /* even field */ + hactive=ewidth; + xsf = (hactive*tvn->scaledtwidth)/tvn->swidth; + hscale = ((tvn->totalwidth*4096UL)/xsf-4096); + hdelay = tvn->hdelayx1; + hdelay = (hdelay*hactive)/tvn->swidth; + hdelay &= 0x3fe; + sr=((tvn->sheight>>inter)*512)/eheight-512; vscale=(0x10000UL-sr)&0x1fff; - vactive=btv->win.cropheight; crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)| - ((vactive>>4)&0x30)|((vdelay>>2)&0xc0); - vscale|= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; + ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); + vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; + bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, tvn->sheight, + hdelay, tvn->vdelay, crop); - bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, vactive, - hdelay, vdelay, crop); - bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive, - hdelay, vdelay, crop); + btwrite(format, BT848_COLOR_FMT); + btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); restore_flags(flags); } -int bpp2fmt[4] = { +static int bpp2fmt[4] = { BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16, BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32 }; @@ -1569,14 +1806,31 @@ { unsigned short format; - if (btv->win.use_yuv) { - /* yuv-to-offscreen */ - format = BT848_COLOR_FMT_YUY2; + if (btv->picture.palette > 0 && btv->picture.palette <= VIDEO_PALETTE_YUV422) { + /* format set by VIDIOCSPICT */ + format = palette2fmt[btv->picture.palette]; } else { + /* use default for the given color depth */ format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 : bpp2fmt[(btv->win.bpp-1)&3]; } btv->win.color_fmt = format; + if (bigendian && + format == BT848_COLOR_FMT_RGB32) { + btv->fb_color_ctl = + BT848_COLOR_CTL_WSWAP_ODD | + BT848_COLOR_CTL_WSWAP_EVEN | + BT848_COLOR_CTL_BSWAP_ODD | + BT848_COLOR_CTL_BSWAP_EVEN; + } else if (bigendian && + (format == BT848_COLOR_FMT_RGB16 || + format == BT848_COLOR_FMT_RGB15)) { + btv->fb_color_ctl = + BT848_COLOR_CTL_BSWAP_ODD | + BT848_COLOR_CTL_BSWAP_EVEN; + } else { + btv->fb_color_ctl = 0; + } /* RGB8 seems to be a 9x5x5 GRB color cube starting at * color 16. Why the h... can't they even mention this in the @@ -1590,39 +1844,9 @@ else btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); - bt848_set_geo(btv, btv->win.width, btv->win.height, format,1); + bt848_set_geo(btv,1); } -/* - * Set TSA5522 synthesizer frequency in 1/16 Mhz steps - */ - -#if 0 -static void set_freq(struct bttv *btv, unsigned short freq) -{ - int naudio; - int fixme = freq; /* XXX */ - /* int oldAudio = btv->audio; */ - - /* mute */ - AUDIO(AUDC_SWITCH_MUTE,0); - - /* tune */ - if (btv->radio) { - TUNER(TUNER_SET_RADIOFREQ,&fixme); - } else { - TUNER(TUNER_SET_TVFREQ,&fixme); - } - - if (btv->radio) { - AUDIO(AUDC_SET_RADIO,0); - } else { - AUDIO(AUDC_SET_TVNORM,&(btv->win.norm)); - AUDIO(AUDC_NEWCHANNEL,0); - } -} -#endif - /* * Grab into virtual memory. @@ -1639,30 +1863,19 @@ if(fbuffer_alloc(btv)) return -ENOBUFS; } - if(btv->grabbing >= MAX_GBUFFERS) - return -ENOBUFS; - - /* - * No grabbing past the end of the buffer! - */ - - if(mp->frame>(MAX_GBUFFERS-1) || mp->frame <0) + + if(mp->frame >= gbuffers || mp->frame < 0) return -EINVAL; + if(btv->gbuf[mp->frame].stat != GBUFFER_UNUSED) + return -EBUSY; if(mp->height <0 || mp->width <0) return -EINVAL; - -/* This doesn´t work like this for NTSC anyway. - So, better check the total image size ... -*/ -/* - if(mp->height>576 || mp->width>768+BURSTOFFSET) - return -EINVAL; -*/ if (mp->format >= PALETTEFMT_MAX) return -EINVAL; + if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2 - > BTTV_MAX_FBUF) + > gbufsize) return -EINVAL; if(-1 == palette2fmt[mp->format]) return -EINVAL; @@ -1677,41 +1890,40 @@ * Ok load up the BT848 */ - vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame); -/* if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)) - return -EAGAIN;*/ - ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0); + vbuf=(unsigned int *)(btv->fbuffer+gbufsize*mp->frame); + ro=btv->gbuf[mp->frame].risc; re=ro+2048; make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); - /* bt848_set_risc_jmps(btv); */ + + if (debug) + printk("bttv%d: cap vgrab: queue %d\n",btv->nr,mp->frame); cli(); - btv->frame_stat[mp->frame] = GBUFFER_GRABBING; - if (btv->grabbing) { - btv->gfmt_next=palette2fmt[mp->format]; - btv->gwidth_next=mp->width; - btv->gheight_next=mp->height; - btv->gro_next=virt_to_bus(ro); - btv->gre_next=virt_to_bus(re); - btv->grf_next=mp->frame; - } else { - btv->gfmt=palette2fmt[mp->format]; - btv->gwidth=mp->width; - btv->gheight=mp->height; - btv->gro=virt_to_bus(ro); - btv->gre=virt_to_bus(re); - btv->grf=mp->frame; - } - if (!(btv->grabbing++)) { + btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; + btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; + btv->gbuf[mp->frame].width = mp->width; + btv->gbuf[mp->frame].height = mp->height; + btv->gbuf[mp->frame].ro = virt_to_bus(ro); + btv->gbuf[mp->frame].re = virt_to_bus(re); + +#if 1 + if (mp->height <= tvnorms[btv->win.norm].sheight/2 && + mp->format != VIDEO_PALETTE_RAW) + btv->gbuf[mp->frame].ro = 0; +#endif + + if (btv->gq_in == btv->gq_out) { 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]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); } + btv->gqueue[btv->gq_in++] = mp->frame; + btv->gq_in = btv->gq_in % MAX_GBUFFERS; + sti(); btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); - /* interruptible_sleep_on(&btv->capq); */ return 0; } @@ -1787,16 +1999,16 @@ if (btv->user) goto out_unlock; - btv->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS*BTTV_MAX_FBUF); + btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize); ret = -ENOMEM; if (!btv->fbuffer) goto out_unlock; - btv->grabbing = 0; - btv->grab = 0; - btv->lastgrab = 0; - for (i = 0; i < MAX_GBUFFERS; i++) - btv->frame_stat[i] = GBUFFER_UNUSED; + btv->gq_in = 0; + btv->gq_out = 0; + btv->gq_grab = -1; + for (i = 0; i < gbuffers; i++) + btv->gbuf[i].stat = GBUFFER_UNUSED; burst(0); btv->user++; @@ -1815,8 +2027,10 @@ down(&btv->lock); btv->user--; - btv->cap&=~3; - bt848_set_risc_jmps(btv); + btv->scr_on = 0; + btv->risc_cap_odd = 0; + btv->risc_cap_even = 0; + bt848_set_risc_jmps(btv,-1); /* * A word of warning. At this point the chip @@ -1841,7 +2055,7 @@ */ if(btv->fbuffer) - rvfree((void *) btv->fbuffer, MAX_GBUFFERS*BTTV_MAX_FBUF); + rvfree((void *) btv->fbuffer, gbuffers*gbufsize); btv->fbuffer=0; up(&btv->lock); MOD_DEC_USE_COUNT; @@ -1901,7 +2115,9 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct bttv *btv=(struct bttv *)dev; - int i; + int i,ret; + + if (debug) printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd); switch (cmd) { case VIDIOCGCAP: @@ -2021,17 +2237,6 @@ case VIDIOCGPICT: { struct video_picture p=btv->picture; - if(btv->win.depth==8) - p.palette=VIDEO_PALETTE_HI240; - if(btv->win.depth==15) - p.palette=VIDEO_PALETTE_RGB555; - if(btv->win.depth==16) - p.palette=VIDEO_PALETTE_RGB565; - if(btv->win.depth==24) - p.palette=VIDEO_PALETTE_RGB24; - if(btv->win.depth==32) - p.palette=VIDEO_PALETTE_RGB32; - if(copy_to_user(arg, &p, sizeof(p))) return -EFAULT; return 0; @@ -2041,6 +2246,8 @@ struct video_picture p; if(copy_from_user(&p, arg,sizeof(p))) return -EFAULT; + if (p.palette > PALETTEFMT_MAX) + return -EINVAL; down(&btv->lock); /* We want -128 to 127 we get 0-65535 */ bt848_bright(btv, (p.brightness>>8)-128); @@ -2059,7 +2266,6 @@ { struct video_window vw; struct video_clip *vcp = NULL; - int on; if(copy_from_user(&vw,arg,sizeof(vw))) return -EFAULT; @@ -2067,25 +2273,24 @@ if(vw.flags || vw.width < 16 || vw.height < 16) { down(&btv->lock); - bt848_cap(btv,0); + btv->scr_on = 0; + bt848_set_risc_jmps(btv,-1); up(&btv->lock); return -EINVAL; - } + } if (btv->win.bpp < 4) { /* adjust and align writes */ vw.x = (vw.x + 3) & ~3; vw.width &= ~3; } down(&btv->lock); - btv->win.use_yuv=0; btv->win.x=vw.x; btv->win.y=vw.y; btv->win.width=vw.width; btv->win.height=vw.height; - on=(btv->cap&3); - - bt848_cap(btv,0); + bt848_set_risc_jmps(btv,0); + bt848_set_winsize(btv); up(&btv->lock); @@ -2115,39 +2320,7 @@ make_clip_tab(btv, vcp, vw.clipcount); if (vw.clipcount != 0) vfree(vcp); - if(on && btv->win.vidadr!=0) - bt848_cap(btv,1); - up(&btv->lock); - return 0; - } - case VIDIOCSWIN2: - { - /* experimental -- right now it handles unclipped yuv data only */ - struct video_window2 vo; - __u32 fbsize; - int on; - - if(copy_from_user(&vo,arg,sizeof(vo))) - return -EFAULT; - - fbsize = btv->win.sheight * btv->win.bpl; - if (vo.start + vo.pitch*vo.height > fbsize) - return -EINVAL; - if (vo.palette != VIDEO_PALETTE_YUV422) - return -EINVAL; - - down(&btv->lock); - btv->win.use_yuv=1; - memcpy(&btv->win.win2,&vo,sizeof(vo)); - btv->win.width=vo.width; - btv->win.height=vo.height; - - on=(btv->cap&3); - bt848_cap(btv,0); - bt848_set_winsize(btv); - make_clip_tab(btv, NULL, 0); - if(on && btv->win.vidadr!=0) - bt848_cap(btv,1); + bt848_set_risc_jmps(btv,-1); up(&btv->lock); return 0; } @@ -2174,13 +2347,14 @@ return -EFAULT; if(btv->win.vidadr == 0) return -EINVAL; - if (0 == btv->win.use_yuv && (btv->win.width==0 || btv->win.height==0)) + if (btv->win.width==0 || btv->win.height==0) return -EINVAL; down(&btv->lock); - if(v==0) - bt848_cap(btv,0); - else - bt848_cap(btv,1); + if (v == 1 && btv->win.vidadr != 0) + btv->scr_on = 1; + if (v == 0) + btv->scr_on = 0; + bt848_set_risc_jmps(btv,-1); up(&btv->lock); return 0; } @@ -2217,9 +2391,19 @@ btv->win.bpp=((v.depth+7)&0x38)/8; btv->win.depth=v.depth; btv->win.bpl=v.bytesperline; - - DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", - v.base, v.width,v.height, btv->win.bpp, btv->win.bpl)); + + /* set sefault color format */ + switch (btv->win.bpp) { + case 8: btv->picture.palette = VIDEO_PALETTE_HI240; break; + case 15: btv->picture.palette = VIDEO_PALETTE_RGB555; break; + case 16: btv->picture.palette = VIDEO_PALETTE_RGB565; break; + case 24: btv->picture.palette = VIDEO_PALETTE_RGB24; break; + case 32: btv->picture.palette = VIDEO_PALETTE_RGB32; break; + } + + if (debug) + printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", + v.base, v.width,v.height, btv->win.bpp, btv->win.bpl); bt848_set_winsize(btv); up(&btv->lock); return 0; @@ -2273,19 +2457,6 @@ v.step = 4096; } -#if 0 -#warning this should be handled by tda9855.c - else if (btv->audio_chip == TDA9850) { - unsigned char ALR1; - v.flags|=VIDEO_AUDIO_VOLUME; - ALR1 = I2CRead(btv, I2C_TDA9850|1); - v.mode = VIDEO_SOUND_MONO; - v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0; - v.mode |= (ALR1 & 32) ? VIDEO_SOUND_LANG1:0; - v.volume = 32768; /* fixme */ - v.step = 4096; - } -#endif if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; @@ -2354,23 +2525,8 @@ udelay(10); data &= ~WINVIEW_PT2254_STROBE; btwrite(data, BT848_GPIO_DATA); - -#if 0 -#warning this should be handled by tda9855.c - } else 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_TDA9850, - TDA9850_CON3, con3, 1); - if (v.flags & VIDEO_AUDIO_VOLUME) - I2CWrite(btv, I2C_TDA9850, - TDA9850_CON4, - (v.volume>>12) & 15, 1); -#endif } + btv->audio_dev=v; up(&btv->lock); return 0; @@ -2379,19 +2535,27 @@ case VIDIOCSYNC: if(copy_from_user((void *)&i,arg,sizeof(int))) return -EFAULT; - switch (btv->frame_stat[i]) { + if (i < 0 || i >= gbuffers) + return -EINVAL; + switch (btv->gbuf[i].stat) { case GBUFFER_UNUSED: return -EINVAL; case GBUFFER_GRABBING: - while(btv->frame_stat[i]==GBUFFER_GRABBING) { + while(btv->gbuf[i].stat==GBUFFER_GRABBING) { + if (debug) + printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); interruptible_sleep_on(&btv->capq); if(signal_pending(current)) return -EINTR; } - /* fall */ + /* fall throuth */ case GBUFFER_DONE: - btv->frame_stat[i] = GBUFFER_UNUSED; - break; + case GBUFFER_ERROR: + ret = (btv->gbuf[i].stat == GBUFFER_ERROR) ? -EIO : 0; + if (debug) + printk("bttv%d: cap sync: buffer %d, retval %d\n",btv->nr,i,ret); + btv->gbuf[i].stat = GBUFFER_UNUSED; + return ret; } return 0; @@ -2422,8 +2586,6 @@ int ret; if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm))) return -EFAULT; - if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING) - return -EBUSY; down(&btv->lock); ret = vgrab(btv, &vm); up(&btv->lock); @@ -2434,10 +2596,10 @@ { struct video_mbuf vm; memset(&vm, 0 , sizeof(vm)); - vm.size=BTTV_MAX_FBUF*MAX_GBUFFERS; - vm.frames=MAX_GBUFFERS; - vm.offsets[0]=0; - vm.offsets[1]=BTTV_MAX_FBUF; + vm.size=gbufsize*gbuffers; + vm.frames=gbuffers; + for (i = 0; i < gbuffers; i++) + vm.offsets[i]=i*gbufsize; if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) return -EFAULT; return 0; @@ -2510,7 +2672,7 @@ unsigned long start=(unsigned long) adr; unsigned long page,pos; - if (size>2*BTTV_MAX_FBUF) + if (size>gbuffers*gbufsize) return -EINVAL; if (!btv->fbuffer) { if(fbuffer_alloc(btv)) @@ -2623,8 +2785,8 @@ down(&btv->lock); btv->vbip=VBIBUF_SIZE; - btv->cap|=0x0c; - bt848_set_risc_jmps(btv); + btv->vbi_on = 1; + bt848_set_risc_jmps(btv,-1); up(&btv->lock); MOD_INC_USE_COUNT; @@ -2636,8 +2798,8 @@ struct bttv *btv=(struct bttv *)(dev-2); down(&btv->lock); - btv->cap&=~0x0c; - bt848_set_risc_jmps(btv); + btv->vbi_on = 0; + bt848_set_risc_jmps(btv,-1); up(&btv->lock); MOD_DEC_USE_COUNT; @@ -2875,26 +3037,12 @@ 7a - external */ } - -#if 0 -#warning this should be handled by tda9855.c -static void init_tda9850(struct bttv *btv) -{ - I2CWrite(btv, I2C_TDA9850, TDA9850_CON1, 0x08, 1); /* noise threshold st */ - I2CWrite(btv, I2C_TDA9850, TDA9850_CON2, 0x08, 1); /* noise threshold sap */ - I2CWrite(btv, I2C_TDA9850, TDA9850_CON3, 0x40, 1); /* stereo mode */ - I2CWrite(btv, I2C_TDA9850, TDA9850_CON4, 0x07, 1); /* 0 dB input gain?*/ - I2CWrite(btv, I2C_TDA9850, TDA9850_ALI1, 0x10, 1); /* wideband alignment? */ - I2CWrite(btv, I2C_TDA9850, TDA9850_ALI2, 0x10, 1); /* spectral alignment? */ - I2CWrite(btv, I2C_TDA9850, TDA9850_ALI3, 0x03, 1); -} -#endif - /* Figure out card and tuner type */ static void idcard(int i) { struct bttv *btv = &bttvs[i]; + int type,eeprom = 0; btwrite(0, BT848_GPIO_OUT_EN); DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA))); @@ -2903,40 +3051,36 @@ if (card[i] >= 0 && card[i] < TVCARDS) btv->type=card[i]; - /* If we were asked to auto-detect, then do so! - Right now this will only recognize Miro, Hauppauge or STB - */ - if (btv->type == BTTV_UNKNOWN) - { - if (I2CRead(btv, I2C_HAUPEE, "eeprom")>=0) - { - if(btv->id>849) - btv->type=BTTV_HAUPPAUGE878; - else + /* If we were asked to auto-detect, then do so! */ + if (btv->type == BTTV_UNKNOWN) { + + /* many bt878 cards have a eeprom @ 0xa0 => read ID + and try to identify it */ + if (I2CRead(btv, I2C_HAUPEE, "eeprom") >= 0) { + eeprom = 0xa0; + readee(btv,eeprom_data,0xa0); + dump_eeprom(btv,0xa0); /* DEBUG */ + type = idcard_eeprom(btv); + if (-1 != type) { + btv->type = type; + } else if (btv->id <= 849) { + /* for unknown bt848, assume old Hauppauge */ btv->type=BTTV_HAUPPAUGE; + } + /* STB cards have a eeprom @ 0xae */ } else if (I2CRead(btv, I2C_STBEE, "eeprom")>=0) { btv->type=BTTV_STB; + } -#if 0 /* bad idea: 0xc0 is used for the tuner on _many_ boards */ - } else if (I2CRead(btv, I2C_VHX)>=0) { - btv->type=BTTV_VHX; -#endif - - } else { - if (I2CRead(btv, 0x80, "msp3400")>=0) /* check for msp34xx */ +#if 0 + /* check for msp34xx */ + if (I2CRead(btv, 0x80, "msp3400")>=0) btv->type = BTTV_MIROPRO; else - btv->type = BTTV_MIRO; - } - } - -#if 1 - /* DEBUG: dump eeprom content if available */ - if (I2CRead(btv, 0xa0, "eeprom")>=0) { - dump_eeprom(btv,0xa0); - } + btv->type = BTTV_MIRO; #endif + } /* print which board we have found */ printk(KERN_INFO "bttv%d: model: ",btv->nr); @@ -2955,8 +3099,12 @@ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; } if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) { - hauppauge_msp_reset(btv); + if (0xa0 != eeprom) { + eeprom = 0xa0; + readee(btv,eeprom_data,0xa0); + } hauppauge_eeprom(btv); + hauppauge_boot_msp34xx(btv); } if (btv->type == BTTV_MAXI) { /* PHILIPS FI1216MK2 tuner (PAL/SECAM) */ @@ -2973,7 +3121,11 @@ btv->type == BTTV_CONFERENCETV || btv->type == BTTV_PIXVIEWPLAYTV || btv->type == BTTV_AVERMEDIA98 || - btv->type == BTTV_MAGICTVIEW061) { + btv->type == BTTV_MAGICTVIEW061 || + btv->type == BTTV_CHRONOS_VS2 || + btv->type == BTTV_TYPHOON_TVIEW || + btv->type == BTTV_PXELVWPLTVPRO || + btv->type == BTTV_WINFAST2000) { btv->pll.pll_ifreq=28636363; btv->pll.pll_crystal=BT848_IFORM_XT0; } @@ -3005,7 +3157,7 @@ if (tvcards[btv->type].tda985x && I2CRead(btv, I2C_TDA9850, "TDA985x") >=0) { if (autoload) - request_module("tda9855"); + request_module("tda985x"); } if (tvcards[btv->type].tea63xx /* && @@ -3023,9 +3175,19 @@ } -static void bt848_set_risc_jmps(struct bttv *btv) +static void bt848_set_risc_jmps(struct bttv *btv, int flags) { - int flags=btv->cap; + if (-1 == flags) { + /* defaults */ + flags = 0; + if (btv->scr_on) + flags |= 0x03; + if (btv->vbi_on) + flags |= 0x0c; + } + + if (debug) printk("bttv%d: set_risc_jmp %08lx:", + btv->nr,virt_to_bus(btv->risc_jmp)); /* Sync to start of odd field */ btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC @@ -3034,17 +3196,27 @@ /* Jump to odd vbi sub */ btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20)); - if (flags&8) + if (flags&8) { + if (debug) printk(" ev=%08lx",virt_to_bus(btv->vbi_odd)); btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd)); - else + } else { + if (debug) printk(" -----------"); btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4)); + } /* Jump to odd sub */ btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20)); - if (flags&2) - btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_odd)); - else + if (0 != btv->risc_cap_odd) { + if (debug) printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd); + flags |= 3; + btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd); + } else if (flags&2) { + if (debug) printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd)); + btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_scr_odd)); + } else { + if (debug) printk(" -----------"); btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6)); + } /* Sync to start of even field */ @@ -3054,22 +3226,34 @@ /* Jump to even vbi sub */ btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP); - if (flags&4) + if (flags&4) { + if (debug) printk(" ov=%08lx",virt_to_bus(btv->vbi_even)); btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even)); - else + } else { + if (debug) printk(" -----------"); btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); + } /* Jump to even sub */ btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20)); - if (flags&1) - btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_even)); - else + if (0 != btv->risc_cap_even) { + if (debug) printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even); + flags |= 3; + btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even); + } else if (flags&1) { + if (debug) printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even)); + btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_scr_even)); + } else { + if (debug) printk(" -----------"); btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12)); + } btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp)); /* enable cpaturing and DMA */ + if (debug) printk(" flags=0x%x dma=%s\n", + flags,(flags&0x0f) ? "on" : "off"); btaor(flags, ~0x0f, BT848_CAP_CTL); if (flags&0x0f) bt848_dma(btv, 3); @@ -3114,15 +3298,14 @@ btv->user=0; init_MUTEX(&btv->lock); -#if 0 /* dump current state of the gpio registers before changing them, * might help to make a new card work */ - printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n", - i, - btread(BT848_GPIO_OUT_EN), - btread(BT848_GPIO_DATA), - btread(BT848_GPIO_REG_INP)); -#endif + if (verbose >= 2) + printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n", + i, + btread(BT848_GPIO_OUT_EN), + btread(BT848_GPIO_DATA), + btread(BT848_GPIO_REG_INP)); /* reset the bt848 */ btwrite(0, BT848_SRESET); @@ -3135,10 +3318,6 @@ btv->win.y=0; btv->win.width=768; /* 640 */ btv->win.height=576; /* 480 */ - btv->win.cropwidth=768; /* 640 */ - btv->win.cropheight=576; /* 480 */ - btv->win.cropx=0; - btv->win.cropy=0; btv->win.bpp=2; btv->win.depth=16; btv->win.color_fmt=BT848_COLOR_FMT_RGB16; @@ -3146,27 +3325,24 @@ btv->win.swidth=1024; btv->win.sheight=768; btv->win.vidadr=0; - btv->cap=0; + btv->vbi_on=0; + btv->scr_on=0; - btv->gmode=0; - btv->risc_odd=0; - btv->risc_even=0; + btv->risc_scr_odd=0; + btv->risc_scr_even=0; + btv->risc_cap_odd=0; + btv->risc_cap_even=0; btv->risc_jmp=0; btv->vbibuf=0; - btv->grisc=0; - btv->grabbing=0; - btv->grabcount=0; - btv->grab=0; - btv->lastgrab=0; btv->field=btv->last_field=0; /* i2c */ btv->tuner_type=-1; init_bttv_i2c(btv); - if (!(btv->risc_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) + if (!(btv->risc_scr_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) return -1; - if (!(btv->risc_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) + if (!(btv->risc_scr_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) return -1; if (!(btv->risc_jmp =(unsigned int *) kmalloc(2048, GFP_KERNEL))) return -1; @@ -3180,7 +3356,7 @@ btv->vbibuf=(unsigned char *) vmalloc(VBIBUF_SIZE); if (!btv->vbibuf) return -1; - if (!(btv->grisc=(unsigned int *) kmalloc(32768, GFP_KERNEL))) + if (!(btv->gbuf = kmalloc(sizeof(struct bttv_gbuf)*gbuffers, GFP_KERNEL))) return -1; memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random @@ -3194,7 +3370,14 @@ /* btwrite(0, BT848_TDEC); */ btwrite(0x10, BT848_COLOR_CTL); btwrite(0x00, BT848_CAP_CTL); - btwrite(0xac, BT848_GPIO_DMA_CTL); + /* set planar and packed mode trigger points and */ + /* set rising edge of inverted GPINTR pin as irq trigger */ + btwrite(BT848_GPIO_DMA_CTL_PKTP_32| + BT848_GPIO_DMA_CTL_PLTP1_16| + BT848_GPIO_DMA_CTL_PLTP23_16| + BT848_GPIO_DMA_CTL_GPINTC| + BT848_GPIO_DMA_CTL_GPINTI, + BT848_GPIO_DMA_CTL); /* select direct input */ btwrite(0x00, BT848_GPIO_REG_INP); @@ -3229,13 +3412,14 @@ /*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR| BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/ (fieldnr ? BT848_INT_VSYNC : 0)| + BT848_INT_GPINT| BT848_INT_SCERR| BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| BT848_INT_FMTCHG|BT848_INT_HLOCK, BT848_INT_MASK); make_vbitab(btv); - bt848_set_risc_jmps(btv); + bt848_set_risc_jmps(btv,-1); /* * Now add the template and register the device unit. @@ -3262,12 +3446,17 @@ if (!astat) return; btwrite(astat,BT848_INT_STAT); - IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat)); - IDEBUG(printk ("bttv%d: stat %08x\n", btv->nr, stat)); + IDEBUG(printk ("bttv%d: astat=%08x\n", btv->nr, astat)); + IDEBUG(printk ("bttv%d: stat=%08x\n", btv->nr, stat)); /* get device status bits */ dstat=btread(BT848_DSTATUS); + if (astat&BT848_INT_GPINT) { + IDEBUG(printk ("bttv%d: IRQ_GPINT\n", btv->nr)); + wake_up_interruptible(&btv->gpioq); + } + if (astat&BT848_INT_FMTCHG) { IDEBUG(printk ("bttv%d: IRQ_FMTCHG\n", btv->nr)); @@ -3283,13 +3472,21 @@ IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr)); btv->field++; } - if (astat&BT848_INT_SCERR) { - IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr)); - bt848_dma(btv, 0); - bt848_dma(btv, 1); + if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) { + printk("bttv%d: irq:%s%s risc_count=%08x\n",btv->nr, + (astat&BT848_INT_SCERR) ? " SCERR" : "", + (astat&BT848_INT_OCERR) ? " OCERR" : "", + btread(BT848_RISC_COUNT)); + bt848_set_risc_jmps(btv,0); + btwrite(0, BT848_SRESET); + btwrite(virt_to_bus(btv->risc_jmp), + BT848_RISC_STRT_ADD); + bt848_set_geo(btv,0); + bt848_set_risc_jmps(btv,-1); +#if 0 wake_up_interruptible(&btv->vbiq); wake_up_interruptible(&btv->capq); - +#endif } if (astat&BT848_INT_RISCI) { @@ -3307,41 +3504,48 @@ /* captured full frame */ if (stat&(2<<28)) { - /*wake_up_interruptible(&btv->capq);*/ btv->last_field=btv->field; - btv->grab++; - btv->frame_stat[btv->grf] = GBUFFER_DONE; - if ((--btv->grabbing)) + if (debug) + printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab); + btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE; + btv->gq_grab = -1; + if (btv->gq_in != btv->gq_out) { - btv->gfmt = btv->gfmt_next; - btv->gwidth = btv->gwidth_next; - btv->gheight = btv->gheight_next; - btv->gro = btv->gro_next; - btv->gre = btv->gre_next; - btv->grf = btv->grf_next; - btv->risc_jmp[5]=cpu_to_le32(btv->gro); - btv->risc_jmp[11]=cpu_to_le32(btv->gre); - bt848_set_geo(btv, btv->gwidth, - btv->gheight, - btv->gfmt,0); + btv->gq_grab = btv->gqueue[btv->gq_out++]; + btv->gq_out = btv->gq_out % MAX_GBUFFERS; + if (debug) + printk("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab); + btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; + btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; + bt848_set_risc_jmps(btv,-1); + bt848_set_geo(btv,0); + btwrite(BT848_COLOR_CTL_GAMMA, + BT848_COLOR_CTL); } else { - bt848_set_risc_jmps(btv); + btv->risc_cap_odd = 0; + btv->risc_cap_even = 0; + bt848_set_risc_jmps(btv,-1); 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,0); + bt848_set_geo(btv,0); + btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA, + BT848_COLOR_CTL); } wake_up_interruptible(&btv->capq); break; } if (stat&(8<<28)) { - btv->risc_jmp[5]=cpu_to_le32(btv->gro); - btv->risc_jmp[11]=cpu_to_le32(btv->gre); - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); - bt848_set_geo(btv, btv->gwidth, btv->gheight, - btv->gfmt,0); + btv->gq_grab = btv->gqueue[btv->gq_out++]; + btv->gq_out = btv->gq_out % MAX_GBUFFERS; + if (debug) + printk("bttv%d: cap irq: capture %d\n",btv->nr,btv->gq_grab); + btv->risc_cap_odd = btv->gbuf[btv->gq_grab].ro; + btv->risc_cap_even = btv->gbuf[btv->gq_grab].re; + bt848_set_risc_jmps(btv,-1); + bt848_set_geo(btv,0); + btwrite(BT848_COLOR_CTL_GAMMA, + BT848_COLOR_CTL); } } if (astat&BT848_INT_OCERR) @@ -3427,6 +3631,9 @@ init_waitqueue_head(&btv->capqe); btv->vbip=VBIBUF_SIZE; + init_waitqueue_head(&btv->gpioq); + btv->shutdown=0; + btv->id=dev->device; btv->irq=dev->irq; btv->bt848_adr=dev->resource[0].start; @@ -3551,8 +3758,10 @@ { btv=&bttvs[i]; - /* turn off all capturing, DMA and IRQs */ + /* unregister i2c_bus */ + i2c_bit_del_bus(&btv->i2c_adap); + /* turn off all capturing, DMA and IRQs */ btand(~15, BT848_GPIO_DMA_CTL); /* first disable interrupts before unmapping the memory! */ @@ -3560,9 +3769,6 @@ btwrite(0xffffffffUL,BT848_INT_STAT); btwrite(0x0, BT848_GPIO_OUT_EN); - /* unregister i2c_bus */ - i2c_bit_del_bus(&btv->i2c_adap); - /* disable PCI bus-mastering */ pci_read_config_byte(btv->dev, PCI_COMMAND, &command); /* Should this be &=~ ?? */ @@ -3570,14 +3776,14 @@ pci_write_config_byte(btv->dev, PCI_COMMAND, command); /* unmap and free memory */ - if (btv->grisc) - kfree((void *) btv->grisc); + if (btv->gbuf) + kfree((void *) btv->gbuf); - if (btv->risc_odd) - kfree((void *) btv->risc_odd); + if (btv->risc_scr_odd) + kfree((void *) btv->risc_scr_odd); - if (btv->risc_even) - kfree((void *) btv->risc_even); + if (btv->risc_scr_even) + kfree((void *) btv->risc_scr_even); DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp)); if (btv->risc_jmp) @@ -3599,6 +3805,13 @@ video_unregister_device(&btv->vbi_dev); if (radio[btv->nr] && btv->radio_dev.minor != -1) video_unregister_device(&btv->radio_dev); + + /* wake up any waiting processes + because shutdown flag is set, no new processes (in this queue) + are expected + */ + btv->shutdown=1; + wake_up(&btv->gpioq); } } @@ -3614,6 +3827,14 @@ (BTTV_VERSION_CODE >> 16) & 0xff, (BTTV_VERSION_CODE >> 8) & 0xff, BTTV_VERSION_CODE & 0xff); + if (gbuffers < 2 || gbuffers > MAX_GBUFFERS) + gbuffers = 2; + if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) + gbufsize = BTTV_MAX_FBUF; + if (verbose) + printk(KERN_INFO "bttv: using %d buffers with %dk (%dk total) for capture\n", + gbuffers,gbufsize/1024,gbuffers*gbufsize/1024); + handle_chipset(); if (find_bt848()<=0) return -EIO; --- linux-2.3.47/drivers/char/bttv.h Fri Feb 25 17:47:18 2000 +++ linux/drivers/char/bttv.h Fri Feb 25 17:59:21 2000 @@ -21,45 +21,67 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE 0x00070d +#define BTTV_VERSION_CODE 0x000714 #include #include +#include +#include +#include #include "audiochip.h" #include "bt848.h" +#define WAIT_QUEUE wait_queue_head_t -/* experimental, interface might change */ -#ifndef VIDIOCSWIN2 -#define VIDIOCSWIN2 _IOW('v',28,struct video_window2) -struct video_window2 -{ - __u16 palette; /* Palette (aka video format) in use */ - __u32 start; /* start address, relative to video_buffer.base */ - __u32 pitch; - __u32 width; - __u32 height; - __u32 flags; - - struct video_clip *clips; - int clipcount; -}; -#endif - +/* returns card type, + for possible values see lines below beginning with #define BTTV_UNKNOWN + returns negative value if error ocurred +*/ +extern int bttv_get_id(unsigned int card); + +/* sets GPOE register (BT848_GPIO_OUT_EN) to new value: + data | (current_GPOE_value & ~mask) + returns negative value if error ocurred +*/ +extern int bttv_gpio_enable(unsigned int card, + unsigned long mask, unsigned long data); + +/* fills data with GPDATA register contents + returns negative value if error ocurred +*/ +extern int bttv_read_gpio(unsigned int card, unsigned long *data); + +/* sets GPDATA register to new value: + (data & mask) | (current_GPDATA_value & ~mask) + returns negative value if error ocurred +*/ +extern int bttv_write_gpio(unsigned int card, + unsigned long mask, unsigned long data); + +/* returns pointer to task queue which can be used as parameter to + interruptible_sleep_on + in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated + (wake_up_interruptible) and following call to the function bttv_read_gpio + should return new value of GPDATA, + returns NULL value if error ocurred or queue is not available + WARNING: because there is no buffer for GPIO data, one MUST + process data ASAP +*/ +extern WAIT_QUEUE* bttv_get_gpio_queue(unsigned int card); -#define WAIT_QUEUE wait_queue_head_t #ifndef O_NONCAP #define O_NONCAP O_TRUNC #endif -#define MAX_GBUFFERS 2 +#define MAX_GBUFFERS 64 #define RISCMEM_LEN (32744*2) #define VBI_MAXLINES 16 #define VBIBUF_SIZE (2048*VBI_MAXLINES*2) #define BTTV_MAX_FBUF 0x208000 +#define I2C_CLIENTS_MAX 8 #ifdef __KERNEL__ @@ -69,17 +91,12 @@ ushort width, height; ushort bpp, bpl; ushort swidth, sheight; - short cropx, cropy; - ushort cropwidth, cropheight; unsigned long vidadr; ushort freq; int norm; int interlace; int color_fmt; ushort depth; - - int use_yuv; - struct video_window2 win2; }; struct bttv_pll_info { @@ -89,7 +106,21 @@ unsigned int pll_current; /* Currently programmed ofreq */ }; -#define I2C_CLIENTS_MAX 8 +struct bttv_gbuf { + int stat; +#define GBUFFER_UNUSED 0 +#define GBUFFER_GRABBING 1 +#define GBUFFER_DONE 2 +#define GBUFFER_ERROR 3 + + u16 width; + u16 height; + u16 fmt; + + u32 risc[4096]; + unsigned long ro; + unsigned long re; +}; struct bttv { @@ -125,6 +156,7 @@ unsigned char *vbibuf; struct bttv_window win; + int fb_color_ctl; int type; /* card type */ int audio; /* audio mode */ int audio_chip; /* set to one of the chips supported by bttv.c */ @@ -141,34 +173,18 @@ WAIT_QUEUE capqe; int vbip; - u32 *risc_odd; - u32 *risc_even; - int cap; + u32 *risc_scr_odd; + u32 *risc_scr_even; + u32 risc_cap_odd; + u32 risc_cap_even; + int scr_on; + int vbi_on; struct video_clip *cliprecs; - struct gbuffer *ogbuffers; - struct gbuffer *egbuffers; - u16 gwidth, gheight, gfmt; - u16 gwidth_next, gheight_next, gfmt_next; - u32 *grisc; - - unsigned long gro; - unsigned long gre; - unsigned long gro_next; - unsigned long gre_next; - - int grf,grf_next; /* frame numbers in grab queue */ - int frame_stat[MAX_GBUFFERS]; -#define GBUFFER_UNUSED 0 -#define GBUFFER_GRABBING 1 -#define GBUFFER_DONE 2 - + struct bttv_gbuf *gbuf; + int gqueue[MAX_GBUFFERS]; + int gq_in,gq_out,gq_grab; char *fbuffer; - int gmode; - int grabbing; - int lastgrab; - int grab; - int grabcount; struct bttv_pll_info pll; unsigned int Fsc; @@ -176,12 +192,12 @@ unsigned int last_field; /* number of last grabbed field */ int i2c_command; int triton1; + + WAIT_QUEUE gpioq; + int shutdown; }; #endif -/*The following should be done in more portable way. It depends on define - of _ALPHA_BTTV in the Makefile.*/ - #if defined(__powerpc__) /* big-endian */ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) { @@ -193,14 +209,9 @@ #define btwrite(dat,adr) io_st_le32((unsigned *)(btv->bt848_mem+(adr)),(dat)) #define btread(adr) ld_le32((unsigned *)(btv->bt848_mem+(adr))) #else -#ifdef _ALPHA_BTTV -#define btwrite(dat,adr) writel((dat),(char *) (btv->bt848_adr+(adr))) -#define btread(adr) readl(btv->bt848_adr+(adr)) -#else #define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mem+(adr))) #define btread(adr) readl(btv->bt848_mem+(adr)) #endif -#endif #define btand(dat,adr) btwrite((dat) & btread(adr), adr) #define btor(dat,adr) btwrite((dat) | btread(adr), adr) @@ -243,10 +254,19 @@ #define BTTV_PHOEBE_TVMAS 0x16 #define BTTV_MODTEC_205 0x17 #define BTTV_MAGICTVIEW061 0x18 - +#define BTTV_VOBIS_BOOSTAR 0x19 +#define BTTV_HAUPPAUG_WCAM 0x1a #define BTTV_MAXI 0x1b #define BTTV_TERRATV 0x1c #define BTTV_PXC200 0x1d +#define BTTV_FLYVIDEO_98 0x1e +#define BTTV_IPROTV 0x1f +#define BTTV_INTEL_C_S_PCI 0x20 +#define BTTV_TERRATVALUE 0x21 +#define BTTV_WINFAST2000 0x22 +#define BTTV_CHRONOS_VS2 0x23 +#define BTTV_TYPHOON_TVIEW 0x24 +#define BTTV_PXELVWPLTVPRO 0x25 #define AUDIO_TUNER 0x00 @@ -279,27 +299,6 @@ #define TDA9840_STADJ 0x03 #define TDA9840_TEST 0x04 -#define TDA9850_CON1 0x04 -#define TDA9850_CON2 0x05 -#define TDA9850_CON3 0x06 -#define TDA9850_CON4 0x07 -#define TDA9850_ALI1 0x08 -#define TDA9850_ALI2 0x09 -#define TDA9850_ALI3 0x0a - -#define TDA8425_VL 0x00 -#define TDA8425_VR 0x01 -#define TDA8425_BA 0x02 -#define TDA8425_TR 0x03 -#define TDA8425_S1 0x08 - -#define TEA6300_VL 0x00 /* volume control left */ -#define TEA6300_VR 0x01 /* volume control right */ -#define TEA6300_BA 0x02 /* bass control */ -#define TEA6300_TR 0x03 /* treble control */ -#define TEA6300_FA 0x04 /* fader control */ -#define TEA6300_SW 0x05 /* mute and source switch */ - #define PT2254_L_CHANEL 0x10 #define PT2254_R_CHANEL 0x08 #define PT2254_DBS_IN_2 0x400 @@ -309,3 +308,9 @@ #define WINVIEW_PT2254_STROBE 0x80 #endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.3.47/drivers/char/tuner.c Fri Feb 25 17:47:08 2000 +++ linux/drivers/char/tuner.c Fri Feb 25 17:59:21 2000 @@ -12,6 +12,7 @@ #include #include "tuner.h" +#include "audiochip.h" /* Addresses to scan */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; @@ -334,6 +335,9 @@ t->type,tuners[t->type].name); strncpy(client->name, tuners[t->type].name, sizeof(client->name)); break; + case AUDC_SET_RADIO: + t->radio = 1; + break; /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a @@ -342,6 +346,7 @@ { struct video_channel *vc = arg; + t->radio = 0; if (t->type == TUNER_PHILIPS_SECAM) { t->mode = (vc->norm == VIDEO_MODE_SECAM) ? 1 : 0; set_tv_freq(client,t->freq); --- linux-2.3.47/drivers/char/msp3400.c Fri Feb 25 17:47:58 2000 +++ linux/drivers/char/msp3400.c Fri Feb 25 17:59:21 2000 @@ -480,7 +480,7 @@ break; case VIDEO_SOUND_MONO: if (msp->mode == MSP_MODE_AM_NICAM) { - printk("msp3400: switching to AM mono\n"); + dprintk("msp3400: switching to AM mono\n"); /* AM mono decoding is handled by tuner, not MSP chip */ /* so let's redirect sound from tuner via SCART */ /* volume prescale for SCART */ @@ -723,7 +723,7 @@ /* some time for the tuner to sync */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + schedule_timeout(HZ/5); if (signal_pending(current)) goto done; @@ -750,13 +750,15 @@ msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/25); + schedule_timeout(HZ/10); if (signal_pending(current)) goto done; if (msp->restart) msp->restart = 0; val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); + if (val > 32768) + val -= 65536; if (val1 < val) val1 = val, max1 = this; dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name); @@ -785,13 +787,15 @@ msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/25); + schedule_timeout(HZ/10); if (signal_pending(current)) goto done; if (msp->restart) goto restart; val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); + if (val > 32768) + val -= 65536; if (val2 < val) val2 = val, max2 = this; dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name); @@ -974,7 +978,7 @@ /* some time for the tuner to sync */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + schedule_timeout(HZ/5); if (signal_pending(current)) goto done; @@ -1041,10 +1045,9 @@ for (i = 0; modelist[i].name != NULL; i++) if (modelist[i].retval == val) break; - if (debug) - printk("msp3410: current mode: %s (0x%04x)\n", - modelist[i].name ? modelist[i].name : "unknown", - val); + dprintk("msp3410: current mode: %s (0x%04x)\n", + modelist[i].name ? modelist[i].name : "unknown", + val); msp->main = modelist[i].main; msp->second = modelist[i].second; @@ -1242,6 +1245,7 @@ msp3400c_mixer_open(struct inode *inode, struct file *file) { int minor = MINOR(inode->i_rdev); + struct i2c_client *client; struct msp3400c *msp; int i; @@ -1249,12 +1253,17 @@ for (i = 0; i < MSP3400_MAX; i++) { msp = msps[i]->data; if (msp->mixer_num == minor) { - file->private_data = msps[i]; + client = msps[i]; + file->private_data = client; break; } } if (MSP3400_MAX == i) return -ENODEV; + + /* lock bttv in memory while the mixer is in use */ + if (client->adapter->inc_use) + client->adapter->inc_use(client->adapter); MOD_INC_USE_COUNT; return 0; @@ -1263,6 +1272,10 @@ static int msp3400c_mixer_release(struct inode *inode, struct file *file) { + struct i2c_client *client = file->private_data; + + if (client->adapter->inc_use) + client->adapter->inc_use(client->adapter); MOD_DEC_USE_COUNT; return 0; } @@ -1274,10 +1287,10 @@ } static struct file_operations msp3400c_mixer_fops = { - llseek: msp3400c_mixer_llseek, - ioctl: msp3400c_mixer_ioctl, - open: msp3400c_mixer_open, - release: msp3400c_mixer_release, + llseek: msp3400c_mixer_llseek, + ioctl: msp3400c_mixer_ioctl, + open: msp3400c_mixer_open, + release: msp3400c_mixer_release, }; #endif --- linux-2.3.47/drivers/char/tda985x.c Tue May 5 22:32:27 1998 +++ linux/drivers/char/tda985x.c Fri Feb 25 17:59:21 2000 @@ -0,0 +1,532 @@ +/* + * For the TDA9850 and TDA9855 chips + * (The TDA9855 is used on the Diamond DTV2000 and the TDA9850 is used + * on STB cards. Other cards probably use these chips as well.) + * This driver will not complain if used with any + * other i2c device with the same address. + * + * Copyright (c) 1999 Gerd Knorr + * TDA9850 code and TDA9855.c merger by Eric Sandeen (eric_sandeen@bigfoot.com) + * This code is placed under the terms of the GNU General Public License + * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) + * Which was based on tda8425.c by Greg Alexander (c) 1998 + * + * OPTIONS: + * debug - set to 1 if you'd like to see debug messages + * chip - set to 9850 or 9855 to select your chip (default 9855) + * + * TODO: + * Fix channel change bug - sound goes out when changeing channels, mute + * and unmote to fix. - Is this still here? + * Fine tune sound + * Get rest of capabilities into video_audio struct... + * + * Revision: 0.4 - check for correct chip= insmod value + * also cleaned up comments a bit + * Revision: 0.3 - took out extraneous tda985x_write in tda985x_command + * Revision: 0.2 - added insmod option chip= + * Revision: 0.1 - original version + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bttv.h" +#include "audiochip.h" + +MODULE_PARM(debug,"i"); +MODULE_PARM(chip,"i"); +MODULE_PARM_DESC(chip, "Type of chip to handle: 9850 or 9855"); + +static int debug = 0; /* insmod parameter */ +static int chip = 9855; /* insmod parameter */ + +/* Addresses to scan */ +#define I2C_TDA985x_L 0xb4 +#define I2C_TDA985x_H 0xb6 +static unsigned short normal_i2c[] = {I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = { + I2C_TDA985x_L >> 1, + I2C_TDA985x_H >> 1, + I2C_CLIENT_END}; +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + normal_i2c, normal_i2c_range, + probe, probe_range, + ignore, ignore_range, + force +}; + +/* This is a superset of the TDA9850 and TDA9855 members */ + +struct tda985x { + int addr; + int rvol, lvol; + int bass, treble, sub; + int c4, c5, c6, c7; + int a1, a2, a3; +}; + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define dprintk if (debug) printk + +/* The TDA9850 and TDA9855 are both made by Philips Semiconductor + * http://www.semiconductors.philips.com + * TDA9850: I2C-bus controlled BTSC stereo/SAP decoder + * TDA9855: I2C-bus controlled BTSC stereo/SAP decoder and audio processor + * + * The TDA9850 has more or less a subset of the functions that the TDA9855 + * has. As a result, we can re-use many of these defines. Anything with + * TDA9855 is specific to that chip, anything with TDA9850 is specific + * to that chip, and anything with TDA985x is valid for either. + * + * To complicate things further, the TDA9850 uses labels C1 through C4 + * for subaddresses 0x04 through 0x07, while the TDA9855 uses + * C1 through C3 for subadresses 0x05 through 0x07 - quite confusing. + * To help keep things straight, I have renamed the various C[1,4] labels + * to C[4,7] so that the numerical label matches the hex value of the + * subaddress for both chips. At least the A[1,3] labels line up. :) + */ + + /* subaddresses for TDA9855 */ +#define TDA9855_VR 0x00 /* Volume, right */ +#define TDA9855_VL 0x01 /* Volume, left */ +#define TDA9855_BA 0x02 /* Bass */ +#define TDA9855_TR 0x03 /* Treble */ +#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */ + + /* subaddresses for TDA9850 */ +#define TDA9850_C4 0x04 /* Control 1 for TDA9850 */ + + /* subaddesses for both chips */ +#define TDA985x_C5 0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */ +#define TDA985x_C6 0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */ +#define TDA985x_C7 0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */ +#define TDA985x_A1 0x08 /* Alignment 1 for both chips */ +#define TDA985x_A2 0x09 /* Alignment 2 for both chips */ +#define TDA985x_A3 0x0a /* Alignment 3 for both chips */ + + /* Masks for bits in TDA9855 subaddresses */ +/* 0x00 - VR in TDA9855 */ +/* 0x01 - VL in TDA9855 */ +/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f) + * in 1dB steps - mute is 0x27 */ + + +/* 0x02 - BA in TDA9855 */ +/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19) + * in .5dB steps - 0 is 0x0E */ + + +/* 0x03 - TR in TDA9855 */ +/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb) + * in 3dB steps - 0 is 0x7 */ + + /* Masks for bits in both chips' subaddresses */ +/* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */ +/* Unique to TDA9855: */ +/* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf) + * in 3dB steps - mute is 0x0 */ + +/* Unique to TDA9850: */ +/* lower 4 bits control stereo noise threshold, over which stereo turns off + * set to values of 0x00 through 0x0f for Ster1 through Ster16 */ + + +/* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/ +/* Unique to TDA9855: */ +#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */ +#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */ +#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ +#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ + /* Bits 0 to 3 select various combinations + * of line in and line out, only the + * interesting ones are defined */ +#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ +#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ + +/* Unique to TDA9850: */ +/* lower 4 bits contol SAP noise threshold, over which SAP turns off + * set to values of 0x00 through 0x0f for SAP1 through SAP16 */ + + +/* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */ +/* Common to TDA9855 and TDA9850: */ +#define TDA985x_SAP 3<<6 /* Selects SAP output, mute if not received */ +#define TDA985x_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */ +#define TDA985x_MONO 0 /* Forces Mono output */ +#define TDA985x_LMU 1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */ + +/* Unique to TDA9855: */ +#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */ +#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/ +#define TDA9855_LINEAR 0 /* Linear Stereo */ +#define TDA9855_PSEUDO 1 /* Pseudo Stereo */ +#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */ +#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */ +#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/ + + +/* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */ +/* Common to both TDA9855 and TDA9850: */ +/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF) + * in .5dB steps - 0dB is 0x7 */ + + +/* 0x08, 0x09 - A1 and A2 (read/write) */ +/* Common to both TDA9855 and TDA9850: */ +/* lower 5 bites are wideband and spectral expander alignment + * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */ +#define TDA985x_STP 1<<5 /* Stereo Pilot/detect (read-only) */ +#define TDA985x_SAPP 1<<6 /* SAP Pilot/detect (read-only) */ +#define TDA985x_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/ + + +/* 0x0a - A3 */ +/* Common to both TDA9855 and TDA9850: */ +/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1), + * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */ +#define TDA985x_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral */ + +/* Unique to TDA9855: */ +/* 2 bits << 5 control AVL attack time: 420ohm (0x0), 730ohm (0x2), + * 1200ohm (0x1), 2100ohm (0x3) */ + + +/* Begin code */ + +static int tda985x_write(struct i2c_client *client, int subaddr, int val) +{ + unsigned char buffer[2]; + dprintk("In tda985x_write\n"); + dprintk("Writing %d 0x%x\n", subaddr, val); + buffer[0] = subaddr; + buffer[1] = val; + if (2 != i2c_master_send(client,buffer,2)) { + printk(KERN_WARNING "tda985x: I/O error, trying (write %d 0x%x)\n", + subaddr, val); + return -1; + } + return 0; +} + +static int tda985x_read(struct i2c_client *client) +{ + unsigned char buffer; + dprintk("In tda985x_read\n"); + if (1 != i2c_master_recv(client,&buffer,1)) { + printk(KERN_WARNING "tda985x: I/O error, trying (read)\n"); + return -1; + } + dprintk("Read 0x%02x\n", buffer); + return buffer; +} + +static int tda985x_set(struct i2c_client *client) +{ + struct tda985x *t = client->data; + unsigned char buf[16]; + dprintk("In tda985x_set\n"); + + if (chip == 9855) + { + dprintk(KERN_INFO + "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + t->rvol,t->lvol,t->bass,t->treble,t->sub, + t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); + buf[0] = TDA9855_VR; + buf[1] = t->rvol; + buf[2] = t->lvol; + buf[3] = t->bass; + buf[4] = t->treble; + buf[5] = t->sub; + buf[6] = t->c5; + buf[7] = t->c6; + buf[8] = t->c7; + buf[9] = t->a1; + buf[10] = t->a2; + buf[11] = t->a3; + if (12 != i2c_master_send(client,buf,12)) { + printk(KERN_WARNING "tda9855: I/O error, trying tda985x_set\n"); + return -1; + } + } + + else if (chip == 9850) + { + dprintk(KERN_INFO + "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + t->c4,t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); + buf[0] = TDA9850_C4; + buf[1] = t->c4; + buf[2] = t->c5; + buf[3] = t->c6; + buf[4] = t->c7; + buf[5] = t->a1; + buf[6] = t->a2; + buf[7] = t->a3; + if (8 != i2c_master_send(client,buf,8)) { + printk(KERN_WARNING "tda9850: I/O error, trying tda985x_set\n"); + return -1; + } + } + + return 0; +} + +static void do_tda985x_init(struct i2c_client *client) +{ + struct tda985x *t = client->data; + dprintk("In tda985x_init\n"); + + if (chip == 9855) + { + printk("Using tda9855 options\n"); + t->rvol = 0x6f; /* 0dB */ + t->lvol = 0x6f; /* 0dB */ + t->bass = 0x0e; /* 0dB */ + t->treble = (0x07 << 1); /* 0dB */ + t->sub = 0x8 << 2; /* 0dB */ + t->c5 = TDA9855_MUTE | TDA9855_AVL | + TDA9855_LOUD | TDA9855_INT; + /* Set Mute, AVL, Loudness off, Internal sound */ + t->c6 = TDA985x_STEREO | TDA9855_LINEAR | + TDA9855_TZCM | TDA9855_VZCM; + /* Stereo linear mode, also wait til zero crossings */ + t->c7 = 0x07; /* 0dB input gain */ + } + + else if (chip == 9850) + { + printk("Using tda9850 options\n"); + t->c4 = 0x08; /* Set stereo noise thresh to nominal */ + t->c5 = 0x08; /* Set SAP noise threshold to nominal */ + t->c6 = TDA985x_STEREO; /* Select Stereo mode for decoder */ + t->c7 = 0x07; /* 0dB input gain */ + } + + /* The following is valid for both chip types */ + t->a1 = 0x10; /* Select nominal wideband expander */ + t->a2 = 0x10; /* Select nominal spectral expander and 30mV trigger */ + t->a3 = 0x3; /* Set: nominal timing current, 420ohm AVL attack */ + + tda985x_set(client); +} + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda985x_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tda985x *t; + struct i2c_client *client; + dprintk("In tda985x_attach\n"); + client = kmalloc(sizeof *client,GFP_KERNEL); + if (!client) + return -ENOMEM; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; + + client->data = t = kmalloc(sizeof *t,GFP_KERNEL); + if (!t) + return -ENOMEM; + memset(t,0,sizeof *t); + do_tda985x_init(client); + MOD_INC_USE_COUNT; + strcpy(client->name,"TDA985x"); + printk(KERN_INFO "tda985x: init\n"); + + i2c_attach_client(client); + return 0; +} + +static int tda985x_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tda985x_attach); + return 0; +} + +static int tda985x_detach(struct i2c_client *client) +{ + struct tda985x *t = client->data; + + do_tda985x_init(client); + i2c_detach_client(client); + + kfree(t); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int tda985x_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct tda985x *t = client->data; + dprintk("In tda985x_command...\n"); +#if 0 + __u16 *sarg = arg; +#endif + + switch (cmd) { + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + dprintk("VIDIOCGAUDIO\n"); + if (chip == 9855) + { + int left,right; + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; + + /* min is 0x27 max is 0x7f, vstep is 2e8 */ + left = (t->lvol-0x27)*0x2e8; + right = (t->rvol-0x27)*0x2e8; + va->volume=MAX(left,right); + va->balance=(32768*MIN(left,right))/ + (va->volume ? va->volume : 1); + va->balance=(leftbalance) : va->balance; + va->bass = (t->bass-0x6)*0xccc; /* min 0x6 max 0x19 */ + va->treble = ((t->treble>>1)-0x3)*0x1c71; + } + + /* Valid for both chips: */ + { + va->mode = ((TDA985x_STP | TDA985x_SAPP) & + tda985x_read(client)) >> 4; + /* Add mono mode regardless of SAP and stereo */ + /* Allows forced mono */ + va->mode |= VIDEO_SOUND_MONO; + } + + break; /* VIDIOCGAUDIO case */ + } + + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + dprintk("VIDEOCSAUDIO...\n"); + if (chip == 9855) + { + int left,right; + + left = (MIN(65536 - va->balance,32768) * + va->volume) / 32768; + right = (MIN(va->balance,32768) * + va->volume) / 32768; + t->lvol = left/0x2e8+0x27; + t->rvol = right/0x2e8+0x27; + t->bass = va->bass/0xccc+0x6; + t->treble = (va->treble/0x1c71+0x3)<<1; + tda985x_write(client,TDA9855_VL,t->lvol); + tda985x_write(client,TDA9855_VR,t->rvol); + tda985x_write(client,TDA9855_BA, t->bass); + tda985x_write(client,TDA9855_TR,t->treble); + } + + /* The following is valid for both chips */ + + switch (va->mode) { + case VIDEO_SOUND_MONO: + dprintk("VIDEO_SOUND_MONO\n"); + t->c6= TDA985x_MONO | (t->c6 & 0x3f); + tda985x_write(client,TDA985x_C6,t->c6); + break; + case VIDEO_SOUND_STEREO: + dprintk("VIDEO_SOUND_STEREO\n"); + t->c6= TDA985x_STEREO | (t->c6 & 0x3f); + tda985x_write(client,TDA985x_C6,t->c6); + break; + case VIDEO_SOUND_LANG1: + dprintk("VIDEO_SOUND_LANG1\n"); + t->c6= TDA985x_SAP | (t->c6 & 0x3f); + tda985x_write(client,TDA985x_C6,t->c6); + break; + } /* End of (va->mode) switch */ + + break; + + } /* end of VIDEOCSAUDIO case */ + + default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ + + /* nothing */ + dprintk("Default\n"); + + } /* end of (cmd) switch */ + + return 0; +} + + +static struct i2c_driver driver = { + "i2c tda985x driver", + I2C_DRIVERID_TDA9855, /* Get new one for TDA985x? */ + I2C_DF_NOTIFY, + tda985x_probe, + tda985x_detach, + tda985x_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tda985x_init(void) +#endif +{ + if ( (chip != 9850) && (chip != 9855) ) + { + printk(KERN_ERR "tda985x: chip parameter must be 9850 or 9855\n"); + return -EINVAL; + } + i2c_add_driver(&driver); + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + i2c_del_driver(&driver); +} +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ --- linux-2.3.47/Documentation/video4linux/bttv/README Fri Feb 25 17:47:18 2000 +++ linux/Documentation/video4linux/bttv/README Fri Feb 25 17:59:22 2000 @@ -12,6 +12,13 @@ kernel, download it from: http://www2.lm-sensors.nu/~lm78/download.html +You'll need at least these i2c config options for bttv: +CONFIG_I2C=m +CONFIG_I2C_ALGOBIT=m + +The latest bttv version is available here: + http://www.in-berlin.de/User/kraxel/v4l/ + You'll find Ralphs original (mostly outdated) documentation in the ralphs-doc subdirectory. --- linux-2.3.47/Documentation/video4linux/bttv/Insmod-options Fri Feb 25 17:47:15 2000 +++ linux/Documentation/video4linux/bttv/Insmod-options Fri Feb 25 17:59:22 2000 @@ -14,11 +14,19 @@ but this might also help with other chipsets bigendian=n Set the endianness of the gfx framebuffer. Default is native endian. - fieldnr=1 Count fields. Some TV descrambling software + fieldnr=0/1 Count fields. Some TV descrambling software needs this, for others it only generates - 50 useless IRQs/sec. + 50 useless IRQs/sec. default is 0 (off). autoload=0/1 autoload helper modules (tuner, audio). default is 1 (on). + verbose=0/1/2 verbose level (at insmod time, while looking at + the hardware). default is 1. + debug=0/1 debug messages (for capture). + default is 0 (off). + gbuffers=2-64 number of capture buffers for mmap'ed capture. + default is 2. + gbufsize=n size of capture buffers. default and + maximum value is 0x208000 (~2MB) remap, card, radio and pll accept up to four comma-separated arguments (for multiple boards). @@ -59,12 +67,12 @@ insmod args: debug=1 print some debug info to the syslog. -tda9855.o - The driver for the tda9855 audio chip. Afaik, only the - Diamond DTV2000 has this chip. +tda985x.o + The driver for the tda9850/55 audio chips. insmod args: debug=1 print some debug info to the syslog. + chip=9850/9855 set the chip type. tuner.o The tuner driver. You need this unless you want to use only --- linux-2.3.47/Documentation/video4linux/bttv/CARDLIST Fri Feb 25 17:47:18 2000 +++ linux/Documentation/video4linux/bttv/CARDLIST Fri Feb 25 17:59:22 2000 @@ -1,5 +1,5 @@ bttv.o - card=0 - unknown + card=0 - *** UNKNOWN *** card=1 - MIRO PCTV card=2 - Hauppauge old card=3 - STB @@ -33,6 +33,10 @@ card=31 - iProTV card=32 - Intel Create and Share PCI card=33 - Terratec TerraTValue + card=34 - Leadtek WinFast 2000 + card=35 - Chronos Video Shuttle II + card=36 - Typhoon TView TV/FM Tuner + card=37 - PixelView PlayTV pro tuner.o type=0 - Temic PAL --- linux-2.3.47/drivers/char/tda9855.c Fri Feb 25 17:47:18 2000 +++ linux/drivers/char/tda9855.c Tue May 5 22:32:27 1998 @@ -1,455 +0,0 @@ -/* - * For the TDA9855 chip (afaik, only the Diamond DTV2000 has this) - * This driver will not complain if used with a TDA9850 or any - * other i2c device with the same address. - * - * Copyright (c) 1999 Steve VanDeBogart (vandebo@uclink.berkeley.edu) - * This code is placed under the terms of the GNU General Public License - * Based on tda8425.c by Greg Alexander (c) 1998 - * - * TODO: - * Fix channel change bug - sound goes out when changeing channels, mute - * and unmote to fix. - * Fine tune sound - * Get rest of capabilities into video_audio struct... - * - * Revision: 0.1 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ - -/* Addresses to scan */ -#define I2C_TDA9855_L 0xb4 -#define I2C_TDA9855_H 0xb6 -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = { - I2C_TDA9855_L >> 1, - I2C_TDA9855_H >> 1, - I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -struct tda9855 { - int addr; - int rvol, lvol; - int bass, treble, sub; - int c1, c2, c3; - int a1, a2, a3; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - - -#define dprintk if (debug) printk - - /* subaddresses */ -#define TDA9855_VR 0x00 /* Volume, right */ -#define TDA9855_VL 0x01 /* Volume, left */ -#define TDA9855_BA 0x02 /* Bass */ -#define TDA9855_TR 0x03 /* Treble */ -#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */ -#define TDA9855_C1 0x05 /* Control 1 */ -#define TDA9855_C2 0x06 /* Control 2 */ -#define TDA9855_C3 0x07 /* Control 3 */ -#define TDA9855_A1 0x08 /* Alignmnet 1*/ -#define TDA9855_A2 0x09 /* Alignmnet 2*/ -#define TDA9855_A3 0x0a /* Alignmnet 3*/ - /* Masks for bits in subaddresses */ -/* VR */ /* VL */ -/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f) - * in 1dB steps - mute is 0x27 */ - -/* BA */ -/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19) - * in .5dB steps - 0 is 0x0E */ - -/* TR */ -/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb) - * in 3dB steps - 0 is 0x7 */ - -/* SW */ -/* 4 bits << 2 control subwoofer/surraound gain from -14db (0x1) to 14db (0xf) - * in 3dB steps - mute is 0x0 */ - -/* C1 */ -#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */ -#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */ -#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ -#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ - /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ -#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ -#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ - -/* C2 */ -#define TDA9855_SAP 3<<6 /* Selects SAP output, mute if not received */ -#define TDA9855_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */ -#define TDA9855_MONO 0 /* Forces Mono output */ -#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */ -#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/ -#define TDA9855_LMU 1<<3 /* Mute at LOR and LOL */ -#define TDA9855_LINEAR 0 /* Linear Stereo */ -#define TDA9855_PSEUDO 1 /* Pseudo Stereo */ -#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */ -#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */ -#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/ - -/* C3 */ -/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF) - * in .5dB steps - 0 is 0x7 */ - -/* A1 and A2 (read/write) */ -/* lower 5 bites are wideband and spectral expander alignment - * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */ -#define TDA9855_STP 1<<5 /* Stereo Pilot/detect (read-only) */ -#define TDA9855_SAPP 1<<6 /* SAP Pilot/detect (read-only) */ -#define TDA9855_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/ - -/* A3 */ -/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1), - * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */ -/* 2 bits << 5 control AVL attack time: 420ohm (0x0), 730ohm (0x2), - * 1200ohm (0x1), 2100ohm (0x3) */ -#define TDA9855_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral) */ - - -/* Begin code */ - -static int tda9855_write(struct i2c_client *client, int subaddr, int val) -{ - unsigned char buffer[2]; - - buffer[0] = subaddr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda9855: I/O error, trying (write %d 0x%x)\n", - subaddr, val); - return -1; - } - return 0; -} - -static int tda9855_read(struct i2c_client *client) -{ - unsigned char buffer; - - if (1 != i2c_master_recv(client,&buffer,1)) { - printk(KERN_WARNING "tda9855: I/O error, trying (read)\n"); - return -1; - } - return buffer; -} - -static int tda9855_set(struct i2c_client *client) -{ - struct tda9855 *t = client->data; - unsigned char buf[16]; - - dprintk(KERN_INFO "tda9855_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",t->rvol,t->lvol,t->bass,t->treble,t->sub, - t->c1,t->c2,t->c3,t->a1,t->a2,t->a3); - buf[0] = TDA9855_VR; - buf[1] = t->rvol; - buf[2] = t->lvol; - buf[3] = t->bass; - buf[4] = t->treble; - buf[5] = t->sub; - buf[6] = t->c1; - buf[7] = t->c2; - buf[8] = t->c3; - buf[9] = t->a1; - buf[10] = t->a2; - buf[11] = t->a3; - if (12 != i2c_master_send(client,buf,12)) { - printk(KERN_WARNING "tda9855: I/O error, trying tda9855_set\n"); - return -1; - } - return 0; -} - -static void do_tda9855_init(struct i2c_client *client) -{ - struct tda9855 *t = client->data; - - t->rvol=0x6f; /* 0dB */ - t->lvol=0x6f; /* 0dB */ - t->bass=0x0e; /* 0dB */ - t->treble=(0x07 << 1); /* 0dB */ - t->sub=0x8 << 2; /* 0dB */ - t->c1=TDA9855_MUTE | TDA9855_AVL | TDA9855_LOUD | TDA9855_INT; - /* Set Mute, AVL, Loudness off, Internal sound */ - t->c2=TDA9855_STEREO | TDA9855_LINEAR; /* Set Stereo liner mode */ - t->c3=0x07; /* 0dB input gain */ - t->a1=0x10; /* Select nominal wideband expander */ - t->a2=0x10; /* Select nominal spectral expander and 30mV trigger */ - t->a3=0x3; /* Set: nominal timinig current, 420ohm AVL attack */ - tda9855_write(client, TDA9855_C1, TDA9855_MUTE); /* mute */ - tda9855_set(client); -} - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda9855_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda9855 *t; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) - return -ENOMEM; - memset(t,0,sizeof *t); - do_tda9855_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA9855"); - printk(KERN_INFO "tda9855: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda9855_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda9855_attach); - return 0; -} - -static int tda9855_detach(struct i2c_client *client) -{ - struct tda9855 *t = client->data; - - do_tda9855_init(client); - i2c_detach_client(client); - - kfree(t); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda9855_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda9855 *t = client->data; -#if 0 - __u16 *sarg = arg; -#endif - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - int left,right; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - - /* min is 0x27 max is 0x7f, vstep is 2e8 */ - left = (t->lvol-0x27)*0x2e8; - right = (t->rvol-0x27)*0x2e8; - va->volume=MAX(left,right); - va->balance=(32768*MIN(left,right))/ - (va->volume ? va->volume : 1); - va->balance=(leftbalance) : va->balance; - va->bass = (t->bass-0x6)*0xccc; /* min 0x6 max is 0x19 */ - va->treble = ((t->treble>>1)-0x3)*0x1c71; - - va->mode = ((TDA9855_STP | TDA9855_SAPP) & - tda9855_read(client)) >> 4; - va->mode |= VIDEO_SOUND_MONO; - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - int left,right; - - left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - right = (MIN(va->balance,32768) * - va->volume) / 32768; - t->lvol = left/0x2e8+0x27; - t->rvol = right/0x2e8+0x27; - t->bass = va->bass/0xccc+0x6; - t->treble = (va->treble/0x1c71+0x3)<<1; - tda9855_write(client,TDA9855_VL,t->lvol); - tda9855_write(client,TDA9855_VR,t->rvol); - tda9855_write(client,TDA9855_BA, t->bass); - tda9855_write(client,TDA9855_TR,t->treble); - - switch (va->mode) { - case VIDEO_SOUND_MONO: - t->c2= TDA9855_MONO | (t->c2 & 0x3f); - break; - case VIDEO_SOUND_STEREO: - t->c2= TDA9855_STEREO | (t->c2 & 0x3f); - break; - case VIDEO_SOUND_LANG1: - t->c2= TDA9855_SAP | (t->c2 & 0x3f); - break; - } - tda9855_write(client,TDA9855_C2,t->c2); - break; - } - -#if 0 - /* --- old, obsolete interface --- */ - case AUDC_GET_VOLUME_LEFT: - *sarg = (t->lvol-0x27)*0x2e8; /* min is 0x27 max is 0x7f, vstep is 2e8 */ - break; - case AUDC_GET_VOLUME_RIGHT: - *sarg = (t->rvol-0x27)*0x2e8; - break; - case AUDC_SET_VOLUME_LEFT: - t->lvol = *sarg/0x2e8+0x27; - break; - case AUDC_SET_VOLUME_RIGHT: - t->rvol = *sarg/0x2e8+0x27; - break; - case AUDC_GET_BASS: - *sarg = (t->bass-0x6)*0xccc; /* min 0x6 max is 0x19 */ - break; - case AUDC_SET_BASS: - t->bass = *sarg/0xccc+0x6; - tda9855_write(client,TDA9855_BA, t->bass); - break; - case AUDC_GET_TREBLE: - *sarg = ((t->treble>>1)-0x3)*0x1c71; - break; - case AUDC_SET_TREBLE: - t->treble = (*sarg/0x1c71+0x3)<<1; - tda9855_write(client,TDA9855_TR,t->treble); - break; - case AUDC_GET_STEREO: - *sarg = ((TDA9855_STP | TDA9855_SAPP) & - tda9855_read(client)) >> 4; - if(*sarg==0) *sarg=VIDEO_SOUND_MONO; - break; - case AUDC_SET_STEREO: - if(*sarg==VIDEO_SOUND_MONO) - t->c2= TDA9855_MONO | (t->c2 & 0x3f); - /* Mask out the sap and stereo bits and set mono */ - else if(*sarg==VIDEO_SOUND_STEREO) - t->c2= TDA9855_STEREO | (t->c2 & 0x3f); - /* Mask out the sap and stereo bits and set stereo */ - else if(*sarg==VIDEO_SOUND_LANG2) - t->c2= TDA9855_SAP | (t->c2 & 0x3f); - /* Mask out the sap and stereo bits and set sap */ - tda9855_write(client,TDA9855_C2,t->c2); - break; - case AUDC_SET_INPUT: - dprintk(KERN_INFO "tda9855: SET_INPUT with 0x%04x\n",*sarg); - if((*sarg & (AUDIO_MUTE | AUDIO_OFF))!=0) - t->c1|=TDA9855_MUTE; - else - t->c1= t->c1 & 0x7f; /* won't work --> (~TDA9855_MUTE); */ - if((*sarg & AUDIO_INTERN) == AUDIO_INTERN) - t->c1=(t->c1 & ~0x7) | TDA9855_INT; /* 0x7 is a mask for the int/ext */ - if((*sarg & AUDIO_EXTERN) == AUDIO_EXTERN) - t->c1=(t->c1 & ~0x7) | TDA9855_EXT; /* 0x7 is a mask for the int/ext */ - tda9855_write(client,TDA9855_C1,t->c1); - break; - case AUDC_SWITCH_MUTE: - if((t->c1 & ~TDA9855_MUTE) == 0) - t->c1|=TDA9855_MUTE; - else - t->c1&=~TDA9855_MUTE; - tda9855_write(client,TDA9855_C1,t->c1); - break; - -/* TDA9855 unsupported: */ -/* case AUDC_NEWCHANNEL: - case AUDC_SET_RADIO: - case AUDC_GET_DC: -*/ -#endif - default: - /* nothing */ - } - return 0; -} - - -static struct i2c_driver driver = { - "i2c tda9855 driver", - I2C_DRIVERID_TDA9855, - I2C_DF_NOTIFY, - tda9855_probe, - tda9855_detach, - tda9855_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda9855_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ --- 2.3.47/drivers/char/Config.in.orig Wed Feb 23 20:06:11 2000 +++ linux/drivers/char/Config.in Tue Feb 22 23:01:35 2000 @@ -178,7 +178,9 @@ hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c fi comment 'Video Adapters' - dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI + if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then + dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT + fi dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate ' Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT --- 2.3.47/drivers/char/Makefile.orig Wed Feb 23 20:06:02 2000 +++ linux/drivers/char/Makefile Tue Feb 22 22:51:31 2000 @@ -38,7 +38,7 @@ export-objs := busmouse.o console.o i2c-old.o keyboard.o sysrq.o \ misc.o pty.o random.o selection.o serial.o videodev.o \ - tty_io.o + tty_io.o bttv.o KEYMAP =defkeymap.o KEYBD =pc_keyb.o @@ -166,13 +166,11 @@ endif endif -obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda9855.o tea6300.o +obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda985x.o tea6300.o ifeq ($(CONFIG_VIDEO_BT848),y) -L_I2C=y L_TUNERS=y else ifeq ($(CONFIG_VIDEO_BT848),m) - L_I2C=m L_TUNERS=m endif endif