From: Gerd Knorr bttv driver update. Changes: (1) Added a new, sysfs-based interface to allow access to the bt878 gpio lines from other kernel modules (new bttv-gpio.c file), which fixes alot of problems the old interface has (which still is in bttv-if.c, to be removed in 2.7). (2) moved the i2c code from bttv-if.c to bttv-i2c.c. (3) created a new "struct bttv_core" and moved some of the entries from "struct bttv" to the new one. This is needed for (1) and makes the patch pretty big, althrough there is no actual code changes. (4) first cut for suspend support (S1 works for me). (5) usual batch of new/updated tv card list entries. (6) minor fixes. --- drivers/media/video/Makefile | 2 drivers/media/video/bt848.h | 3 drivers/media/video/bttv-cards.c | 582 ++++++++++++++++++++++++-------------- drivers/media/video/bttv-driver.c | 468 ++++++++++++++++++++---------- drivers/media/video/bttv-gpio.c | 183 +++++++++++ drivers/media/video/bttv-i2c.c | 471 ++++++++++++++++++++++++++++++ drivers/media/video/bttv-if.c | 447 ----------------------------- drivers/media/video/bttv-risc.c | 43 +- drivers/media/video/bttv-vbi.c | 4 drivers/media/video/bttv.h | 66 ++++ drivers/media/video/bttvp.h | 51 ++- 11 files changed, 1464 insertions(+), 856 deletions(-) diff -puN drivers/media/video/bt848.h~v4l-04-bttv-driver-update drivers/media/video/bt848.h --- 25/drivers/media/video/bt848.h~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bt848.h 2004-01-15 08:27:42.000000000 -0800 @@ -158,6 +158,9 @@ #define BT848_ADC_C_SLEEP (1<<1) #define BT848_ADC_CRUSH (1<<0) +#define BT848_WC_UP 0x044 +#define BT848_WC_DOWN 0x078 + #define BT848_E_VTC 0x06C #define BT848_O_VTC 0x0EC #define BT848_VTC_HSFMT (1<<7) diff -puN drivers/media/video/bttv-cards.c~v4l-04-bttv-driver-update drivers/media/video/bttv-cards.c --- 25/drivers/media/video/bttv-cards.c~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttv-cards.c 2004-01-15 08:27:42.000000000 -0800 @@ -53,6 +53,8 @@ static void winview_audio(struct bttv *b static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set); static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set); +static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, + int set); static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set); @@ -64,6 +66,7 @@ static void rv605_muxsel(struct bttv *bt static void eagle_muxsel(struct bttv *btv, unsigned int input); static void xguard_muxsel(struct bttv *btv, unsigned int input); static void ivc120_muxsel(struct bttv *btv, unsigned int input); +static void gvc1100_muxsel(struct bttv *btv, unsigned int input); static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); @@ -77,10 +80,11 @@ static unsigned int vsfx=0; static unsigned int latency = UNSET; unsigned int no_overlay=-1; -static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET}; -static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET}; -static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET}; -static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET}; +static unsigned int card[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; #ifdef MODULE static unsigned int autoload = 1; #else @@ -108,6 +112,10 @@ MODULE_PARM(tuner,"1-" __stringify(BTTV_ MODULE_PARM_DESC(tuner,"specify installed tuner type"); MODULE_PARM(autoload,"i"); MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); + +MODULE_PARM(svhs,"1-" __stringify(BTTV_MAX) "i"); +MODULE_PARM(remote,"1-" __stringify(BTTV_MAX) "i"); + MODULE_PARM(gpiomask,"i"); MODULE_PARM(audioall,"i"); MODULE_PARM(audiomux,"1-5i"); @@ -155,12 +163,13 @@ static struct CARD { { 0x00031002, BTTV_ATI_TVWONDERVE,"ATI TV Wonder/VE" }, { 0x6606107d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x6607107d, BTTV_WINFAST2000, "Leadtek WinFast VC 100" }, + { 0x6607107d, BTTV_WINFASTVC100, "Leadtek WinFast VC 100" }, { 0x263610b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x264510b4, BTTV_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, { 0x405010fc, BTTV_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, { 0x407010fc, BTTV_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + { 0xd01810fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, { 0x001211bd, BTTV_PINNACLE, "Pinnacle PCTV" }, { 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" }, @@ -175,16 +184,15 @@ static struct CARD { { 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" }, { 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" }, { 0x5000144f, BTTV_MAGICTVIEW061, "Askey CPH050" }, - + { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, + { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" }, + { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, { 0x00021461, BTTV_AVERMEDIA98, "AVermedia TVCapture 98" }, { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, { 0x00041461, BTTV_AVERMEDIA98, "AVerMedia TVCapture 98" }, { 0x03001461, BTTV_AVERMEDIA98, "VDOMATE TV TUNER CARD" }, - { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, - { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master (CPH060)" }, - { 0x1117153b, BTTV_TERRATVALUE, "Terratec TValue (Philips PAL B/G)" }, { 0x1118153b, BTTV_TERRATVALUE, "Terratec TValue (Temic PAL B/G)" }, { 0x1119153b, BTTV_TERRATVALUE, "Terratec TValue (Philips PAL I)" }, @@ -253,16 +261,27 @@ static struct CARD { { 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, { 0x18511851, BTTV_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, + { 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0xfff6f6ff, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0x03116000, BTTV_SENSORAY311, "Sensoray 311" }, { 0x00790e11, BTTV_WINDVR, "Canopus WinDVR PCI" }, { 0xa0fca1a0, BTTV_ZOLTRIX, "Face to Face Tvmax" }, - { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x20007063, BTTV_PC_HDTV, "pcHDTV HD-2000 TV"}, + { 0x82b2aa6a, BTTV_SIMUS_GVC1100, "SIMUS GVC1100" }, + + { 0x40111554, BTTV_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, + { 0x17de0a01, BTTV_KWORLD, "Mecer TV/FM/Video Tuner" }, // likely broken, vendor id doesn't match the other magic views ... //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, + // DVB cards (using pci function .1 for mpeg data xfer) + { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, + { 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, + { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" }, + { 0, -1, NULL } }; @@ -352,6 +371,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .tuner_type = -1, .audio_hook = avermedia_tvphone_audio, + .has_remote = 1, },{ .name = "MATRIX-Vision MV-Delta", .video_inputs = 5, @@ -438,6 +458,7 @@ struct tvcard bttv_tvcards[] = { .msp34xx_alt = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, + .audio_hook = avermedia_tv_stereo_audio, },{ .name = "Aimslab Video Highway Xtreme (VHX)", .video_inputs = 3, @@ -471,7 +492,13 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0x01fe00, .muxsel = { 2, 3, 1, 1}, +#if 0 + // old .audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }, +#else + // 2003-10-20 by "Anton A. Arapov" + .audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 }, +#endif .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1, @@ -733,6 +760,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .tuner_type = 5, // default for now, gpio reads BFFF06 for Pal bg+dk .audio_hook = winfast2000_audio, + .has_remote = 1, },{ .name = "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II", .video_inputs = 4, @@ -988,7 +1016,7 @@ struct tvcard bttv_tvcards[] = { /* Claas Langbehn , Sven Grothklags */ .name = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS", - .video_inputs = 3, + .video_inputs = 4, .audio_inputs = 3, .tuner = 0, .svhs = 2, @@ -997,7 +1025,7 @@ struct tvcard bttv_tvcards[] = { .audiomux = { 0, 0, 0x10, 8, 4 }, .needs_tvaudio = 1, .pll = PLL_28, - .tuner_type = TUNER_PHILIPS_PAL_I, + .tuner_type = TUNER_PHILIPS_PAL, .has_radio = 1, },{ /* Tim Röstermundt @@ -1248,6 +1276,7 @@ struct tvcard bttv_tvcards[] = { .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = 25, + .has_remote = 1, /* GPIO wiring: GPIO0: U4.A0 (hef4052bt) GPIO1: U4.A1 @@ -1283,6 +1312,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = 5, .audio_hook = pvbt878p9b_audio, // Note: not all cards have stereo .has_radio = 1, // Note: not all cards have radio + .has_remote = 1, /* GPIO wiring: GPIO0: A0 hef4052 GPIO1: A1 hef4052 @@ -1751,7 +1781,8 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .pll = PLL_28, .tuner_type = -1, - .no_video = 1, + .has_dvb = 1, + .no_gpioirq = 1, },{ /* Jorge Boncompte - DTI2 */ .name = "ProVideo PV143", @@ -1850,6 +1881,86 @@ struct tvcard bttv_tvcards[] = { 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }, .muxsel_hook = ivc120_muxsel, .pll = PLL_28, +},{ + + /* ---- card 0x70 ---------------------------------- */ + .name = "pcHDTV HD-2000 TV", + .video_inputs = 4, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .muxsel = { 2, 3, 1, 0}, + .tuner_type = TUNER_PHILIPS_ATSC, +},{ + .name = "Twinhan DST + clones", + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = TUNER_ABSENT, + .no_video = 1, + .has_dvb = 1, +},{ + .name = "Winfast VC100", + .video_inputs = 3, + .audio_inputs = 0, + .svhs = 1, + .tuner = -1, // no tuner + .muxsel = { 3, 1, 1, 3}, // Vid In, SVid In, Vid over SVid in connector + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .tuner_type = TUNER_ABSENT, + .no_video = 1, + .pll = PLL_28, +},{ + .name = "Teppro TEV-560/InterVision IV-560", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 3, + .muxsel = { 2, 3, 1, 1}, + .audiomux = { 1, 1, 1, 1, 0}, + .needs_tvaudio = 1, + .tuner_type = TUNER_PHILIPS_PAL, + .pll = PLL_35, +},{ + + /* ---- card 0x74 ---------------------------------- */ + .name = "SIMUS GVC1100", + .video_inputs = 4, + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .tuner_type = -1, + .pll = PLL_28, + .muxsel = { 2, 2, 2, 2}, + .gpiomask = 0x3F, + .muxsel_hook = gvc1100_muxsel, +},{ + /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */ + .name = "NGS NGSTV+", + .video_inputs = 3, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = {2, 3, 0, 0}, + .audiomux = {0, 0, 0, 0, 0x000003, 0}, + .pll = PLL_28, + .tuner_type = TUNER_PHILIPS_PAL, + .has_remote = 1, +},{ + /* http://linuxmedialabs.com */ + .name = "LMLBT4", + .video_inputs = 4, /* IN1,IN2,IN3,IN4 */ + .audio_inputs = 0, + .tuner = -1, + .svhs = -1, + .muxsel = { 2, 3, 1, 0 }, + .no_msp34xx = 1, + .no_tda9875 = 1, + .no_tda7432 = 1, + .needs_tvaudio = 0, }}; const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -1868,9 +1979,9 @@ void __devinit bttv_idcard(struct bttv * unsigned short tmp; /* read PCI subsystem ID */ - pci_read_config_word(btv->dev, PCI_SUBSYSTEM_ID, &tmp); + pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_ID, &tmp); btv->cardid = tmp << 16; - pci_read_config_word(btv->dev, PCI_SUBSYSTEM_VENDOR_ID, &tmp); + pci_read_config_word(btv->c.pci, PCI_SUBSYSTEM_VENDOR_ID, &tmp); btv->cardid |= tmp; if (0 != btv->cardid && 0xffffffff != btv->cardid) { @@ -1883,14 +1994,14 @@ void __devinit bttv_idcard(struct bttv * /* found it */ printk(KERN_INFO "bttv%d: detected: %s [card=%d], " "PCI subsystem ID is %04x:%04x\n", - btv->nr,cards[type].name,cards[type].cardnr, + btv->c.nr,cards[type].name,cards[type].cardnr, btv->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); - btv->type = cards[type].cardnr; + btv->c.type = cards[type].cardnr; } else { /* 404 */ printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n", - btv->nr, btv->cardid & 0xffff, + btv->c.nr, btv->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); printk(KERN_DEBUG "please mail id, board name and " "the correct card= insmod option to kraxel@bytesex.org\n"); @@ -1898,13 +2009,13 @@ void __devinit bttv_idcard(struct bttv * } /* let the user override the autodetected type */ - if (card[btv->nr] < bttv_num_tvcards) - btv->type=card[btv->nr]; + if (card[btv->c.nr] < bttv_num_tvcards) + btv->c.type=card[btv->c.nr]; /* print which card config we are using */ - printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->nr, - bttv_tvcards[btv->type].name, btv->type, - card[btv->nr] < bttv_num_tvcards + printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr, + bttv_tvcards[btv->c.type].name, btv->c.type, + card[btv->c.nr] < bttv_num_tvcards ? "insmod option" : "autodetected"); /* overwrite gpio stuff ?? */ @@ -1914,20 +2025,20 @@ void __devinit bttv_idcard(struct bttv * if (UNSET != audiomux[0]) { gpiobits = 0; for (i = 0; i < 5; i++) { - bttv_tvcards[btv->type].audiomux[i] = audiomux[i]; + bttv_tvcards[btv->c.type].audiomux[i] = audiomux[i]; gpiobits |= audiomux[i]; } } else { gpiobits = audioall; for (i = 0; i < 5; i++) { - bttv_tvcards[btv->type].audiomux[i] = audioall; + bttv_tvcards[btv->c.type].audiomux[i] = audioall; } } - bttv_tvcards[btv->type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; + bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", - btv->nr,bttv_tvcards[btv->type].gpiomask); + btv->c.nr,bttv_tvcards[btv->c.type].gpiomask); for (i = 0; i < 5; i++) { - printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->type].audiomux[i]); + printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].audiomux[i]); } printk("\n"); } @@ -1941,7 +2052,7 @@ void identify_by_eeprom(struct bttv *btv { int type = -1; - if (0 == strncmp(eeprom_data,"GET.MM20xPCTV",13)) + if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13)) type = BTTV_MODTEC_205; else if (0 == strncmp(eeprom_data+20,"Picolo",7)) type = BTTV_EURESYS_PICOLO; @@ -1949,22 +2060,22 @@ void identify_by_eeprom(struct bttv *btv type = BTTV_HAUPPAUGE; /* old bt848 */ if (-1 != type) { - btv->type = type; + btv->c.type = type; printk("bttv%d: detected by eeprom: %s [card=%d]\n", - btv->nr, bttv_tvcards[btv->type].name, btv->type); + btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type); } } static void flyvideo_gpio(struct bttv *btv) { - int gpio,outbits,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; + int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; int tuner=-1,ttype; - - outbits = btread(BT848_GPIO_OUT_EN); - btwrite(0x00, BT848_GPIO_OUT_EN); + + gpio_inout(0xffffff, 0); udelay(8); // without this we would see the 0x1800 mask - gpio=btread(BT848_GPIO_DATA); - btwrite(outbits, BT848_GPIO_OUT_EN); + gpio = gpio_read(); + /* FIXME: must restore OUR_EN ??? */ + // all cards provide GPIO info, some have an additional eeprom // LR50: GPIO coding can be found lower right CP1 .. CP9 // CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1. @@ -1989,7 +2100,7 @@ static void flyvideo_gpio(struct bttv *b case 0xC: tuner=3; // Philips SECAM(+PAL) FQ1216ME or FI1216MF break; default: - printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->nr); + printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr); } has_remote = gpio & 0x800000; @@ -2005,9 +2116,9 @@ static void flyvideo_gpio(struct bttv *b tuner=4; // No tuner present printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", - btv->nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); + btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n", - btv->nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", + btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", is_capture_only?"yes":"no "); if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through @@ -2031,8 +2142,8 @@ static void miro_pinnacle_gpio(struct bt int id,msp,gpio; char *info; - btwrite(0,BT848_GPIO_OUT_EN); - gpio = btread(BT848_GPIO_DATA); + gpio_inout(0xffffff, 0); + gpio = gpio_read(); id = ((gpio>>10) & 63) -1; msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); if (id < 32) { @@ -2051,14 +2162,14 @@ static void miro_pinnacle_gpio(struct bt btv->has_radio = 0; } if (-1 != msp) { - if (btv->type == BTTV_MIRO) - btv->type = BTTV_MIROPRO; - if (btv->type == BTTV_PINNACLE) - btv->type = BTTV_PINNACLEPRO; + if (btv->c.type == BTTV_MIRO) + btv->c.type = BTTV_MIROPRO; + if (btv->c.type == BTTV_PINNACLE) + btv->c.type = BTTV_PINNACLEPRO; } printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n", - btv->nr, id+1, btv->tuner_type, + btv->c.nr, id+1, btv->tuner_type, !btv->has_radio ? "no" : (btv->has_matchbox ? "matchbox" : "fmtuner"), (-1 == msp) ? "no" : "yes"); @@ -2087,15 +2198,18 @@ static void miro_pinnacle_gpio(struct bt case 6: info = "NTSC / stereo"; break; + case 7: + info = "PAL / stereo"; + break; default: info = "oops: unknown card"; break; } if (-1 != msp) - btv->type = BTTV_PINNACLEPRO; + btv->c.type = BTTV_PINNACLEPRO; printk(KERN_INFO "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n", - btv->nr, id, info, btv->has_radio ? "yes" : "no"); + btv->c.nr, id, info, btv->has_radio ? "yes" : "no"); btv->tuner_type = 33; btv->pinnacle_id = id; } @@ -2106,16 +2220,14 @@ static void miro_pinnacle_gpio(struct bt static void init_ids_eagle(struct bttv *btv) { - btwrite(0xFFFF37, BT848_GPIO_OUT_EN); - btwrite(0x000000, BT848_GPIO_REG_INP); - - btwrite(0x200020, BT848_GPIO_DATA); + gpio_inout(0xffffff,0xFFFF37); + gpio_write(0x200020); /* flash strobe inverter ?! */ - btwrite(0x200024, BT848_GPIO_DATA); + gpio_write(0x200024); /* switch sync drive off */ - btor(LM1882_SYNC_DRIVE, BT848_GPIO_DATA); + gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); /* set BT848 muxel to 2 */ btaor((2)<<5, ~(2<<5), BT848_IFORM); @@ -2127,8 +2239,7 @@ static void init_ids_eagle(struct bttv * static void eagle_muxsel(struct bttv *btv, unsigned int input) { btaor((2)<<5, ~(3<<5), BT848_IFORM); - btaor((bttv_tvcards[btv->type].muxsel[input&7]&3), - ~3, BT848_GPIO_DATA); + gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]); #if 0 /* svhs */ @@ -2147,9 +2258,37 @@ static void eagle_muxsel(struct bttv *bt #endif /* switch sync drive off */ - btor(LM1882_SYNC_DRIVE, BT848_GPIO_DATA); + gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE); +} + +static void gvc1100_muxsel(struct bttv *btv, unsigned int input) +{ + static const int masks[] = {0x30, 0x01, 0x12, 0x23}; + gpio_write(masks[input%4]); } +/* LMLBT4x initialization - to allow access to GPIO bits for sensors input and + alarms output + + GPIObit | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + assignment | TI | O3|INx| O2| O1|IN4|IN3|IN2|IN1| | | + + IN - sensor inputs, INx - sensor inputs and TI XORed together + O1,O2,O3 - alarm outputs (relays) + + OUT ENABLE 1 1 0 . 1 1 0 0 . 0 0 0 0 = 0x6C0 + +*/ + +static void init_lmlbt4x(struct bttv *btv) +{ + printk(KERN_DEBUG "LMLBT4x init\n"); + btwrite(0x000000, BT848_GPIO_REG_INP); + gpio_inout(0xffffff, 0x0006C0); + gpio_write(0x000000); +} + + /* ----------------------------------------------------------------------- */ void bttv_reset_audio(struct bttv *btv) @@ -2167,7 +2306,7 @@ void bttv_reset_audio(struct bttv *btv) return; if (bttv_debug) - printk("bttv%d: BT878A ARESET\n",btv->nr); + printk("bttv%d: BT878A ARESET\n",btv->c.nr); btwrite((1<<7), 0x058); udelay(10); btwrite( 0, 0x058); @@ -2176,7 +2315,7 @@ void bttv_reset_audio(struct bttv *btv) /* initialization part one -- before registering i2c bus */ void __devinit bttv_init_card1(struct bttv *btv) { - switch (btv->type) { + switch (btv->c.type) { case BTTV_HAUPPAUGE: case BTTV_HAUPPAUGE878: boot_msp34xx(btv,5); @@ -2198,12 +2337,12 @@ void __devinit bttv_init_card2(struct bt { btv->tuner_type = -1; - if (BTTV_UNKNOWN == btv->type) { + if (BTTV_UNKNOWN == btv->c.type) { bttv_readee(btv,eeprom_data,0xa0); identify_by_eeprom(btv,eeprom_data); } - switch (btv->type) { + switch (btv->c.type) { case BTTV_MIRO: case BTTV_MIROPRO: case BTTV_PINNACLE: @@ -2255,7 +2394,7 @@ void __devinit bttv_init_card2(struct bt case BTTV_MAGICTVIEW061: if (btv->cardid == 0x3002144f) { btv->has_radio=1; - printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->nr); + printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr); } break; case BTTV_STB2: @@ -2287,21 +2426,24 @@ void __devinit bttv_init_card2(struct bt bttv_readee(btv,eeprom_data,0xa0); modtec_eeprom(btv); break; + case BTTV_LMLBT4: + init_lmlbt4x(btv); + break; } /* pll configuration */ if (!(btv->id==848 && btv->revision==0x11)) { /* defaults from card list */ - if (PLL_28 == bttv_tvcards[btv->type].pll) { + if (PLL_28 == bttv_tvcards[btv->c.type].pll) { btv->pll.pll_ifreq=28636363; btv->pll.pll_crystal=BT848_IFORM_XT0; } - if (PLL_35 == bttv_tvcards[btv->type].pll) { + if (PLL_35 == bttv_tvcards[btv->c.type].pll) { btv->pll.pll_ifreq=35468950; btv->pll.pll_crystal=BT848_IFORM_XT1; } /* insmod options can override */ - switch (pll[btv->nr]) { + switch (pll[btv->c.nr]) { case 0: /* none */ btv->pll.pll_crystal = 0; btv->pll.pll_ifreq = 0; @@ -2324,27 +2466,33 @@ void __devinit bttv_init_card2(struct bt btv->pll.pll_current = -1; /* tuner configuration (from card list / autodetect / insmod option) */ - if (UNSET != bttv_tvcards[btv->type].tuner_type) + if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) - btv->tuner_type = bttv_tvcards[btv->type].tuner_type; - if (UNSET != tuner[btv->nr]) - btv->tuner_type = tuner[btv->nr]; - printk("bttv%d: using tuner=%d\n",btv->nr,btv->tuner_type); + btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; + if (UNSET != tuner[btv->c.nr]) + btv->tuner_type = tuner[btv->c.nr]; + printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); if (btv->pinnacle_id != UNSET) bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); if (btv->tuner_type != UNSET) bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - btv->svhs = bttv_tvcards[btv->type].svhs; - if (svhs[btv->nr] != UNSET) - btv->svhs = svhs[btv->nr]; + btv->svhs = bttv_tvcards[btv->c.type].svhs; + if (svhs[btv->c.nr] != UNSET) + btv->svhs = svhs[btv->c.nr]; + if (remote[btv->c.nr] != UNSET) + btv->has_remote = remote[btv->c.nr]; - if (bttv_tvcards[btv->type].has_radio) + if (bttv_tvcards[btv->c.type].has_radio) btv->has_radio=1; - if (bttv_tvcards[btv->type].audio_hook) - btv->audio_hook=bttv_tvcards[btv->type].audio_hook; + if (bttv_tvcards[btv->c.type].has_remote) + btv->has_remote=1; + if (bttv_tvcards[btv->c.type].no_gpioirq) + btv->gpioirq=0; + if (bttv_tvcards[btv->c.type].audio_hook) + btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; - if (bttv_tvcards[btv->type].digital_mode == DIGITAL_MODE_CAMERA) { + if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) { /* detect Bt832 chip for quartzsight digital camera */ if ((bttv_I2CRead(btv, I2C_BT832_ALT1, "Bt832") >=0) || (bttv_I2CRead(btv, I2C_BT832_ALT2, "Bt832") >=0)) @@ -2352,31 +2500,31 @@ void __devinit bttv_init_card2(struct bt } /* try to detect audio/fader chips */ - if (!bttv_tvcards[btv->type].no_msp34xx && + if (!bttv_tvcards[btv->c.type].no_msp34xx && bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) { if (autoload) request_module("msp3400"); } - if (bttv_tvcards[btv->type].msp34xx_alt && + if (bttv_tvcards[btv->c.type].msp34xx_alt && bttv_I2CRead(btv, I2C_MSP3400_ALT, "MSP34xx (alternate address)") >=0) { if (autoload) request_module("msp3400"); } - if (!bttv_tvcards[btv->type].no_tda9875 && + if (!bttv_tvcards[btv->c.type].no_tda9875 && bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { if (autoload) request_module("tda9875"); } - if (!bttv_tvcards[btv->type].no_tda7432 && + if (!bttv_tvcards[btv->c.type].no_tda7432 && bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { if (autoload) request_module("tda7432"); } - if (bttv_tvcards[btv->type].needs_tvaudio) { + if (bttv_tvcards[btv->c.type].needs_tvaudio) { if (autoload) request_module("tvaudio"); } @@ -2460,11 +2608,15 @@ static void modtec_eeprom(struct bttv *b { if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) { btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I; - printk("bttv Modtec: Tuner autodetected %s\n", - &eeprom_data[0x1e]); + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) { + btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); } else { - printk("bttv Modtec: Unknown TunerString:%s\n", - &eeprom_data[0x1e]); + printk("bttv%d: Modtec: Unknown TunerString: %s\n", + btv->c.nr,&eeprom_data[0x1e]); } } @@ -2474,7 +2626,7 @@ static void __devinit hauppauge_eeprom(s if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0) printk(KERN_WARNING "bttv%d: Hauppauge eeprom: invalid\n", - btv->nr); + btv->c.nr); /* Block 2 starts after len+3 bytes header */ blk2 = eeprom_data[1] + 3; @@ -2492,7 +2644,7 @@ static void __devinit hauppauge_eeprom(s if (bttv_verbose) printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, " "tuner=%s (%d), radio=%s\n", - btv->nr, model, hauppauge_tuner[tuner].name, + btv->c.nr, model, hauppauge_tuner[tuner].name, btv->tuner_type, radio ? "yes" : "no"); } @@ -2516,7 +2668,7 @@ static int terratec_active_radio_upgrade tea5757_write(btv, 5 * freq + 0x358); // write 0x1ed8 if (0x1ed8 == tea5757_read(btv)) { printk("bttv%d: Terratec Active Radio Upgrade found.\n", - btv->nr); + btv->c.nr); btv->has_radio = 1; btv->has_matchbox = 1; } else { @@ -2547,36 +2699,35 @@ static int __devinit pvr_altera_load(str u32 n; u8 bits; int i; - - btwrite(BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG, - BT848_GPIO_OUT_EN); - btwrite(0,BT848_GPIO_DATA); + + gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); + gpio_write(0); udelay(PVR_GPIO_DELAY); - btwrite(BTTV_ALT_NCONFIG,BT848_GPIO_DATA); + gpio_write(BTTV_ALT_NCONFIG); udelay(PVR_GPIO_DELAY); for (n = 0; n < microlen; n++) { bits = micro[n]; for ( i = 0 ; i < 8 ; i++ ) { - btand(~BTTV_ALT_DCLK,BT848_GPIO_DATA); - if (bits & 0x01) - btor(BTTV_ALT_DATA,BT848_GPIO_DATA); + gpio_bits(BTTV_ALT_DCLK,0); + if (bits & 0x01) + gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA); else - btand(~BTTV_ALT_DATA,BT848_GPIO_DATA); - btor(BTTV_ALT_DCLK,BT848_GPIO_DATA); + gpio_bits(BTTV_ALT_DATA,0); + gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); bits >>= 1; } } - btand(~BTTV_ALT_DCLK,BT848_GPIO_DATA); + gpio_bits(BTTV_ALT_DCLK,0); udelay(PVR_GPIO_DELAY); /* begin Altera init loop (Not necessary,but doesn't hurt) */ for (i = 0 ; i < 30 ; i++) { - btand(~BTTV_ALT_DCLK,BT848_GPIO_DATA); - btor(BTTV_ALT_DCLK,BT848_GPIO_DATA); + gpio_bits(BTTV_ALT_DCLK,0); + gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK); } - btand(~BTTV_ALT_DCLK,BT848_GPIO_DATA); + gpio_bits(BTTV_ALT_DCLK,0); return 0; } @@ -2599,15 +2750,15 @@ int __devinit pvr_boot(struct bttv *btv) microlen = mod_firmware_load(firm_altera, (char**) µ); if (!microlen) { printk(KERN_WARNING "bttv%d: altera firmware not found [%s]\n", - btv->nr, firm_altera); + btv->c.nr, firm_altera); return -1; } printk(KERN_INFO "bttv%d: uploading altera firmware [%s] ...\n", - btv->nr, firm_altera); + btv->c.nr, firm_altera); result = pvr_altera_load(btv, micro, microlen); printk(KERN_INFO "bttv%d: ... upload %s\n", - btv->nr, (result < 0) ? "failed" : "ok"); + btv->c.nr, (result < 0) ? "failed" : "ok"); vfree(micro); return result; } @@ -2619,15 +2770,15 @@ int __devinit pvr_boot(struct bttv *btv) const struct firmware *fw_entry; int rc; - rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->dev->dev); + rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); if (rc != 0) { printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", - btv->nr); + btv->c.nr); return rc; } rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); printk(KERN_INFO "bttv%d: altera firmware upload %s\n", - btv->nr, (rc < 0) ? "failed" : "ok"); + btv->c.nr, (rc < 0) ? "failed" : "ok"); release_firmware(fw_entry); return rc; } @@ -2642,7 +2793,7 @@ static void __devinit osprey_eeprom(stru unsigned char *ee = eeprom_data; unsigned long serial = 0; - if (btv->type == 0) { + if (btv->c.type == 0) { /* this might be an antique... check for MMAC label in eeprom */ if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { unsigned char checksum = 0; @@ -2650,7 +2801,7 @@ static void __devinit osprey_eeprom(stru checksum += ee[i]; if (checksum != ee[21]) return; - btv->type = BTTV_OSPREY1x0_848; + btv->c.type = BTTV_OSPREY1x0_848; for (i = 12; i < 21; i++) serial *= 10, serial += ee[i] - '0'; } @@ -2679,49 +2830,49 @@ static void __devinit osprey_eeprom(stru /* 848 based */ case 0x0004: - btv->type = BTTV_OSPREY1x0_848; + btv->c.type = BTTV_OSPREY1x0_848; break; case 0x0005: - btv->type = BTTV_OSPREY101_848; + btv->c.type = BTTV_OSPREY101_848; break; /* 878 based */ case 0x0012: case 0x0013: - btv->type = BTTV_OSPREY1x0; + btv->c.type = BTTV_OSPREY1x0; break; case 0x0014: case 0x0015: - btv->type = BTTV_OSPREY1x1; + btv->c.type = BTTV_OSPREY1x1; break; case 0x0016: case 0x0017: case 0x0020: - btv->type = BTTV_OSPREY1x1_SVID; + btv->c.type = BTTV_OSPREY1x1_SVID; break; case 0x0018: case 0x0019: case 0x001E: case 0x001F: - btv->type = BTTV_OSPREY2xx; + btv->c.type = BTTV_OSPREY2xx; break; case 0x001A: case 0x001B: - btv->type = BTTV_OSPREY2x0_SVID; + btv->c.type = BTTV_OSPREY2x0_SVID; break; case 0x0040: - btv->type = BTTV_OSPREY500; + btv->c.type = BTTV_OSPREY500; break; case 0x0050: case 0x0056: - btv->type = BTTV_OSPREY540; + btv->c.type = BTTV_OSPREY540; /* bttv_osprey_540_init(btv); */ break; case 0x0060: case 0x0070: - btv->type = BTTV_OSPREY2x0; + btv->c.type = BTTV_OSPREY2x0; //enable output on select control lines - btwrite(0x000303, BT848_GPIO_OUT_EN); + gpio_inout(0xffffff,0x000303); break; default: /* unknown...leave generic, but get serial # */ @@ -2734,7 +2885,7 @@ static void __devinit osprey_eeprom(stru } printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n", - btv->nr, btv->type, bttv_tvcards[btv->type].name,serial); + btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial); } /* ----------------------------------------------------------------------- */ @@ -2779,7 +2930,7 @@ static void __devinit avermedia_eeprom(s tuner = tuner_1_table[tuner_format]; printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=", - btv->nr,eeprom_data[0x41],eeprom_data[0x42]); + btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]); if(tuner) { btv->tuner_type=tuner; printk("%d",tuner); @@ -2805,8 +2956,8 @@ void bttv_tda9880_setnorm(struct bttv *b dprintk("bttv_tda9880_setnorm to PAL\n"); } // set GPIO according - btaor(bttv_tvcards[btv->type].audiomux[btv->audio], - ~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); + gpio_bits(bttv_tvcards[btv->c.type].gpiomask, + bttv_tvcards[btv->c.type].audiomux[btv->audio]); } @@ -2821,23 +2972,23 @@ static void __devinit boot_msp34xx(struc { int mask = (1 << pin); - btaor(mask, ~mask, BT848_GPIO_OUT_EN); - btaor(0, ~mask, BT848_GPIO_DATA); + gpio_inout(mask,mask); + gpio_bits(mask,0); udelay(2500); - btaor(mask, ~mask, BT848_GPIO_DATA); + gpio_bits(mask,mask); + if (bttv_gpio) bttv_gpio_tracking(btv,"msp34xx"); - if (bttv_verbose) printk(KERN_INFO "bttv%d: Hauppauge/Voodoo msp34xx: reset line " - "init [%d]\n", btv->nr, pin); + "init [%d]\n", btv->c.nr, pin); } static void __devinit boot_bt832(struct bttv *btv) { - int outbits,databits,resetbit=0; + int resetbit=0; - switch (btv->type) { + switch (btv->c.type) { case BTTV_PXELVWPLTVPAK: resetbit = 0x400000; break; @@ -2851,18 +3002,14 @@ static void __devinit boot_bt832(struct request_module("bt832"); bttv_call_i2c_clients(btv, BT832_HEXDUMP, NULL); - printk("bttv%d: Reset Bt832 [line=0x%x]\n",btv->nr,resetbit); - btwrite(0, BT848_GPIO_DATA); - outbits = btread(BT848_GPIO_OUT_EN); - databits= btread(BT848_GPIO_DATA); - btwrite(resetbit, BT848_GPIO_OUT_EN); + printk("bttv%d: Reset Bt832 [line=0x%x]\n",btv->c.nr,resetbit); + gpio_write(0); + gpio_inout(resetbit, resetbit); udelay(5); - btwrite(resetbit, BT848_GPIO_DATA); + gpio_bits(resetbit, resetbit); udelay(5); - btwrite(0, BT848_GPIO_DATA); + gpio_bits(resetbit, 0); udelay(5); - btwrite(outbits, BT848_GPIO_OUT_EN); - btwrite(databits, BT848_GPIO_DATA); // bt832 on pixelview changes from i2c 0x8a to 0x88 after // being reset as above. So we must follow by this: @@ -2885,13 +3032,13 @@ static void __devinit init_PXC200(struct u32 val; /* Initialise GPIO-connevted stuff */ - btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */ - btwrite(0,BT848_GPIO_DATA); + gpio_bits(0xffffff, (1<<13)); + gpio_write(0); udelay(3); - btwrite(1<<13,BT848_GPIO_DATA); + gpio_write(1<<13); /* GPIO inputs are pulled up, so no need to drive * reset pin any longer */ - btwrite(0,BT848_GPIO_OUT_EN); + gpio_bits(0xffffff, 0); if (bttv_gpio) bttv_gpio_tracking(btv,"pxc200"); @@ -2926,10 +3073,10 @@ static void __devinit init_PXC200(struct * device same as above for the reset line, but not the same * value sent to the GPIO-connected stuff * which one is the good one? */ - btwrite( (1<<2), BT848_GPIO_OUT_EN); /* only the reset pin */ - btwrite(0, BT848_GPIO_DATA); + gpio_inout(0xffffff,(1<<2)); + gpio_write(0); udelay(10); - btwrite(1<<2, BT848_GPIO_DATA); + gpio_write(1<<2); for (i = 0; i < ARRAY_SIZE(vals); i++) { tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1); @@ -2956,17 +3103,16 @@ static void __devinit init_PXC200(struct void bus_low(struct bttv *btv, int bit) { if (btv->mbox_ior) { - btor(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - BT848_GPIO_DATA); + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); udelay(5); } - btand(~(bit), BT848_GPIO_DATA); + gpio_bits(bit,0); udelay(5); if (btv->mbox_ior) { - btand(~(btv->mbox_iow | btv->mbox_csel), - BT848_GPIO_DATA); + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); udelay(5); } } @@ -2974,17 +3120,16 @@ void bus_low(struct bttv *btv, int bit) void bus_high(struct bttv *btv, int bit) { if (btv->mbox_ior) { - btor(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - BT848_GPIO_DATA); + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); udelay(5); } - btor((bit), BT848_GPIO_DATA); + gpio_bits(bit,bit); udelay(5); if (btv->mbox_ior) { - btand(~(btv->mbox_iow | btv->mbox_csel), - BT848_GPIO_DATA); + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); udelay(5); } } @@ -2992,15 +3137,14 @@ void bus_high(struct bttv *btv, int bit) int bus_in(struct bttv *btv, int bit) { if (btv->mbox_ior) { - btor(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - BT848_GPIO_DATA); + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); udelay(5); - btand(~(btv->mbox_ior | btv->mbox_csel), - BT848_GPIO_DATA); + gpio_bits(btv->mbox_iow | btv->mbox_csel, 0); udelay(5); } - return btread(BT848_GPIO_DATA) & (bit); + return gpio_read() & (bit); } /* TEA5757 register bits */ @@ -3038,12 +3182,11 @@ static int tea5757_read(struct bttv *btv int i; /* better safe than sorry */ - btaor((btv->mbox_clk | btv->mbox_we), - ~btv->mbox_mask, BT848_GPIO_OUT_EN); + gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we); if (btv->mbox_ior) { - btor(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - BT848_GPIO_DATA); + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); udelay(5); } @@ -3060,11 +3203,11 @@ static int tea5757_read(struct bttv *btv while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout)) schedule(); if (bus_in(btv,btv->mbox_data)) { - printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->nr); + printk(KERN_WARNING "bttv%d: tea5757: read timeout\n",btv->c.nr); return -1; } - dprintk("bttv%d: tea5757:",btv->nr); + dprintk("bttv%d: tea5757:",btv->c.nr); for(i = 0; i < 24; i++) { udelay(5); @@ -3076,7 +3219,7 @@ static int tea5757_read(struct bttv *btv value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */ dprintk("%c", (bus_in(btv,btv->mbox_most) == 0)?'S':'M'); } - dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->nr, value); + dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->c.nr, value); return value; } @@ -3085,18 +3228,17 @@ static int tea5757_write(struct bttv *bt int i; int reg = value; - btaor(btv->mbox_clk | btv->mbox_we | btv->mbox_data, - ~btv->mbox_mask, BT848_GPIO_OUT_EN); + gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data); if (btv->mbox_ior) { - btor(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, - BT848_GPIO_DATA); + gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel, + btv->mbox_ior | btv->mbox_iow | btv->mbox_csel); udelay(5); } if (bttv_gpio) bttv_gpio_tracking(btv,"tea5757 write"); - dprintk("bttv%d: tea5757: write 0x%X\n", btv->nr, value); + dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value); bus_low(btv,btv->mbox_clk); bus_high(btv,btv->mbox_we); for(i = 0; i < 25; i++) @@ -3122,7 +3264,7 @@ void tea5757_set_freq(struct bttv *btv, #if 0 /* breaks Miro PCTV */ value = tea5757_read(btv); - dprintk("bttv%d: tea5757 readback=0x%x\n",btv->nr,value); + dprintk("bttv%d: tea5757 readback=0x%x\n",btv->c.nr,value); #endif } @@ -3148,7 +3290,7 @@ void winview_audio(struct bttv *btv, str /* tens */ bits_out |= (PT2254_DBS_IN_10>>(vol/5)); bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL; - data = btread(BT848_GPIO_DATA); + data = gpio_read(); data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| WINVIEW_PT2254_STROBE); for (loops = 17; loops >= 0 ; loops--) { @@ -3156,20 +3298,20 @@ void winview_audio(struct bttv *btv, str data |= WINVIEW_PT2254_DATA; else data &= ~WINVIEW_PT2254_DATA; - btwrite(data, BT848_GPIO_DATA); + gpio_write(data); udelay(5); data |= WINVIEW_PT2254_CLK; - btwrite(data, BT848_GPIO_DATA); + gpio_write(data); udelay(5); data &= ~WINVIEW_PT2254_CLK; - btwrite(data, BT848_GPIO_DATA); + gpio_write(data); } data |= WINVIEW_PT2254_STROBE; data &= ~WINVIEW_PT2254_DATA; - btwrite(data, BT848_GPIO_DATA); + gpio_write(data); udelay(10); data &= ~WINVIEW_PT2254_STROBE; - btwrite(data, BT848_GPIO_DATA); + gpio_write(data); } /* ----------------------------------------------------------------------- */ @@ -3182,7 +3324,7 @@ gvbctv3pci_audio(struct bttv *btv, struc unsigned int con = 0; if (set) { - btor(0x300, BT848_GPIO_OUT_EN); + gpio_inout(0x300, 0x300); if (v->mode & VIDEO_SOUND_LANG1) con = 0x000; if (v->mode & VIDEO_SOUND_LANG2) @@ -3191,7 +3333,7 @@ gvbctv3pci_audio(struct bttv *btv, struc con = 0x200; // if (v->mode & VIDEO_SOUND_MONO) // con = 0x100; - btaor(con, ~0x300, BT848_GPIO_DATA); + gpio_bits(0x300, con); } else { v->mode = VIDEO_SOUND_STEREO | VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; @@ -3217,12 +3359,12 @@ avermedia_tvphone_audio(struct bttv *btv int val = 0; if (set) { - if (v->mode & VIDEO_SOUND_LANG1) /* SAP */ + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ val = 0x02; if (v->mode & VIDEO_SOUND_STEREO) val = 0x01; if (val) { - btaor(val, ~0x03, BT848_GPIO_DATA); + gpio_bits(0x03,val); if (bttv_gpio) bttv_gpio_tracking(btv,"avermedia"); } @@ -3233,13 +3375,33 @@ avermedia_tvphone_audio(struct bttv *btv } } +static void +avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) +{ + int val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* SAP */ + val = 0x01; + if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */ + val = 0x02; + btaor(val, ~0x03, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"avermedia"); + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + return; + } +} + /* Lifetec 9415 handling */ static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set) { int val = 0; - if (btread(BT848_GPIO_DATA) & 0x4000) { + if (gpio_read() & 0x4000) { v->mode = VIDEO_SOUND_MONO; return; } @@ -3252,7 +3414,7 @@ lt9415_audio(struct bttv *btv, struct vi if ((v->mode & VIDEO_SOUND_LANG1) || (v->mode & VIDEO_SOUND_MONO)) val = 0; - btaor(val, ~0x0880, BT848_GPIO_DATA); + gpio_bits(0x0880, val); if (bttv_gpio) bttv_gpio_tracking(btv,"lt9415"); } else { @@ -3270,12 +3432,12 @@ terratv_audio(struct bttv *btv, struct v unsigned int con = 0; if (set) { - btor(0x180000, BT848_GPIO_OUT_EN); + gpio_inout(0x180000,0x180000); if (v->mode & VIDEO_SOUND_LANG2) con = 0x080000; if (v->mode & VIDEO_SOUND_STEREO) con = 0x180000; - btaor(con, ~0x180000, BT848_GPIO_DATA); + gpio_bits(0x180000, con); if (bttv_gpio) bttv_gpio_tracking(btv,"terratv"); } else { @@ -3300,7 +3462,7 @@ winfast2000_audio(struct bttv *btv, stru if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */ val = 0x020000; if (val) { - btaor(val, ~0x430000, BT848_GPIO_DATA); + gpio_bits(0x430000, val); if (bttv_gpio) bttv_gpio_tracking(btv,"winfast2000"); } @@ -3340,7 +3502,7 @@ pvbt878p9b_audio(struct bttv *btv, struc val = 0x02; } if (val) { - btaor(val, ~0x03, BT848_GPIO_DATA); + gpio_bits(0x03,val); if (bttv_gpio) bttv_gpio_tracking(btv,"pvbt878p9b"); } @@ -3376,7 +3538,7 @@ fv2000s_audio(struct bttv *btv, struct v val = 0x1080; //-dk-???: 0x0880, 0x0080, 0x1800 ... } if (val != 0xffff) { - btaor(val, ~0x1800, BT848_GPIO_DATA); + gpio_bits(0x1800, val); if (bttv_gpio) bttv_gpio_tracking(btv,"fv2000s"); } @@ -3405,7 +3567,7 @@ windvr_audio(struct bttv *btv, struct vi if (v->mode & VIDEO_SOUND_STEREO) val = 0; if (val) { - btaor(val, ~0x140000, BT848_GPIO_DATA); + gpio_bits(0x140000, val); if (bttv_gpio) bttv_gpio_tracking(btv,"windvr"); } @@ -3437,7 +3599,7 @@ adtvk503_audio(struct bttv *btv, struct if (v->mode & VIDEO_SOUND_MONO) con = 0x00060000; if (con != 0xffffff) { - btaor(con, ~0x1e0000, BT848_GPIO_DATA); + gpio_bits(0x1e0000,con); if (bttv_gpio) bttv_gpio_tracking(btv, "adtvk503"); } @@ -3474,16 +3636,16 @@ adtvk503_audio(struct bttv *btv, struct static void rv605_muxsel(struct bttv *btv, unsigned int input) { /* reset all conections */ - btaor(0x200,~0x200, BT848_GPIO_DATA); + gpio_bits(0x200,0x200); mdelay(1); - btaor(0x000,~0x200, BT848_GPIO_DATA); + gpio_bits(0x200,0x000); mdelay(1); /* create a new conection */ - btaor(0x080,~0x480, BT848_GPIO_DATA); - btaor(0x480,~0x480, BT848_GPIO_DATA); + gpio_bits(0x480,0x080); + gpio_bits(0x480,0x480); mdelay(1); - btaor(0x080,~0x480, BT848_GPIO_DATA); + gpio_bits(0x480,0x080); mdelay(1); } @@ -3513,7 +3675,7 @@ static void xguard_muxsel(struct bttv *b ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, }; - btwrite(masks[input%16], BT848_GPIO_DATA); + gpio_write(masks[input%16]); } /* @@ -3555,7 +3717,7 @@ static void ivc120_muxsel(struct bttv *b int matrix = input / 4; dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n", - btv->nr, input, matrix, key); + btv->c.nr, input, matrix, key); // Handles the input selection on the TDA8540's bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00, @@ -3641,12 +3803,12 @@ int __devinit bttv_handle_chipset(struct if (bttv_verbose) { if (triton1) - printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->nr); + printk(KERN_INFO "bttv%d: enabling ETBF (430FX/VP3 compatibilty)\n",btv->c.nr); if (vsfx && btv->id >= 878) - printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->nr); + printk(KERN_INFO "bttv%d: enabling VSFX\n",btv->c.nr); if (UNSET != latency) printk(KERN_INFO "bttv%d: setting pci timer to %d\n", - btv->nr,latency); + btv->c.nr,latency); } if (btv->id < 878) { @@ -3655,15 +3817,15 @@ int __devinit bttv_handle_chipset(struct btv->triton1 = BT848_INT_ETBF; } else { /* bt878 has a bit in the pci config space for it */ - pci_read_config_byte(btv->dev, BT878_DEVCTRL, &command); + pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); if (triton1) command |= BT878_EN_TBFX; if (vsfx) command |= BT878_EN_VSFX; - pci_write_config_byte(btv->dev, BT878_DEVCTRL, command); + pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); } if (UNSET != latency) - pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency); + pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); return 0; } diff -puN drivers/media/video/bttv-driver.c~v4l-04-bttv-driver-update drivers/media/video/bttv-driver.c --- 25/drivers/media/video/bttv-driver.c~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttv-driver.c 2004-01-15 08:27:42.000000000 -0800 @@ -68,11 +68,12 @@ static unsigned int lumafilter = 0; static unsigned int automute = 1; static unsigned int chroma_agc = 0; static unsigned int adc_crush = 1; +static unsigned int whitecrush_upper = 0xCF; +static unsigned int whitecrush_lower = 0x7F; static unsigned int vcr_hack = 0; static unsigned int irq_iswitch = 0; /* API features (turn on/off stuff for testing) */ -static unsigned int sloppy = 0; static unsigned int v4l2 = 1; @@ -108,12 +109,15 @@ MODULE_PARM(chroma_agc,"i"); MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)"); MODULE_PARM(adc_crush,"i"); MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)"); +MODULE_PARM(whitecrush_upper,"i"); +MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207"); +MODULE_PARM(whitecrush_lower,"i"); +MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127"); MODULE_PARM(vcr_hack,"i"); MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)"); MODULE_PARM(irq_iswitch,"i"); MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler"); -MODULE_PARM(sloppy,"i"); MODULE_PARM(v4l2,"i"); MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards"); @@ -133,7 +137,7 @@ static ssize_t show_card(struct class_de { struct video_device *vfd = to_video_device(cd); struct bttv *btv = dev_get_drvdata(vfd->dev); - return sprintf(buf, "%d\n", btv ? btv->type : UNSET); + return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL); @@ -479,7 +483,9 @@ const unsigned int BTTV_FORMATS = ARRAY_ #define V4L2_CID_PRIVATE_LUMAFILTER (V4L2_CID_PRIVATE_BASE + 3) #define V4L2_CID_PRIVATE_AGC_CRUSH (V4L2_CID_PRIVATE_BASE + 4) #define V4L2_CID_PRIVATE_VCR_HACK (V4L2_CID_PRIVATE_BASE + 5) -#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 8) static const struct v4l2_queryctrl no_ctl = { .name = "42", @@ -597,7 +603,24 @@ static const struct v4l2_queryctrl bttv_ .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_PRIVATE_WHITECRUSH_UPPER, + .name = "whitecrush upper", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0xCF, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_PRIVATE_WHITECRUSH_LOWER, + .name = "whitecrush lower", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 0x7F, + .type = V4L2_CTRL_TYPE_INTEGER, } + }; const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); @@ -695,7 +718,7 @@ static void set_pll(struct bttv *btv) return; if (btv->pll.pll_ofreq == btv->pll.pll_current) { - dprintk("bttv%d: PLL: no change required\n",btv->nr); + dprintk("bttv%d: PLL: no change required\n",btv->c.nr); return; } @@ -704,22 +727,22 @@ static void set_pll(struct bttv *btv) if (btv->pll.pll_current == 0) return; vprintk(KERN_INFO "bttv%d: PLL can sleep, using XTAL (%d).\n", - btv->nr,btv->pll.pll_ifreq); + btv->c.nr,btv->pll.pll_ifreq); btwrite(0x00,BT848_TGCTRL); btwrite(0x00,BT848_PLL_XCI); btv->pll.pll_current = 0; return; } - vprintk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->nr, + vprintk(KERN_INFO "bttv%d: PLL: %d => %d ",btv->c.nr, btv->pll.pll_ifreq, btv->pll.pll_ofreq); set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq); for (i=0; i<10; i++) { /* Let other people run while the PLL stabilizes */ vprintk("."); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ/10); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/50); if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) { btwrite(0,BT848_DSTATUS); @@ -742,9 +765,9 @@ void bt848A_set_timing(struct bttv *btv) int table_idx = bttv_tvnorms[btv->tvnorm].sram; int fsc = bttv_tvnorms[btv->tvnorm].Fsc; - if (UNSET == bttv_tvcards[btv->type].muxsel[btv->input]) { + if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) { dprintk("bttv%d: load digital timing table (table_idx=%d)\n", - btv->nr,table_idx); + btv->c.nr,table_idx); /* timing change...reset timing generator address */ btwrite(0x00, BT848_TGCTRL); @@ -828,13 +851,13 @@ video_mux(struct bttv *btv, unsigned int { int mux,mask2; - if (input >= bttv_tvcards[btv->type].video_inputs) + if (input >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; /* needed by RemoteVideo MX */ - mask2 = bttv_tvcards[btv->type].gpiomask2; + mask2 = bttv_tvcards[btv->c.type].gpiomask2; if (mask2) - btaor(mask2,~mask2,BT848_GPIO_OUT_EN); + gpio_inout(mask2,mask2); if (input == btv->svhs) { btor(BT848_CONTROL_COMP, BT848_E_CONTROL); @@ -843,14 +866,14 @@ video_mux(struct bttv *btv, unsigned int btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); btand(~BT848_CONTROL_COMP, BT848_O_CONTROL); } - mux = bttv_tvcards[btv->type].muxsel[input] & 3; + mux = bttv_tvcards[btv->c.type].muxsel[input] & 3; btaor(mux<<5, ~(3<<5), BT848_IFORM); dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n", - btv->nr,input,mux); + btv->c.nr,input,mux); /* card specific hook */ - if(bttv_tvcards[btv->type].muxsel_hook) - bttv_tvcards[btv->type].muxsel_hook (btv, input); + if(bttv_tvcards[btv->c.type].muxsel_hook) + bttv_tvcards[btv->c.type].muxsel_hook (btv, input); return 0; } @@ -863,9 +886,9 @@ static int audio_mux(struct bttv *btv, int mode) { int val,mux,i2c_mux,signal; - - btaor(bttv_tvcards[btv->type].gpiomask, - ~bttv_tvcards[btv->type].gpiomask,BT848_GPIO_OUT_EN); + + gpio_inout(bttv_tvcards[btv->c.type].gpiomask, + bttv_tvcards[btv->c.type].gpiomask); signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC; switch (mode) { @@ -887,12 +910,12 @@ audio_mux(struct bttv *btv, int mode) mux = AUDIO_OFF; #if 0 printk("bttv%d: amux: mode=%d audio=%d signal=%s mux=%d/%d irq=%s\n", - btv->nr, mode, btv->audio, signal ? "yes" : "no", + btv->c.nr, mode, btv->audio, signal ? "yes" : "no", mux, i2c_mux, in_interrupt() ? "yes" : "no"); #endif - val = bttv_tvcards[btv->type].audiomux[mux]; - btaor(val,~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); + val = bttv_tvcards[btv->c.type].audiomux[mux]; + gpio_bits(bttv_tvcards[btv->c.type].gpiomask,val); if (bttv_gpio) bttv_gpio_tracking(btv,audio_modes[mux]); if (!in_interrupt()) @@ -909,7 +932,7 @@ i2c_vidiocschan(struct bttv *btv) c.norm = btv->tvnorm; c.channel = btv->input; bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); - if (btv->type == BTTV_VOODOOTV_FM) + if (btv->c.type == BTTV_VOODOOTV_FM) bttv_tda9880_setnorm(btv,c.norm); } @@ -932,7 +955,7 @@ set_tvnorm(struct bttv *btv, unsigned in btwrite(1, BT848_VBI_PACK_DEL); bt848A_set_timing(btv); - switch (btv->type) { + switch (btv->c.type) { case BTTV_VOODOOTV_FM: bttv_tda9880_setnorm(btv,norm); break; @@ -963,16 +986,43 @@ set_input(struct bttv *btv, unsigned int } else { video_mux(btv,input); } - audio_mux(btv,(input == bttv_tvcards[btv->type].tuner ? + audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ? AUDIO_TUNER : AUDIO_EXTERN)); set_tvnorm(btv,btv->tvnorm); } +static void init_irqreg(struct bttv *btv) +{ + /* clear status */ + btwrite(0xfffffUL, BT848_INT_STAT); + + if (bttv_tvcards[btv->c.type].no_video) { + /* i2c only */ + btwrite(BT848_INT_I2CDONE, + BT848_INT_MASK); + } else { + /* full video */ + btwrite((btv->triton1) | + (btv->gpioirq ? BT848_INT_GPINT : 0) | + BT848_INT_SCERR | + (fdsr ? BT848_INT_FDSR : 0) | + BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| + BT848_INT_FMTCHG|BT848_INT_HLOCK| + BT848_INT_I2CDONE, + BT848_INT_MASK); + } +} + static void init_bt848(struct bttv *btv) { int val; - btwrite(0, BT848_SRESET); + if (bttv_tvcards[btv->c.type].no_video) { + /* very basic init only */ + init_irqreg(btv); + return; + } + btwrite(0x00, BT848_CAP_CTL); btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); @@ -995,6 +1045,9 @@ static void init_bt848(struct bttv *btv) btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), BT848_ADC); + btwrite(whitecrush_upper, BT848_WC_UP); + btwrite(whitecrush_lower, BT848_WC_DOWN); + if (btv->opt_lumafilter) { btwrite(0, BT848_E_CONTROL); btwrite(0, BT848_O_CONTROL); @@ -1004,14 +1057,7 @@ static void init_bt848(struct bttv *btv) } /* interrupt */ - btwrite(0xfffffUL, BT848_INT_STAT); - btwrite((btv->triton1) | - BT848_INT_GPINT | - BT848_INT_SCERR | - (fdsr ? BT848_INT_FDSR : 0) | - BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES| - BT848_INT_FMTCHG|BT848_INT_HLOCK, - BT848_INT_MASK); + init_irqreg(btv); } extern void bttv_reinit_bt848(struct bttv *btv) @@ -1019,7 +1065,7 @@ extern void bttv_reinit_bt848(struct btt unsigned long flags; if (bttv_verbose) - printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->nr); + printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr); spin_lock_irqsave(&btv->s_lock,flags); btv->errors=0; bttv_set_dma(btv,0,0); @@ -1094,6 +1140,12 @@ static int get_control(struct bttv *btv, case V4L2_CID_PRIVATE_VCR_HACK: c->value = btv->opt_vcr_hack; break; + case V4L2_CID_PRIVATE_WHITECRUSH_UPPER: + c->value = btv->opt_whitecrush_upper; + break; + case V4L2_CID_PRIVATE_WHITECRUSH_LOWER: + c->value = btv->opt_whitecrush_lower; + break; default: return -EINVAL; } @@ -1182,6 +1234,14 @@ static int set_control(struct bttv *btv, case V4L2_CID_PRIVATE_VCR_HACK: btv->opt_vcr_hack = c->value; break; + case V4L2_CID_PRIVATE_WHITECRUSH_UPPER: + btv->opt_whitecrush_upper = c->value; + btwrite(c->value, BT848_WC_UP); + break; + case V4L2_CID_PRIVATE_WHITECRUSH_LOWER: + btv->opt_whitecrush_lower = c->value; + btwrite(c->value, BT848_WC_DOWN); + break; default: return -EINVAL; } @@ -1201,7 +1261,7 @@ void bttv_gpio_tracking(struct bttv *btv outbits = btread(BT848_GPIO_OUT_EN); data = btread(BT848_GPIO_DATA); printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n", - btv->nr,outbits,data & outbits, data & ~outbits, comment); + btv->c.nr,outbits,data & outbits, data & ~outbits, comment); } void bttv_field_count(struct bttv *btv) @@ -1325,7 +1385,7 @@ static int bttv_prepare_buffer(struct bt /* alloc risc memory */ if (STATE_NEEDS_INIT == buf->vb.state) { redo_dma_risc = 1; - if (0 != (rc = videobuf_iolock(btv->dev,&buf->vb,&btv->fbuf))) + if (0 != (rc = videobuf_iolock(btv->c.pci,&buf->vb,&btv->fbuf))) goto fail; } @@ -1428,7 +1488,7 @@ int bttv_common_ioctls(struct bttv *btv, { struct video_tuner *v = arg; - if (UNSET == bttv_tvcards[btv->type].tuner) + if (UNSET == bttv_tvcards[btv->c.type].tuner) return -EINVAL; if (v->tuner) /* Only tuner 0 */ return -EINVAL; @@ -1462,13 +1522,13 @@ int bttv_common_ioctls(struct bttv *btv, struct video_channel *v = arg; unsigned int channel = v->channel; - if (channel >= bttv_tvcards[btv->type].video_inputs) + if (channel >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; v->tuners=0; v->flags = VIDEO_VC_AUDIO; v->type = VIDEO_TYPE_CAMERA; v->norm = btv->tvnorm; - if (channel == bttv_tvcards[btv->type].tuner) { + if (channel == bttv_tvcards[btv->c.type].tuner) { strcpy(v->name,"Television"); v->flags|=VIDEO_VC_TUNER; v->type=VIDEO_TYPE_TV; @@ -1485,7 +1545,7 @@ int bttv_common_ioctls(struct bttv *btv, struct video_channel *v = arg; unsigned int channel = v->channel; - if (channel >= bttv_tvcards[btv->type].video_inputs) + if (channel >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; if (v->norm >= BTTV_TVNORMS) return -EINVAL; @@ -1528,7 +1588,7 @@ int bttv_common_ioctls(struct bttv *btv, struct video_audio *v = arg; unsigned int audio = v->audio; - if (audio >= bttv_tvcards[btv->type].audio_inputs) + if (audio >= bttv_tvcards[btv->c.type].audio_inputs) return -EINVAL; down(&btv->lock); @@ -1596,13 +1656,13 @@ int bttv_common_ioctls(struct bttv *btv, unsigned int n; n = i->index; - if (n >= bttv_tvcards[btv->type].video_inputs) + if (n >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; memset(i,0,sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 1; - if (i->index == bttv_tvcards[btv->type].tuner) { + if (i->index == bttv_tvcards[btv->c.type].tuner) { sprintf(i->name, "Television"); i->type = V4L2_INPUT_TYPE_TUNER; i->tuner = 0; @@ -1632,7 +1692,7 @@ int bttv_common_ioctls(struct bttv *btv, { unsigned int *i = arg; - if (*i > bttv_tvcards[btv->type].video_inputs) + if (*i > bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; down(&btv->lock); set_input(btv,*i); @@ -1645,7 +1705,7 @@ int bttv_common_ioctls(struct bttv *btv, { struct v4l2_tuner *t = arg; - if (UNSET == bttv_tvcards[btv->type].tuner) + if (UNSET == bttv_tvcards[btv->c.type].tuner) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -1683,7 +1743,7 @@ int bttv_common_ioctls(struct bttv *btv, { struct v4l2_tuner *t = arg; - if (UNSET == bttv_tvcards[btv->type].tuner) + if (UNSET == bttv_tvcards[btv->c.type].tuner) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -2061,16 +2121,16 @@ static int bttv_do_ioctl(struct inode *i switch (_IOC_TYPE(cmd)) { case 'v': printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n", - btv->nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ? + btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ? v4l1_ioctls[_IOC_NR(cmd)] : "???"); break; case 'V': printk("bttv%d: ioctl 0x%x (v4l2, %s)\n", - btv->nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]); + btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]); break; default: printk("bttv%d: ioctl 0x%x (???)\n", - btv->nr, cmd); + btv->c.nr, cmd); } } if (btv->errors) @@ -2110,8 +2170,8 @@ static int bttv_do_ioctl(struct inode *i VID_TYPE_OVERLAY| VID_TYPE_CLIPPING| VID_TYPE_SCALES; - cap->channels = bttv_tvcards[btv->type].video_inputs; - cap->audios = bttv_tvcards[btv->type].audio_inputs; + cap->channels = bttv_tvcards[btv->c.type].video_inputs; + cap->audios = bttv_tvcards[btv->c.type].audio_inputs; cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; cap->minwidth = 48; @@ -2144,7 +2204,7 @@ static int bttv_do_ioctl(struct inode *i if (NULL == fmt) return -EINVAL; down(&fh->cap.lock); - if (fmt->depth != pic->depth && !sloppy) { + if (fmt->depth != pic->depth) { retval = -EINVAL; goto fh_unlock_and_return; } @@ -2228,43 +2288,35 @@ static int bttv_do_ioctl(struct inode *i fbuf->height * fbuf->bytesperline; down(&fh->cap.lock); retval = -EINVAL; - if (sloppy) { - /* also set the default palette -- for backward - compatibility with older versions */ - switch (fbuf->depth) { - case 8: - fmt = format_by_palette(VIDEO_PALETTE_HI240); - break; - case 16: - fmt = format_by_palette(VIDEO_PALETTE_RGB565); - break; - case 24: - fmt = format_by_palette(VIDEO_PALETTE_RGB24); - break; - case 32: - fmt = format_by_palette(VIDEO_PALETTE_RGB32); - break; - case 15: - fbuf->depth = 16; - fmt = format_by_palette(VIDEO_PALETTE_RGB555); - break; - default: - fmt = NULL; - break; - } - if (NULL == fmt) - goto fh_unlock_and_return; - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - } else { - if (15 == fbuf->depth) - fbuf->depth = 16; - if (fbuf->depth != 8 && fbuf->depth != 16 && - fbuf->depth != 24 && fbuf->depth != 32) - goto fh_unlock_and_return; + + switch (fbuf->depth) { + case 8: + fmt = format_by_palette(VIDEO_PALETTE_HI240); + break; + case 16: + fmt = format_by_palette(VIDEO_PALETTE_RGB565); + break; + case 24: + fmt = format_by_palette(VIDEO_PALETTE_RGB24); + break; + case 32: + fmt = format_by_palette(VIDEO_PALETTE_RGB32); + break; + case 15: + fbuf->depth = 16; + fmt = format_by_palette(VIDEO_PALETTE_RGB555); + break; + default: + fmt = NULL; + break; } + if (NULL == fmt) + goto fh_unlock_and_return; + + fh->ovfmt = fmt; + fh->fmt = fmt; + btv->init.ovfmt = fmt; + btv->init.fmt = fmt; btv->fbuf.base = fbuf->base; btv->fbuf.fmt.width = fbuf->width; btv->fbuf.fmt.height = fbuf->height; @@ -2287,7 +2339,7 @@ static int bttv_do_ioctl(struct inode *i if (NULL == btv->fbuf.base) return -EINVAL; if (!fh->ov.setup_ok) { - dprintk("bttv%d: overlay: !setup_ok\n",btv->nr); + dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); return -EINVAL; } } @@ -2383,7 +2435,7 @@ static int bttv_do_ioctl(struct inode *i retval = -EIO; /* fall through */ case STATE_DONE: - videobuf_dma_pci_sync(btv->dev,&buf->vb.dma); + videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma); bttv_dma_free(btv,buf); break; default: @@ -2464,7 +2516,7 @@ static int bttv_do_ioctl(struct inode *i return -EINVAL; strcpy(cap->driver,"bttv"); strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); - sprintf(cap->bus_info,"PCI:%s",pci_name(btv->dev)); + sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci)); cap->version = BTTV_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | @@ -2768,7 +2820,7 @@ static ssize_t bttv_read(struct file *fi if (fh->btv->errors) bttv_reinit_bt848(fh->btv); dprintk("bttv%d: read count=%d type=%s\n", - fh->btv->nr,(int)count,v4l2_type_names[fh->type]); + fh->btv->c.nr,(int)count,v4l2_type_names[fh->type]); switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -2849,12 +2901,14 @@ static int bttv_open(struct inode *inode dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); for (i = 0; i < bttv_num; i++) { - if (bttvs[i].video_dev->minor == minor) { + if (bttvs[i].video_dev && + bttvs[i].video_dev->minor == minor) { btv = &bttvs[i]; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; break; } - if (bttvs[i].vbi_dev->minor == minor) { + if (bttvs[i].vbi_dev && + bttvs[i].vbi_dev->minor == minor) { btv = &bttvs[i]; type = V4L2_BUF_TYPE_VBI_CAPTURE; break; @@ -2864,7 +2918,7 @@ static int bttv_open(struct inode *inode return -ENODEV; dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", - btv->nr,v4l2_type_names[type]); + btv->c.nr,v4l2_type_names[type]); /* allocate per filehandle data */ fh = kmalloc(sizeof(*fh),GFP_KERNEL); @@ -2879,12 +2933,12 @@ static int bttv_open(struct inode *inode #endif videobuf_queue_init(&fh->cap, &bttv_video_qops, - btv->dev, &btv->s_lock, + btv->c.pci, &btv->s_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct bttv_buffer)); videobuf_queue_init(&fh->vbi, &bttv_vbi_qops, - btv->dev, &btv->s_lock, + btv->c.pci, &btv->s_lock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer)); @@ -2942,7 +2996,7 @@ bttv_mmap(struct file *file, struct vm_a struct bttv_fh *fh = file->private_data; dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n", - fh->btv->nr, v4l2_type_names[fh->type], + fh->btv->c.nr, v4l2_type_names[fh->type], vma->vm_start, vma->vm_end - vma->vm_start); return videobuf_mmap_mapper(vma,bttv_queue(fh)); } @@ -2998,7 +3052,7 @@ static int radio_open(struct inode *inod if (NULL == btv) return -ENODEV; - dprintk("bttv%d: open called (radio)\n",btv->nr); + dprintk("bttv%d: open called (radio)\n",btv->c.nr); down(&btv->lock); if (btv->radio_user) { up(&btv->lock); @@ -3196,7 +3250,7 @@ bttv_irq_next_set(struct bttv *btv, stru dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p " "[screen=%p,irq=%d,%d]\n", - btv->nr,set->top, set->bottom, set->vbi, + btv->c.nr,set->top, set->bottom, set->vbi, btv->screen,set->irqflags,set->topirq); return 0; } @@ -3218,7 +3272,7 @@ bttv_irq_wakeup_set(struct bttv *btv, st if (wakeup->top == wakeup->bottom) { if (NULL != wakeup->top && curr->top != wakeup->top) { if (irq_debug > 1) - printk("bttv%d: wakeup: both=%p\n",btv->nr,wakeup->top); + printk("bttv%d: wakeup: both=%p\n",btv->c.nr,wakeup->top); wakeup->top->vb.ts = ts; wakeup->top->vb.field_count = btv->field_count; wakeup->top->vb.state = state; @@ -3227,7 +3281,7 @@ bttv_irq_wakeup_set(struct bttv *btv, st } else { if (NULL != wakeup->top && curr->top != wakeup->top) { if (irq_debug > 1) - printk("bttv%d: wakeup: top=%p\n",btv->nr,wakeup->top); + printk("bttv%d: wakeup: top=%p\n",btv->c.nr,wakeup->top); wakeup->top->vb.ts = ts; wakeup->top->vb.field_count = btv->field_count; wakeup->top->vb.state = state; @@ -3235,7 +3289,7 @@ bttv_irq_wakeup_set(struct bttv *btv, st } if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) { if (irq_debug > 1) - printk("bttv%d: wakeup: bottom=%p\n",btv->nr,wakeup->bottom); + printk("bttv%d: wakeup: bottom=%p\n",btv->c.nr,wakeup->bottom); wakeup->bottom->vb.ts = ts; wakeup->bottom->vb.field_count = btv->field_count; wakeup->bottom->vb.state = state; @@ -3249,15 +3303,17 @@ static void bttv_irq_timeout(unsigned lo struct bttv *btv = (struct bttv *)data; struct bttv_buffer_set old,new; struct bttv_buffer *item; + unsigned long flags; if (bttv_verbose) { - printk(KERN_INFO "bttv%d: timeout: risc=%08x, ", - btv->nr,btread(BT848_RISC_COUNT)); + printk(KERN_INFO "bttv%d: timeout: irq=%d/%d, risc=%08x, ", + btv->c.nr, btv->irq_me, btv->irq_total, + btread(BT848_RISC_COUNT)); bttv_print_irqbits(btread(BT848_INT_STAT),0); printk("\n"); } - spin_lock(&btv->s_lock); + spin_lock_irqsave(&btv->s_lock,flags); /* deactivate stuff */ memset(&new,0,sizeof(new)); @@ -3284,7 +3340,7 @@ static void bttv_irq_timeout(unsigned lo } btv->errors++; - spin_unlock(&btv->s_lock); + spin_unlock_irqrestore(&btv->s_lock,flags); } static void @@ -3321,8 +3377,13 @@ bttv_irq_switch_fields(struct bttv *btv) rc = btread(BT848_RISC_COUNT); if (rc < btv->main.dma || rc > btv->main.dma + 0x100) { if (1 /* irq_debug */) - printk("bttv%d: skipped frame. no signal? high irq latency?\n", - btv->nr); + printk("bttv%d: skipped frame. no signal? high irq latency? " + "[main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n", + btv->c.nr, + (unsigned long)btv->main.dma, + (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1], + (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1], + (unsigned long)rc); spin_unlock(&btv->s_lock); return; } @@ -3369,7 +3430,7 @@ static irqreturn_t bttv_irq(int irq, voi if (irq_debug) { printk(KERN_DEBUG "bttv%d: irq loop=%d fc=%d " "riscs=%x, riscc=%08x, ", - btv->nr, count, btv->field_count, + btv->c.nr, count, btv->field_count, stat>>28, btread(BT848_RISC_COUNT)); bttv_print_irqbits(stat,astat); if (stat & BT848_INT_HLOCK) @@ -3388,11 +3449,13 @@ static irqreturn_t bttv_irq(int irq, voi btv->field_count++; if (astat & BT848_INT_GPINT) { -#ifdef CONFIG_VIDEO_IR - if (btv->remote) - bttv_input_irq(btv); -#endif wake_up(&btv->gpioq); + bttv_gpio_irq(&btv->c); + } + + if (astat & BT848_INT_I2CDONE) { + btv->i2c_done = stat; + wake_up(&btv->i2c_queue); } if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) @@ -3405,7 +3468,7 @@ static irqreturn_t bttv_irq(int irq, voi audio_mux(btv, -1); if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) { - printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->nr, + printk(KERN_INFO "bttv%d: %s%s @ %08x,",btv->c.nr, (astat & BT848_INT_SCERR) ? "SCERR" : "", (astat & BT848_INT_OCERR) ? "OCERR" : "", btread(BT848_RISC_COUNT)); @@ -3416,7 +3479,7 @@ static irqreturn_t bttv_irq(int irq, voi } if (fdsr && astat & BT848_INT_FDSR) { printk(KERN_INFO "bttv%d: FDSR @ %08x\n", - btv->nr,btread(BT848_RISC_COUNT)); + btv->c.nr,btread(BT848_RISC_COUNT)); if (bttv_debug) bttv_print_riscaddr(btv); } @@ -3425,11 +3488,14 @@ static irqreturn_t bttv_irq(int irq, voi if (count > 4) { btwrite(0, BT848_INT_MASK); printk(KERN_ERR - "bttv%d: IRQ lockup, cleared int mask [", btv->nr); + "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); bttv_print_irqbits(stat,astat); printk("]\n"); } } + btv->irq_total++; + if (handled) + btv->irq_me++; return IRQ_RETVAL(handled); } @@ -3448,11 +3514,11 @@ static struct video_device *vdev_init(st return NULL; *vfd = *template; vfd->minor = -1; - vfd->dev = &btv->dev->dev; + vfd->dev = &btv->c.pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", - type, bttv_tvcards[btv->type].name); + type, bttv_tvcards[btv->c.type].name); return vfd; } @@ -3491,7 +3557,7 @@ static int __devinit bttv_register_video if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", - btv->nr,btv->video_dev->minor & 0x1f); + btv->c.nr,btv->video_dev->minor & 0x1f); video_device_create_file(btv->video_dev, &class_device_attr_card); /* vbi */ @@ -3501,7 +3567,7 @@ static int __devinit bttv_register_video if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", - btv->nr,btv->vbi_dev->minor & 0x1f); + btv->c.nr,btv->vbi_dev->minor & 0x1f); if (!btv->has_radio) return 0; @@ -3512,7 +3578,7 @@ static int __devinit bttv_register_video if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) goto err; printk(KERN_INFO "bttv%d: registered device radio%d\n", - btv->nr,btv->radio_dev->minor & 0x1f); + btv->c.nr,btv->radio_dev->minor & 0x1f); /* all done */ return 0; @@ -3548,14 +3614,17 @@ static int __devinit bttv_probe(struct p printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); btv=&bttvs[bttv_num]; memset(btv,0,sizeof(*btv)); - btv->nr = bttv_num; - sprintf(btv->name,"bttv%d",btv->nr); + btv->c.nr = bttv_num; + sprintf(btv->c.name,"bttv%d",btv->c.nr); /* initialize structs / fill in defaults */ init_MUTEX(&btv->lock); init_MUTEX(&btv->reslock); - btv->s_lock = SPIN_LOCK_UNLOCKED; + btv->s_lock = SPIN_LOCK_UNLOCKED; + btv->gpio_lock = SPIN_LOCK_UNLOCKED; init_waitqueue_head(&btv->gpioq); + init_waitqueue_head(&btv->i2c_queue); + INIT_LIST_HEAD(&btv->c.subs); INIT_LIST_HEAD(&btv->capture); INIT_LIST_HEAD(&btv->vcapture); #ifdef VIDIOC_G_PRIORITY @@ -3570,33 +3639,34 @@ static int __devinit bttv_probe(struct p btv->tuner_type = UNSET; btv->pinnacle_id = UNSET; btv->new_input = UNSET; - btv->has_radio=radio[btv->nr]; + btv->gpioirq = 1; + btv->has_radio=radio[btv->c.nr]; /* pci stuff (init, get irq/mmio, ... */ - btv->dev = dev; + btv->c.pci = dev; btv->id = dev->device; if (pci_enable_device(dev)) { printk(KERN_WARNING "bttv%d: Can't enable device.\n", - btv->nr); + btv->c.nr); return -EIO; } if (pci_set_dma_mask(dev, 0xffffffff)) { printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", - btv->nr); + btv->c.nr); return -EIO; } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), - btv->name)) { + btv->c.name)) { printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", - btv->nr, pci_resource_start(dev,0)); + btv->c.nr, pci_resource_start(dev,0)); return -EBUSY; } pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); if (!pci_dma_supported(dev,0xffffffff)) { - printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->nr); + printk("bttv%d: Oops: no 32bit PCI DMA ???\n", btv->c.nr); result = -EIO; goto fail1; } @@ -3606,12 +3676,12 @@ static int __devinit bttv_probe(struct p printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", bttv_num,btv->id, btv->revision, pci_name(dev)); printk("irq: %d, latency: %d, mmio: 0x%lx\n", - btv->dev->irq, lat, pci_resource_start(dev,0)); + btv->c.pci->irq, lat, pci_resource_start(dev,0)); schedule(); btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000); if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) { - printk("bttv%d: ioremap() failed\n", btv->nr); + printk("bttv%d: ioremap() failed\n", btv->c.nr); result = -EIO; goto fail1; } @@ -3621,11 +3691,11 @@ static int __devinit bttv_probe(struct p /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); - result = request_irq(btv->dev->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,btv->name,(void *)btv); + result = request_irq(btv->c.pci->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); if (result < 0) { printk(KERN_ERR "bttv%d: can't get IRQ %d\n", - bttv_num,btv->dev->irq); + bttv_num,btv->c.pci->irq); goto fail1; } @@ -3641,6 +3711,8 @@ static int __devinit bttv_probe(struct p btv->opt_chroma_agc = chroma_agc; btv->opt_adc_crush = adc_crush; btv->opt_vcr_hack = vcr_hack; + btv->opt_whitecrush_upper = whitecrush_upper; + btv->opt_whitecrush_lower = whitecrush_lower; /* fill struct bttv with some useful defaults */ btv->init.btv = btv; @@ -3657,31 +3729,27 @@ static int __devinit bttv_probe(struct p bttv_gpio_tracking(btv,"pre-init"); bttv_risc_init_main(btv); - if (!bttv_tvcards[btv->type].no_video) - init_bt848(btv); + init_bt848(btv); /* gpio */ btwrite(0x00, BT848_GPIO_REG_INP); btwrite(0x00, BT848_GPIO_OUT_EN); - if (bttv_gpio) + if (bttv_verbose) bttv_gpio_tracking(btv,"init"); /* needs to be done before i2c is registered */ bttv_init_card1(btv); - /* register i2c */ + /* register i2c + gpio */ init_bttv_i2c(btv); /* some card-specific stuff (needs working i2c) */ bttv_init_card2(btv); + init_irqreg(btv); /* register video4linux + input */ - if (!bttv_tvcards[btv->type].no_video) { + if (!bttv_tvcards[btv->c.type].no_video) { bttv_register_video(btv); -#ifdef CONFIG_VIDEO_IR - bttv_input_init(btv); -#endif - bt848_bright(btv,32768); bt848_contrast(btv,32768); bt848_hue(btv,32768); @@ -3690,18 +3758,24 @@ static int __devinit bttv_probe(struct p set_input(btv,0); } + /* add subdevices */ + if (btv->has_remote) + bttv_sub_add_device(&btv->c, "remote"); + if (bttv_tvcards[btv->c.type].has_dvb) + bttv_sub_add_device(&btv->c, "dvb"); + /* everything is fine */ bttv_num++; return 0; fail2: - free_irq(btv->dev->irq,btv); + free_irq(btv->c.pci->irq,btv); fail1: if (btv->bt848_mmio) iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->dev,0), - pci_resource_len(btv->dev,0)); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); pci_set_drvdata(dev,NULL); return result; } @@ -3711,7 +3785,7 @@ static void __devexit bttv_remove(struct struct bttv *btv = pci_get_drvdata(pci_dev); if (bttv_verbose) - printk("bttv%d: unloading\n",btv->nr); + printk("bttv%d: unloading\n",btv->c.nr); /* shutdown everything (DMA+IRQs) */ btand(~15, BT848_GPIO_DMA_CTL); @@ -3724,29 +3798,92 @@ static void __devexit bttv_remove(struct /* tell gpio modules we are leaving ... */ btv->shutdown=1; wake_up(&btv->gpioq); - + bttv_sub_del_devices(&btv->c); + /* unregister i2c_bus + input */ fini_bttv_i2c(btv); -#ifdef CONFIG_VIDEO_IR - bttv_input_fini(btv); -#endif /* unregister video4linux */ bttv_unregister_video(btv); /* free allocated memory */ - btcx_riscmem_free(btv->dev,&btv->main); + btcx_riscmem_free(btv->c.pci,&btv->main); /* free ressources */ - free_irq(btv->dev->irq,btv); + free_irq(btv->c.pci->irq,btv); iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->dev,0), - pci_resource_len(btv->dev,0)); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); pci_set_drvdata(pci_dev, NULL); return; } +static int bttv_suspend(struct pci_dev *pci_dev, u32 state) +{ + struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv_buffer_set idle; + unsigned long flags; + + printk("bttv%d: suspend %d\n", btv->c.nr, state); + + /* stop dma + irqs */ + spin_lock_irqsave(&btv->s_lock,flags); + memset(&idle, 0, sizeof(idle)); + btv->state.set = btv->curr; + btv->curr = idle; + bttv_buffer_set_activate(btv, &idle); + bttv_set_dma(btv, 0, 0); + btwrite(0, BT848_INT_MASK); + spin_unlock_irqrestore(&btv->s_lock,flags); + + /* save bt878 state */ + btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN); + btv->state.gpio_data = gpio_read(); + + /* save pci state */ + pci_save_state(pci_dev, btv->state.pci_cfg); + if (0 != pci_set_power_state(pci_dev, state)) { + pci_disable_device(pci_dev); + btv->state.disabled = 1; + } + return 0; +} + +static int bttv_resume(struct pci_dev *pci_dev) +{ + struct bttv *btv = pci_get_drvdata(pci_dev); + unsigned long flags; + + printk("bttv%d: resume\n", btv->c.nr); + + /* restore pci state */ + if (btv->state.disabled) { + pci_enable_device(pci_dev); + btv->state.disabled = 0; + } + pci_set_power_state(pci_dev, 0); + pci_restore_state(pci_dev, btv->state.pci_cfg); + + /* restore bt878 state */ + bttv_reinit_bt848(btv); + gpio_inout(0xffffff, btv->state.gpio_enable); + gpio_write(btv->state.gpio_data); + + bt848_bright(btv, btv->bright); + bt848_hue(btv, btv->hue); + bt848_contrast(btv, btv->contrast); + bt848_sat(btv, btv->saturation); + + /* restart dma */ + spin_lock_irqsave(&btv->s_lock,flags); + btv->curr = btv->state.set; + bttv_buffer_set_activate(btv, &btv->curr); + bttv_set_dma(btv, 0, btv->curr.irqflags); + spin_unlock_irqrestore(&btv->s_lock,flags); + return 0; +} + static struct pci_device_id bttv_pci_tbl[] = { {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, @@ -3766,6 +3903,9 @@ static struct pci_driver bttv_pci_driver .id_table = bttv_pci_tbl, .probe = bttv_probe, .remove = __devexit_p(bttv_remove), + + .suspend = bttv_suspend, + .resume = bttv_resume, }; static int bttv_init_module(void) @@ -3777,6 +3917,10 @@ static int bttv_init_module(void) (BTTV_VERSION_CODE >> 16) & 0xff, (BTTV_VERSION_CODE >> 8) & 0xff, BTTV_VERSION_CODE & 0xff); +#ifdef SNAPSHOT + printk(KERN_INFO "bttv: snapshot date %04d-%02d-%02d\n", + SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); +#endif if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) gbuffers = 2; if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) @@ -3788,6 +3932,7 @@ static int bttv_init_module(void) bttv_check_chipset(); + bus_register(&bttv_sub_bus_type); rc = pci_module_init(&bttv_pci_driver); if (-ENODEV == rc) { /* plenty of people trying to use bttv for the cx2388x ... */ @@ -3800,6 +3945,7 @@ static int bttv_init_module(void) static void bttv_cleanup_module(void) { pci_unregister_driver(&bttv_pci_driver); + bus_unregister(&bttv_sub_bus_type); return; } diff -puN /dev/null drivers/media/video/bttv-gpio.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/drivers/media/video/bttv-gpio.c 2004-01-15 08:27:42.000000000 -0800 @@ -0,0 +1,183 @@ +/* + bttv-gpio.c -- gpio sub drivers + + sysfs-based sub driver interface for bttv + mainly intented for gpio access + + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + (c) 1999-2003 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include + +#include "bttvp.h" + +/* ----------------------------------------------------------------------- */ +/* internal: the bttv "bus" */ + +static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) +{ + struct bttv_sub_driver *sub = to_bttv_sub_drv(drv); + int len = strlen(sub->wanted); + + if (0 == strncmp(dev->bus_id, sub->wanted, len)) + return 1; + return 0; +} + +struct bus_type bttv_sub_bus_type = { + .name = "bttv-sub", + .match = &bttv_sub_bus_match, +}; +EXPORT_SYMBOL(bttv_sub_bus_type); + +static void release_sub_device(struct device *dev) +{ + struct bttv_sub_device *sub = to_bttv_sub_dev(dev); + kfree(sub); +} + +int bttv_sub_add_device(struct bttv_core *core, char *name) +{ + struct bttv_sub_device *sub; + + sub = kmalloc(sizeof(*sub),GFP_KERNEL); + if (NULL == sub) + return -ENOMEM; + memset(sub,0,sizeof(*sub)); + + sub->core = core; + sub->dev.parent = &core->pci->dev; + sub->dev.bus = &bttv_sub_bus_type; + sub->dev.release = release_sub_device; + snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d", + name, core->nr); + + printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id); + list_add_tail(&sub->list,&core->subs); + device_register(&sub->dev); + return 0; +} + +int bttv_sub_del_devices(struct bttv_core *core) +{ + struct bttv_sub_device *sub; + struct list_head *item,*save; + + list_for_each_safe(item,save,&core->subs) { + sub = list_entry(item,struct bttv_sub_device,list); + device_unregister(&sub->dev); + } + return 0; +} + +void bttv_gpio_irq(struct bttv_core *core) +{ + struct bttv_sub_driver *drv; + struct bttv_sub_device *dev; + struct list_head *item; + + list_for_each(item,&core->subs) { + dev = list_entry(item,struct bttv_sub_device,list); + drv = to_bttv_sub_drv(dev->dev.driver); + if (drv && drv->gpio_irq) + drv->gpio_irq(dev); + } +} + +/* ----------------------------------------------------------------------- */ +/* external: sub-driver register/unregister */ + +int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted) +{ + sub->drv.bus = &bttv_sub_bus_type; + snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted); + driver_register(&sub->drv); + return 0; +} +EXPORT_SYMBOL(bttv_sub_register); + +int bttv_sub_unregister(struct bttv_sub_driver *sub) +{ + driver_unregister(&sub->drv); + return 0; +} +EXPORT_SYMBOL(bttv_sub_unregister); + +/* ----------------------------------------------------------------------- */ +/* external: gpio access functions */ + +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits) +{ + struct bttv *btv = container_of(core, struct bttv, c); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&btv->gpio_lock,flags); + data = btread(BT848_GPIO_OUT_EN); + data = data & ~mask; + data = data | (mask & outbits); + btwrite(data,BT848_GPIO_OUT_EN); + spin_unlock_irqrestore(&btv->gpio_lock,flags); +} +EXPORT_SYMBOL(bttv_gpio_inout); + +u32 bttv_gpio_read(struct bttv_core *core) +{ + struct bttv *btv = container_of(core, struct bttv, c); + u32 value; + + value = btread(BT848_GPIO_DATA); + return value; +} +EXPORT_SYMBOL(bttv_gpio_read); + +void bttv_gpio_write(struct bttv_core *core, u32 value) +{ + struct bttv *btv = container_of(core, struct bttv, c); + + btwrite(value,BT848_GPIO_DATA); +} +EXPORT_SYMBOL(bttv_gpio_write); + +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits) +{ + struct bttv *btv = container_of(core, struct bttv, c); + unsigned long flags; + u32 data; + + spin_lock_irqsave(&btv->gpio_lock,flags); + data = btread(BT848_GPIO_DATA); + data = data & ~mask; + data = data | (mask & bits); + btwrite(data,BT848_GPIO_DATA); + spin_unlock_irqrestore(&btv->gpio_lock,flags); +} +EXPORT_SYMBOL(bttv_gpio_bits); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -puN drivers/media/video/bttv.h~v4l-04-bttv-driver-update drivers/media/video/bttv.h --- 25/drivers/media/video/bttv.h~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttv.h 2004-01-15 08:27:42.000000000 -0800 @@ -14,6 +14,7 @@ #define _BTTV_H_ #include +#include /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ @@ -117,6 +118,12 @@ #define BTTV_PV143 0x69 #define BTTV_IVC100 0x6e #define BTTV_IVC120 0x6f +#define BTTV_PC_HDTV 0x70 +#define BTTV_TWINHAN_DST 0x71 +#define BTTV_WINFASTVC100 0x72 +#define BTTV_SIMUS_GVC1100 0x74 +#define BTTV_NGSTV_PLUS 0x75 +#define BTTV_LMLBT4 0x76 /* i2c address list */ #define I2C_TSA5522 0xc2 @@ -150,6 +157,18 @@ #define DIGITAL_MODE_VIDEO 1 #define DIGITAL_MODE_CAMERA 2 +struct bttv_core { + /* device structs */ + struct pci_dev *pci; + struct i2c_adapter i2c_adap; + struct list_head subs; /* struct bttv_sub_device */ + + /* device config */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int type; /* card type (pointer into tvcards[]) */ + char name[8]; /* dev name */ +}; + struct bttv; struct tvcard @@ -173,7 +192,10 @@ struct tvcard unsigned int msp34xx_alt:1; /* flag: video pci function is unused */ - unsigned int no_video; + unsigned int no_video:1; + unsigned int has_dvb:1; + unsigned int has_remote:1; + unsigned int no_gpioirq:1; /* other settings */ unsigned int pll; @@ -208,7 +230,9 @@ extern int bttv_handle_chipset(struct bt /* ---------------------------------------------------------- */ /* exported by bttv-if.c */ -/* interface for gpio access by other modules */ + +/* this obsolete -- please use the sysfs-based + interface below for new code */ /* returns card type + card ID (for bt878-based ones) for possible values see lines below beginning with #define BTTV_UNKNOWN @@ -256,7 +280,43 @@ extern wait_queue_head_t* bttv_get_gpio_ extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg); -/* i2c */ + +/* ---------------------------------------------------------- */ +/* sysfs/driver-moded based gpio access interface */ + + +struct bttv_sub_device { + struct device dev; + struct bttv_core *core; + struct list_head list; +}; +#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev) + +struct bttv_sub_driver { + struct device_driver drv; + char wanted[BUS_ID_SIZE]; + void (*gpio_irq)(struct bttv_sub_device *sub); +}; +#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) + +int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted); +int bttv_sub_unregister(struct bttv_sub_driver *drv); + +/* gpio access functions */ +void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits); +u32 bttv_gpio_read(struct bttv_core *core); +void bttv_gpio_write(struct bttv_core *core, u32 value); +void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits); + +#define gpio_inout(mask,bits) bttv_gpio_inout(&btv->c, mask, bits) +#define gpio_read() bttv_gpio_read(&btv->c) +#define gpio_write(value) bttv_gpio_write(&btv->c, value) +#define gpio_bits(mask,bits) bttv_gpio_bits(&btv->c, mask, bits) + + +/* ---------------------------------------------------------- */ +/* i2c */ + extern void bttv_bit_setscl(void *data, int state); extern void bttv_bit_setsda(void *data, int state); extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); diff -puN /dev/null drivers/media/video/bttv-i2c.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/drivers/media/video/bttv-i2c.c 2004-01-15 08:27:42.000000000 -0800 @@ -0,0 +1,471 @@ +/* + bttv-i2c.c -- all the i2c code is here + + bttv - Bt848 frame grabber driver + + Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) + (c) 1999-2003 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include + +#include "bttvp.h" + +static struct i2c_algo_bit_data bttv_i2c_algo_bit_template; +static struct i2c_adapter bttv_i2c_adap_sw_template; +static struct i2c_adapter bttv_i2c_adap_hw_template; +static struct i2c_client bttv_i2c_client_template; + +#ifndef I2C_PEC +static void bttv_inc_use(struct i2c_adapter *adap); +static void bttv_dec_use(struct i2c_adapter *adap); +#endif +static int attach_inform(struct i2c_client *client); + +static int i2c_debug = 0; +static int i2c_hw = 0; +MODULE_PARM(i2c_debug,"i"); +MODULE_PARM(i2c_hw,"i"); + +/* ----------------------------------------------------------------------- */ +/* I2C functions - bitbanging adapter (software i2c) */ + +void bttv_bit_setscl(void *data, int state) +{ + struct bttv *btv = (struct bttv*)data; + + if (state) + btv->i2c_state |= 0x02; + else + btv->i2c_state &= ~0x02; + btwrite(btv->i2c_state, BT848_I2C); + btread(BT848_I2C); +} + +void bttv_bit_setsda(void *data, int state) +{ + struct bttv *btv = (struct bttv*)data; + + if (state) + btv->i2c_state |= 0x01; + else + btv->i2c_state &= ~0x01; + btwrite(btv->i2c_state, BT848_I2C); + btread(BT848_I2C); +} + +static int bttv_bit_getscl(void *data) +{ + struct bttv *btv = (struct bttv*)data; + int state; + + state = btread(BT848_I2C) & 0x02 ? 1 : 0; + return state; +} + +static int bttv_bit_getsda(void *data) +{ + struct bttv *btv = (struct bttv*)data; + int state; + + state = btread(BT848_I2C) & 0x01; + return state; +} + +static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { + .setsda = bttv_bit_setsda, + .setscl = bttv_bit_setscl, + .getsda = bttv_bit_getsda, + .getscl = bttv_bit_getscl, + .udelay = 16, + .mdelay = 10, + .timeout = 200, +}; + +static struct i2c_adapter bttv_i2c_adap_sw_template = { +#ifdef I2C_PEC + .owner = THIS_MODULE, +#else + .inc_use = bttv_inc_use, + .dec_use = bttv_dec_use, +#endif +#ifdef I2C_ADAP_CLASS_TV_ANALOG + .class = I2C_ADAP_CLASS_TV_ANALOG, +#endif + I2C_DEVNAME("bt848"), + .id = I2C_HW_B_BT848, + .client_register = attach_inform, +}; + +/* ----------------------------------------------------------------------- */ +/* I2C functions - hardware i2c */ + +static int algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static u32 functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static int +bttv_i2c_wait_done(struct bttv *btv) +{ + DECLARE_WAITQUEUE(wait, current); + int rc = 0; + + add_wait_queue(&btv->i2c_queue, &wait); + set_current_state(TASK_INTERRUPTIBLE); + if (0 == btv->i2c_done) + schedule_timeout(HZ/50+1); + set_current_state(TASK_RUNNING); + remove_wait_queue(&btv->i2c_queue, &wait); + + if (0 == btv->i2c_done) + /* timeout */ + rc = -EIO; + if (btv->i2c_done & BT848_INT_RACK) + rc = 1; + btv->i2c_done = 0; + return rc; +} + +#define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\ + BT848_I2C_SCL | BT848_I2C_SDA) + +static int +bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last) +{ + u32 xmit; + int retval,cnt; + + /* sanity checks */ + if (0 == msg->len) + return -EINVAL; + + /* start, address + first byte */ + xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW; + if (msg->len > 1 || !last) + xmit |= BT878_I2C_NOSTOP; + btwrite(xmit, BT848_I2C); + retval = bttv_i2c_wait_done(btv); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + if (i2c_debug) { + printk(" addr << 1, msg->buf[0]); + if (!(xmit & BT878_I2C_NOSTOP)) + printk(" >\n"); + } + + for (cnt = 1; cnt < msg->len; cnt++ ) { + /* following bytes */ + xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART; + if (cnt < msg->len-1 || !last) + xmit |= BT878_I2C_NOSTOP; + btwrite(xmit, BT848_I2C); + retval = bttv_i2c_wait_done(btv); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + if (i2c_debug) { + printk(" %02x", msg->buf[cnt]); + if (!(xmit & BT878_I2C_NOSTOP)) + printk(" >\n"); + } + } + return msg->len; + + eio: + retval = -EIO; + err: + if (i2c_debug) + printk(" ERR: %d\n",retval); + return retval; +} + +static int +bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) +{ + u32 xmit; + u32 cnt; + int retval; + + for(cnt = 0; cnt < msg->len; cnt++) { + xmit = (msg->addr << 25) | (1 << 24) | I2C_HW; + if (cnt < msg->len-1) + xmit |= BT848_I2C_W3B; + if (cnt < msg->len-1 || !last) + xmit |= BT878_I2C_NOSTOP; + if (cnt) + xmit |= BT878_I2C_NOSTART; + btwrite(xmit, BT848_I2C); + retval = bttv_i2c_wait_done(btv); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff; + if (i2c_debug) { + if (!(xmit & BT878_I2C_NOSTART)) + printk(" addr << 1) +1); + printk(" =%02x", msg->buf[cnt]); + if (!(xmit & BT878_I2C_NOSTOP)) + printk(" >\n"); + } + } + return msg->len; + + eio: + retval = -EIO; + err: + if (i2c_debug) + printk(" ERR: %d\n",retval); + return retval; +} + +int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +{ + struct bttv *btv = i2c_get_adapdata(i2c_adap); + int retval = 0; + int i; + + if (i2c_debug) + printk("bt-i2c:"); + btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT); + for (i = 0 ; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) { + /* read */ + retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num); + if (retval < 0) + goto err; + } else { + /* write */ + retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num); + if (retval < 0) + goto err; + } + } + return num; + + err: + return retval; +} + +static struct i2c_algorithm bttv_algo = { + .name = "bt878", + .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, + .master_xfer = bttv_i2c_xfer, + .algo_control = algo_control, + .functionality = functionality, +}; + +static struct i2c_adapter bttv_i2c_adap_hw_template = { +#ifdef I2C_PEC + .owner = THIS_MODULE, +#else + .inc_use = bttv_inc_use, + .dec_use = bttv_dec_use, +#endif +#ifdef I2C_ADAP_CLASS_TV_ANALOG + .class = I2C_ADAP_CLASS_TV_ANALOG, +#endif + I2C_DEVNAME("bt878"), + .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, + .algo = &bttv_algo, + .client_register = attach_inform, +}; + +/* ----------------------------------------------------------------------- */ +/* I2C functions - common stuff */ + +#ifndef I2C_PEC +static void bttv_inc_use(struct i2c_adapter *adap) +{ + MOD_INC_USE_COUNT; +} + +static void bttv_dec_use(struct i2c_adapter *adap) +{ + MOD_DEC_USE_COUNT; +} +#endif + +static int attach_inform(struct i2c_client *client) +{ + struct bttv *btv = i2c_get_adapdata(client->adapter); + + if (btv->tuner_type != UNSET) + bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); + if (btv->pinnacle_id != UNSET) + bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE, + &btv->pinnacle_id); + + if (bttv_debug) + printk("bttv%d: i2c attach [client=%s]\n", + btv->c.nr, i2c_clientname(client)); + return 0; +} + +void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) +{ + if (0 != btv->i2c_rc) + return; + i2c_clients_command(&btv->c.i2c_adap, cmd, arg); +} + +void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) +{ + if (card >= bttv_num) + return; + bttv_call_i2c_clients(&bttvs[card], cmd, arg); +} + +static struct i2c_client bttv_i2c_client_template = { + I2C_DEVNAME("bttv internal"), + .id = -1, +}; + + +/* read I2C */ +int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) +{ + unsigned char buffer = 0; + + if (0 != btv->i2c_rc) + return -1; + if (bttv_verbose && NULL != probe_for) + printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", + btv->c.nr,probe_for,addr); + btv->i2c_client.addr = addr >> 1; + if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { + if (NULL != probe_for) { + if (bttv_verbose) + printk("not found\n"); + } else + printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", + btv->c.nr,addr); + return -1; + } + if (bttv_verbose && NULL != probe_for) + printk("found\n"); + return buffer; +} + +/* write I2C */ +int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, + unsigned char b2, int both) +{ + unsigned char buffer[2]; + int bytes = both ? 2 : 1; + + if (0 != btv->i2c_rc) + return -1; + btv->i2c_client.addr = addr >> 1; + buffer[0] = b1; + buffer[1] = b2; + if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) + return -1; + return 0; +} + +/* read EEPROM content */ +void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) +{ + int i; + + if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) { + printk(KERN_WARNING "bttv: readee error\n"); + return; + } + btv->i2c_client.addr = addr >> 1; + for (i=0; i<256; i+=16) { + if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) { + printk(KERN_WARNING "bttv: readee error\n"); + break; + } + } +} + +/* init + register i2c algo-bit adapter */ +int __devinit init_bttv_i2c(struct bttv *btv) +{ + int use_hw = (btv->id == 878) && i2c_hw; + + memcpy(&btv->i2c_client, &bttv_i2c_client_template, + sizeof(bttv_i2c_client_template)); + + if (use_hw) { + /* bt878 */ + memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_hw_template, + sizeof(bttv_i2c_adap_hw_template)); + } else { + /* bt848 */ + memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_sw_template, + sizeof(bttv_i2c_adap_sw_template)); + memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, + sizeof(bttv_i2c_algo_bit_template)); + btv->i2c_algo.data = btv; + btv->c.i2c_adap.algo_data = &btv->i2c_algo; + } + + btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; + snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), + "bt%d #%d [%s]", btv->id, btv->c.nr, use_hw ? "hw" : "sw"); + + i2c_set_adapdata(&btv->c.i2c_adap, btv); + btv->i2c_client.adapter = &btv->c.i2c_adap; + + if (use_hw) { + btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap); + } else { + bttv_bit_setscl(btv,1); + bttv_bit_setsda(btv,1); + btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap); + } + return btv->i2c_rc; +} + +int __devexit fini_bttv_i2c(struct bttv *btv) +{ + int use_hw = (btv->id == 878) && i2c_hw; + + if (0 != btv->i2c_rc) + return 0; + + if (use_hw) { + return i2c_del_adapter(&btv->c.i2c_adap); + } else { + return i2c_bit_del_bus(&btv->c.i2c_adap); + } +} + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -puN drivers/media/video/bttv-if.c~v4l-04-bttv-driver-update drivers/media/video/bttv-if.c --- 25/drivers/media/video/bttv-if.c~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttv-if.c 2004-01-15 08:27:42.000000000 -0800 @@ -1,7 +1,7 @@ /* - bttv-if.c -- interfaces to other kernel modules - all the i2c code is here - also the gpio interface exported by bttv (used by lirc) + bttv-if.c -- old gpio interface to other kernel modules + don't use in new code, will go away in 2.7 + have a look at bttv-gpio.c instead. bttv - Bt848 frame grabber driver @@ -28,22 +28,10 @@ #include #include #include - #include #include "bttvp.h" -static struct i2c_algo_bit_data bttv_i2c_algo_bit_template; -static struct i2c_adapter bttv_i2c_adap_sw_template; -static struct i2c_adapter bttv_i2c_adap_hw_template; -static struct i2c_client bttv_i2c_client_template; - -#ifndef I2C_PEC -static void bttv_inc_use(struct i2c_adapter *adap); -static void bttv_dec_use(struct i2c_adapter *adap); -#endif -static int attach_inform(struct i2c_client *client); - EXPORT_SYMBOL(bttv_get_cardinfo); EXPORT_SYMBOL(bttv_get_pcidev); EXPORT_SYMBOL(bttv_get_id); @@ -53,11 +41,6 @@ EXPORT_SYMBOL(bttv_write_gpio); EXPORT_SYMBOL(bttv_get_gpio_queue); EXPORT_SYMBOL(bttv_i2c_call); -static int i2c_debug = 0; -static int i2c_hw = 0; -MODULE_PARM(i2c_debug,"i"); -MODULE_PARM(i2c_hw,"i"); - /* ----------------------------------------------------------------------- */ /* Exported functions - for other modules which want to access the */ /* gpio ports (IR for example) */ @@ -68,7 +51,7 @@ int bttv_get_cardinfo(unsigned int card, if (card >= bttv_num) { return -1; } - *type = bttvs[card].type; + *type = bttvs[card].c.type; *cardid = bttvs[card].cardid; return 0; } @@ -77,7 +60,7 @@ struct pci_dev* bttv_get_pcidev(unsigned { if (card >= bttv_num) return NULL; - return bttvs[card].dev; + return bttvs[card].c.pci; } int bttv_get_id(unsigned int card) @@ -86,7 +69,7 @@ int bttv_get_id(unsigned int card) if (card >= bttv_num) { return -1; } - return bttvs[card].type; + return bttvs[card].c.type; } @@ -99,7 +82,7 @@ int bttv_gpio_enable(unsigned int card, } btv = &bttvs[card]; - btaor(data, ~mask, BT848_GPIO_OUT_EN); + gpio_inout(mask,data); if (bttv_gpio) bttv_gpio_tracking(btv,"extern enable"); return 0; @@ -121,7 +104,7 @@ int bttv_read_gpio(unsigned int card, un /* prior setting BT848_GPIO_REG_INP is (probably) not needed because we set direct input on init */ - *data = btread(BT848_GPIO_DATA); + *data = gpio_read(); return 0; } @@ -137,7 +120,7 @@ int bttv_write_gpio(unsigned int card, u /* prior setting BT848_GPIO_REG_INP is (probably) not needed because direct input is set on init */ - btaor(data & mask, ~mask, BT848_GPIO_DATA); + gpio_bits(mask,data); if (bttv_gpio) bttv_gpio_tracking(btv,"extern write"); return 0; @@ -158,418 +141,6 @@ wait_queue_head_t* bttv_get_gpio_queue(u return &btv->gpioq; } - -/* ----------------------------------------------------------------------- */ -/* I2C functions - bitbanging adapter (software i2c) */ - -void bttv_bit_setscl(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x02; - else - btv->i2c_state &= ~0x02; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -void bttv_bit_setsda(void *data, int state) -{ - struct bttv *btv = (struct bttv*)data; - - if (state) - btv->i2c_state |= 0x01; - else - btv->i2c_state &= ~0x01; - btwrite(btv->i2c_state, BT848_I2C); - btread(BT848_I2C); -} - -static int bttv_bit_getscl(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x02 ? 1 : 0; - return state; -} - -static int bttv_bit_getsda(void *data) -{ - struct bttv *btv = (struct bttv*)data; - int state; - - state = btread(BT848_I2C) & 0x01; - return state; -} - -static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { - .setsda = bttv_bit_setsda, - .setscl = bttv_bit_setscl, - .getsda = bttv_bit_getsda, - .getscl = bttv_bit_getscl, - .udelay = 16, - .mdelay = 10, - .timeout = 200, -}; - -static struct i2c_adapter bttv_i2c_adap_sw_template = { -#ifdef I2C_PEC - .owner = THIS_MODULE, -#else - .inc_use = bttv_inc_use, - .dec_use = bttv_dec_use, -#endif -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, -#endif - I2C_DEVNAME("bt848"), - .id = I2C_HW_B_BT848, - .client_register = attach_inform, -}; - -/* ----------------------------------------------------------------------- */ -/* I2C functions - hardware i2c */ - -static int algo_control(struct i2c_adapter *adapter, - unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static u32 functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL; -} - -static int -bttv_i2c_wait_done(struct bttv *btv) -{ - u32 stat; - unsigned long timeout; - - timeout = jiffies + HZ/100 + 1; /* 10ms */ - for (;;) { - stat = btread(BT848_INT_STAT); - if (stat & BT848_INT_I2CDONE) - break; - if (time_after(jiffies,timeout)) - return -EIO; - udelay(10); - } - btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT); - return ((stat & BT848_INT_RACK) ? 1 : 0); -} - -#define I2C_HW (BT878_I2C_MODE | BT848_I2C_SYNC |\ - BT848_I2C_SCL | BT848_I2C_SDA) - -static int -bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last) -{ - u32 xmit; - int retval,cnt; - - /* start, address + first byte */ - xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW; - if (msg->len > 1 || !last) - xmit |= BT878_I2C_NOSTOP; - btwrite(xmit, BT848_I2C); - retval = bttv_i2c_wait_done(btv); - if (retval < 0) - goto err; - if (retval == 0) - goto eio; - if (i2c_debug) { - printk(" addr << 1, msg->buf[0]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); - } - - for (cnt = 1; cnt < msg->len; cnt++ ) { - /* following bytes */ - xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART; - if (cnt < msg->len-1 || !last) - xmit |= BT878_I2C_NOSTOP; - btwrite(xmit, BT848_I2C); - retval = bttv_i2c_wait_done(btv); - if (retval < 0) - goto err; - if (retval == 0) - goto eio; - if (i2c_debug) { - printk(" %02x", msg->buf[cnt]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); - } - } - return msg->len; - - eio: - retval = -EIO; - err: - if (i2c_debug) - printk(" ERR: %d\n",retval); - return retval; -} - -static int -bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) -{ - u32 xmit; - u32 cnt; - int retval; - - for(cnt = 0; cnt < msg->len; cnt++) { - xmit = (msg->addr << 25) | (1 << 24) | I2C_HW; - if (cnt < msg->len-1) - xmit |= BT848_I2C_W3B; - if (cnt < msg->len-1 || !last) - xmit |= BT878_I2C_NOSTOP; - if (cnt) - xmit |= BT878_I2C_NOSTART; - btwrite(xmit, BT848_I2C); - retval = bttv_i2c_wait_done(btv); - if (retval < 0) - goto err; - if (retval == 0) - goto eio; - msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff; - if (i2c_debug) { - if (!(xmit & BT878_I2C_NOSTART)) - printk(" addr << 1) +1); - printk(" =%02x", msg->buf[cnt]); - if (!(xmit & BT878_I2C_NOSTOP)) - printk(" >\n"); - } - } - return msg->len; - - eio: - retval = -EIO; - err: - if (i2c_debug) - printk(" ERR: %d\n",retval); - return retval; -} - -int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -{ - struct bttv *btv = i2c_get_adapdata(i2c_adap); - int retval = 0; - int i; - - if (i2c_debug) - printk("bt-i2c:"); - btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT); - for (i = 0 ; i < num; i++) { - if (msgs[i].flags & I2C_M_RD) { - /* read */ - retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num); - if (retval < 0) - goto err; - } else { - /* write */ - retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num); - if (retval < 0) - goto err; - } - } - return num; - - err: - return retval; -} - -static struct i2c_algorithm bttv_algo = { - .name = "bt878", - .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, - .master_xfer = bttv_i2c_xfer, - .algo_control = algo_control, - .functionality = functionality, -}; - -static struct i2c_adapter bttv_i2c_adap_hw_template = { -#ifdef I2C_PEC - .owner = THIS_MODULE, -#else - .inc_use = bttv_inc_use, - .dec_use = bttv_dec_use, -#endif -#ifdef I2C_ADAP_CLASS_TV_ANALOG - .class = I2C_ADAP_CLASS_TV_ANALOG, -#endif - I2C_DEVNAME("bt878"), - .id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */, - .algo = &bttv_algo, - .client_register = attach_inform, -}; - -/* ----------------------------------------------------------------------- */ -/* I2C functions - common stuff */ - -#ifndef I2C_PEC -static void bttv_inc_use(struct i2c_adapter *adap) -{ - MOD_INC_USE_COUNT; -} - -static void bttv_dec_use(struct i2c_adapter *adap) -{ - MOD_DEC_USE_COUNT; -} -#endif - -static int attach_inform(struct i2c_client *client) -{ - struct bttv *btv = i2c_get_adapdata(client->adapter); - - if (btv->tuner_type != UNSET) - bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - if (btv->pinnacle_id != UNSET) - bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE, - &btv->pinnacle_id); - - if (bttv_debug) - printk("bttv%d: i2c attach [client=%s]\n", - btv->nr, i2c_clientname(client)); - return 0; -} - -void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) -{ - if (0 != btv->i2c_rc) - return; - i2c_clients_command(&btv->i2c_adap, cmd, arg); -} - -void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) -{ - if (card >= bttv_num) - return; - bttv_call_i2c_clients(&bttvs[card], cmd, arg); -} - -static struct i2c_client bttv_i2c_client_template = { - I2C_DEVNAME("bttv internal"), - .id = -1, -}; - - -/* read I2C */ -int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) -{ - unsigned char buffer = 0; - - if (0 != btv->i2c_rc) - return -1; - if (bttv_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) { - if (bttv_verbose) - printk("not found\n"); - } else - printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", - btv->nr,addr); - return -1; - } - if (bttv_verbose && NULL != probe_for) - printk("found\n"); - return buffer; -} - -/* write I2C */ -int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both) -{ - unsigned char buffer[2]; - int bytes = both ? 2 : 1; - - if (0 != btv->i2c_rc) - return -1; - btv->i2c_client.addr = addr >> 1; - buffer[0] = b1; - buffer[1] = b2; - if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) - return -1; - return 0; -} - -/* read EEPROM content */ -void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr) -{ - int i; - - if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) { - printk(KERN_WARNING "bttv: readee error\n"); - return; - } - btv->i2c_client.addr = addr >> 1; - for (i=0; i<256; i+=16) { - if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) { - printk(KERN_WARNING "bttv: readee error\n"); - break; - } - } -} - -/* init + register i2c algo-bit adapter */ -int __devinit init_bttv_i2c(struct bttv *btv) -{ - int use_hw = (btv->id == 878) && i2c_hw; - - memcpy(&btv->i2c_client, &bttv_i2c_client_template, - sizeof(bttv_i2c_client_template)); - - if (use_hw) { - /* bt878 */ - memcpy(&btv->i2c_adap, &bttv_i2c_adap_hw_template, - sizeof(bttv_i2c_adap_hw_template)); - } else { - /* bt848 */ - memcpy(&btv->i2c_adap, &bttv_i2c_adap_sw_template, - sizeof(bttv_i2c_adap_sw_template)); - memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, - sizeof(bttv_i2c_algo_bit_template)); - btv->i2c_algo.data = btv; - btv->i2c_adap.algo_data = &btv->i2c_algo; - } - - btv->i2c_adap.dev.parent = &btv->dev->dev; - snprintf(btv->i2c_adap.name, sizeof(btv->i2c_adap.name), - "bt%d #%d [%s]", btv->id, btv->nr, use_hw ? "hw" : "sw"); - - i2c_set_adapdata(&btv->i2c_adap, btv); - btv->i2c_client.adapter = &btv->i2c_adap; - - if (use_hw) { - btv->i2c_rc = i2c_add_adapter(&btv->i2c_adap); - } else { - bttv_bit_setscl(btv,1); - bttv_bit_setsda(btv,1); - btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap); - } - return btv->i2c_rc; -} - -int __devexit fini_bttv_i2c(struct bttv *btv) -{ - int use_hw = (btv->id == 878) && i2c_hw; - - if (0 != btv->i2c_rc) - return 0; - - if (use_hw) { - return i2c_del_adapter(&btv->i2c_adap); - } else { - return i2c_bit_del_bus(&btv->i2c_adap); - } -} - /* * Local variables: * c-basic-offset: 8 diff -puN drivers/media/video/bttvp.h~v4l-04-bttv-driver-update drivers/media/video/bttvp.h --- 25/drivers/media/video/bttvp.h~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttvp.h 2004-01-15 08:27:42.000000000 -0800 @@ -41,13 +41,11 @@ #include #include #include +#include #include "bt848.h" #include "bttv.h" #include "btcx-risc.h" -#ifdef CONFIG_VIDEO_IR -#include "ir-common.h" -#endif #ifdef __KERNEL__ @@ -219,11 +217,14 @@ void bttv_vbi_setlines(struct bttv_fh *f extern struct videobuf_queue_ops bttv_vbi_qops; /* ---------------------------------------------------------- */ -/* bttv-input.c */ +/* bttv-gpio.c */ + + +extern struct bus_type bttv_sub_bus_type; +int bttv_sub_add_device(struct bttv_core *core, char *name); +int bttv_sub_del_devices(struct bttv_core *core); +void bttv_gpio_irq(struct bttv_core *core); -int bttv_input_init(struct bttv *btv); -void bttv_input_fini(struct bttv *btv); -void bttv_input_irq(struct bttv *btv); /* ---------------------------------------------------------- */ /* bttv-driver.c */ @@ -263,7 +264,6 @@ struct bttv_pll_info { unsigned int pll_current; /* Currently programmed ofreq */ }; -#ifdef CONFIG_VIDEO_IR /* for gpio-connected remote control */ struct bttv_input { struct input_dev dev; @@ -273,36 +273,46 @@ struct bttv_input { u32 mask_keycode; u32 mask_keydown; }; -#endif + +struct bttv_suspend_state { + u32 pci_cfg[64 / sizeof(u32)]; + u32 gpio_enable; + u32 gpio_data; + int disabled; + struct bttv_buffer_set set; +}; struct bttv { + struct bttv_core c; + /* pci device config */ - struct pci_dev *dev; unsigned short id; unsigned char revision; unsigned char *bt848_mmio; /* pointer to mmio */ /* card configuration info */ - unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ - char name[8]; /* dev name */ unsigned int cardid; /* pci subsystem id (bt878 based ones) */ - unsigned int type; /* card type (pointer into tvcards[]) */ unsigned int tuner_type; /* tuner chip type */ unsigned int pinnacle_id; unsigned int svhs; struct bttv_pll_info pll; int triton1; + int gpioirq; - /* gpio interface */ + /* old gpio interface */ wait_queue_head_t gpioq; int shutdown; void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); - + + /* new gpio interface */ + spinlock_t gpio_lock; + /* i2c layer */ - struct i2c_adapter i2c_adap; struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; int i2c_state, i2c_rc; + int i2c_done; + wait_queue_head_t i2c_queue; /* video4linux (1) */ struct video_device *video_dev; @@ -311,9 +321,7 @@ struct bttv { /* infrared remote */ int has_remote; -#ifdef CONFIG_VIDEO_IR struct bttv_input *remote; -#endif /* locking */ spinlock_t s_lock; @@ -339,6 +347,8 @@ struct bttv { int opt_chroma_agc; int opt_adc_crush; int opt_vcr_hack; + int opt_whitecrush_upper; + int opt_whitecrush_lower; /* radio data/state */ int has_radio; @@ -371,6 +381,11 @@ struct bttv { unsigned long cap_ctl; unsigned long dma_on; struct timer_list timeout; + struct bttv_suspend_state state; + + /* stats */ + unsigned int irq_total; + unsigned int irq_me; unsigned int errors; unsigned int users; diff -puN drivers/media/video/bttv-risc.c~v4l-04-bttv-driver-update drivers/media/video/bttv-risc.c --- 25/drivers/media/video/bttv-risc.c~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttv-risc.c 2004-01-15 08:27:42.000000000 -0800 @@ -5,7 +5,7 @@ - memory management - generation - (c) 2000 Gerd Knorr + (c) 2000-2003 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 @@ -53,7 +53,7 @@ bttv_risc_packed(struct bttv *btv, struc one write per scan line + sync + jump (all 2 dwords) */ instructions = (bpl * lines) / PAGE_SIZE + lines; instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0) + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) return rc; /* sync instruction */ @@ -67,7 +67,7 @@ bttv_risc_packed(struct bttv *btv, struc if ((btv->opt_vcr_hack) && (line >= (lines - VCR_HACK_LINES))) continue; - while (offset >= sg_dma_len(sg)) { + while (offset && offset >= sg_dma_len(sg)) { offset -= sg_dma_len(sg); sg++; } @@ -100,7 +100,7 @@ bttv_risc_packed(struct bttv *btv, struc } offset += padding; } - dprintk("bttv%d: risc planar: %d sglist elems\n", btv->nr, (int)(sg-sglist)); + dprintk("bttv%d: risc planar: %d sglist elems\n", btv->c.nr, (int)(sg-sglist)); /* save pointer to jmp instruction address */ risc->jmp = rp; @@ -128,7 +128,7 @@ bttv_risc_planar(struct bttv *btv, struc plus sync + jump (2 dwords) */ instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines; instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*4*5)) < 0) + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) return rc; /* sync instruction */ @@ -152,15 +152,15 @@ bttv_risc_planar(struct bttv *btv, struc } for (todo = ybpl; todo > 0; todo -= ylen) { /* go to next sg entry if needed */ - while (yoffset >= sg_dma_len(ysg)) { + while (yoffset && yoffset >= sg_dma_len(ysg)) { yoffset -= sg_dma_len(ysg); ysg++; } - while (uoffset >= sg_dma_len(usg)) { + while (uoffset && uoffset >= sg_dma_len(usg)) { uoffset -= sg_dma_len(usg); usg++; } - while (voffset >= sg_dma_len(vsg)) { + while (voffset && voffset >= sg_dma_len(vsg)) { voffset -= sg_dma_len(vsg); vsg++; } @@ -227,7 +227,7 @@ bttv_risc_overlay(struct bttv *btv, stru instructions = (ov->nclips + 1) * ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height); instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->dev,risc,instructions*8)) < 0) { + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) { kfree(skips); return rc; } @@ -247,9 +247,6 @@ bttv_risc_overlay(struct bttv *btv, stru if ((btv->opt_vcr_hack) && (line >= (ov->w.height - VCR_HACK_LINES))) continue; - if ((line%2) == 0 && skip_even) - continue; - if ((line%2) == 1 && skip_odd) if ((line%2) == 0 && skip_even) continue; if ((line%2) == 1 && skip_odd) @@ -310,7 +307,7 @@ bttv_calc_geo(struct bttv *btv, struct b int totalwidth = tvnorm->totalwidth; int scaledtwidth = tvnorm->scaledtwidth; - if (bttv_tvcards[btv->type].muxsel[btv->input] < 0) { + if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { swidth = 720; totalwidth = 858; scaledtwidth = 858; @@ -391,7 +388,7 @@ bttv_set_dma(struct bttv *btv, int overr d2printk(KERN_DEBUG "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", - btv->nr,capctl,irqflags, + btv->c.nr,capctl,irqflags, btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0, btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0, @@ -429,10 +426,10 @@ bttv_risc_init_main(struct bttv *btv) { int rc; - if ((rc = btcx_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0) + if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0) return rc; dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n", - btv->nr,(unsigned long long)btv->main.dma); + btv->c.nr,(unsigned long long)btv->main.dma); btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | BT848_FIFO_STATUS_VRE); @@ -472,11 +469,11 @@ bttv_risc_hook(struct bttv *btv, int slo if (NULL == risc) { d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n", - btv->nr,risc,slot); + btv->c.nr,risc,slot); btv->main.cpu[slot+1] = cpu_to_le32(next); } else { d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n", - btv->nr,risc,slot,(unsigned long long)risc->dma,irqflags); + btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags); cmd = BT848_RISC_JUMP; if (irqflags) { cmd |= BT848_RISC_IRQ; @@ -496,10 +493,10 @@ bttv_dma_free(struct bttv *btv, struct b if (in_interrupt()) BUG(); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(btv->dev, &buf->vb.dma); + videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); - btcx_riscmem_free(btv->dev,&buf->bottom); - btcx_riscmem_free(btv->dev,&buf->top); + btcx_riscmem_free(btv->c.pci,&buf->bottom); + btcx_riscmem_free(btv->c.pci,&buf->top); buf->vb.state = STATE_NEEDS_INIT; } @@ -577,7 +574,7 @@ bttv_buffer_risc(struct bttv *btv, struc dprintk(KERN_DEBUG "bttv%d: buffer field: %s format: %s size: %dx%d\n", - btv->nr, v4l2_field_names[buf->vb.field], + btv->c.nr, v4l2_field_names[buf->vb.field], buf->fmt->name, buf->vb.width, buf->vb.height); /* packed pixel modes */ @@ -731,7 +728,7 @@ bttv_overlay_risc(struct bttv *btv, /* check interleave, bottom+top fields */ dprintk(KERN_DEBUG "bttv%d: overlay fields: %s format: %s size: %dx%d\n", - btv->nr, v4l2_field_names[buf->vb.field], + btv->c.nr, v4l2_field_names[buf->vb.field], fmt->name,ov->w.width,ov->w.height); /* calculate geometry */ diff -puN drivers/media/video/bttv-vbi.c~v4l-04-bttv-driver-update drivers/media/video/bttv-vbi.c --- 25/drivers/media/video/bttv-vbi.c~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/bttv-vbi.c 2004-01-15 08:27:42.000000000 -0800 @@ -44,7 +44,7 @@ MODULE_PARM_DESC(vbi_debug,"vbi code deb # undef dprintk #endif #define dprintk(fmt, arg...) if (vbi_debug) \ - printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->nr, ## arg) + printk(KERN_DEBUG "bttv%d/vbi: " fmt, btv->c.nr , ## arg) /* ----------------------------------------------------------------------- */ /* vbi risc code + mm */ @@ -87,7 +87,7 @@ static int vbi_buffer_prepare(struct fil return -EINVAL; if (STATE_NEEDS_INIT == buf->vb.state) { - if (0 != (rc = videobuf_iolock(btv->dev, &buf->vb, NULL))) + if (0 != (rc = videobuf_iolock(btv->c.pci, &buf->vb, NULL))) goto fail; if (0 != (rc = vbi_buffer_risc(btv,buf,fh->lines))) goto fail; diff -puN drivers/media/video/Makefile~v4l-04-bttv-driver-update drivers/media/video/Makefile --- 25/drivers/media/video/Makefile~v4l-04-bttv-driver-update 2004-01-15 08:27:41.000000000 -0800 +++ 25-akpm/drivers/media/video/Makefile 2004-01-15 08:27:42.000000000 -0800 @@ -3,7 +3,7 @@ # bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ - bttv-risc.o bttv-vbi.o + bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o zr36067-objs := zoran_procfs.o zoran_device.o \ zoran_driver.o zoran_card.o _