Commit bf3a93ac authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] v4l: bttv driver update

From: Gerd Knorr <kraxel@bytesex.org>

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.
parent d336a87a
......@@ -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
......
......@@ -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)
......
......@@ -53,6 +53,8 @@ static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
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 *btv, unsigned int input);
static void eagle_muxsel(struct bttv *btv, unsigned int input);
static void xguard_muxsel(struct bttv *btv, unsigned int input);
static 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_MAX) "i");
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,6 +184,8 @@ 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" },
......@@ -182,9 +193,6 @@ static struct CARD {
{ 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" <arapov@mail.ru>
.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 <claas@bigfoot.com>,
Sven Grothklags <sven@upb.de> */
.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 Rstermundt <rosterm@uni-muenster.de>
......@@ -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 <jorge@dti2.net> */
.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 *btv)
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 *btv)
/* 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 *btv)
}
/* 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 *btv)
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, unsigned char eeprom_data[256])
{
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, unsigned char eeprom_data[256])
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 *btv)
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 *btv)
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 bttv *btv)
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 bttv *btv)
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 bttv *btv)
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 bttv *btv)
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 *btv)
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 *btv, unsigned int input)
#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 bttv *btv)
{
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 bttv *btv)
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 bttv *btv)
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 bttv *btv)
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->type].digital_mode == DIGITAL_MODE_CAMERA) {
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->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 bttv *btv)
}
/* 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 *btv)
{
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(struct bttv *btv)
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(struct bttv *btv)
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(struct bttv *btv)
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 {
......@@ -2548,35 +2700,34 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
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);
gpio_bits(BTTV_ALT_DCLK,0);
if (bits & 0x01)
btor(BTTV_ALT_DATA,BT848_GPIO_DATA);
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**) &micro);
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(struct bttv *btv)
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(struct bttv *btv)
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(struct bttv *btv)
/* 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(struct bttv *btv)
}
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(struct bttv *btv)
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 *btv, int norm)
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(struct bttv *btv, int pin)
{
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 bttv *btv)
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 bttv *btv)
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 bttv *btv)
* 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 bttv *btv)
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 *btv, int value)
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, unsigned short freq)
#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, struct video_audio *v, int set)
/* 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, struct video_audio *v, int set)
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, struct video_audio *v, int set)
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, struct video_audio *v, int set)
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, struct video_audio *v, int set)
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, struct video_audio *v, int set)
}
}
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 video_audio *v, int set)
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 video_audio *v, int set)
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, struct video_audio *v, int set)
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, struct video_audio *v, int set)
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 video_audio *v, int set)
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 video_audio *v, int set)
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 video_audio *v, int set)
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 video_audio *v, int set)
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 *btv, unsigned int input)
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 *btv, unsigned int input)
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 bttv *btv)
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 bttv *btv)
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;
}
......
......@@ -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_device *cd, char *buf)
{
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_SIZE(bttv_formats);
#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_ctls[] = {
.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 input)
{
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 input)
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;
}
......@@ -864,8 +887,8 @@ 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 int norm)
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 input)
} 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 bttv *btv)
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, struct v4l2_control *c)
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, struct v4l2_control *c)
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, char *comment)
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 bttv *btv, struct bttv_buffer *buf,
/* 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, unsigned int cmd, void *arg)
{
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, unsigned int cmd, void *arg)
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, unsigned int cmd, void *arg)
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, unsigned int cmd, void *arg)
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 cmd, void *arg)
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 cmd, void *arg)
{
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, unsigned int cmd, void *arg)
{
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, unsigned int cmd, void *arg)
{
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 *inode, struct file *file,
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 *inode, struct file *file,
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 *inode, struct file *file,
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,9 +2288,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
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);
......@@ -2254,17 +2312,11 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
}
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;
}
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 *inode, struct file *file,
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 *inode, struct file *file,
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 *inode, struct file *file,
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 *file, char *data,
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, struct file *file)
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, struct file *file)
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, struct file *file)
#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_area_struct *vma)
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 *inode, struct file *file)
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, struct bttv_buffer_set *set)
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, struct bttv_buffer_set *wakeup,
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, struct bttv_buffer_set *wakeup,
} 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, struct bttv_buffer_set *wakeup,
}
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 long data)
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 long data)
}
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, void *dev_id, struct pt_regs * regs)
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, void *dev_id, struct pt_regs * regs)
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, void *dev_id, struct pt_regs * regs)
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, void *dev_id, struct pt_regs * regs)
}
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, void *dev_id, struct pt_regs * regs)
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(struct bttv *btv,
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(struct bttv *btv)
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(struct bttv *btv)
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(struct bttv *btv)
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 pci_dev *dev,
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->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 pci_dev *dev,
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 pci_dev *dev,
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 pci_dev *dev,
/* 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 pci_dev *dev,
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 pci_dev *dev,
bttv_gpio_tracking(btv,"pre-init");
bttv_risc_init_main(btv);
if (!bttv_tvcards[btv->type].no_video)
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 pci_dev *dev,
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 pci_dev *pci_dev)
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 pci_dev *pci_dev)
/* 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;
}
......
/*
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 <kraxel@bytesex.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/io.h>
#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:
*/
/*
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 <kraxel@bytesex.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>
#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(" <W %02x %02x", msg->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(" <R %02x", (msg->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:
*/
/*
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 <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>
#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, int *type, unsigned *cardid)
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 int card)
{
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, unsigned long mask, unsigned long data)
}
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, unsigned long *data)
/* 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, unsigned long mask, unsigned long data)
/* 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(unsigned int card)
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(" <W %02x %02x", msg->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(" <R %02x", (msg->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
......
......@@ -5,7 +5,7 @@
- memory management
- generation
(c) 2000 Gerd Knorr <kraxel@bytesex.org>
(c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
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, struct btcx_riscmem *risc,
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, struct btcx_riscmem *risc,
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, struct btcx_riscmem *risc,
}
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, struct btcx_riscmem *risc,
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, struct btcx_riscmem *risc,
}
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, struct btcx_riscmem *risc,
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, struct btcx_riscmem *risc,
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 bttv_geometry *geo,
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 override, int irqflags)
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 slot, struct btcx_riscmem *risc,
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 bttv_buffer *buf)
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, struct bttv_buffer *buf)
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 */
......
......@@ -44,7 +44,7 @@ MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
# 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 file *file, struct videobuf_buffer *vb,
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;
......
......@@ -14,6 +14,7 @@
#define _BTTV_H_
#include <linux/videodev.h>
#include <linux/i2c.h>
/* ---------------------------------------------------------- */
/* 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 bttv *btv);
/* ---------------------------------------------------------- */
/* 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_queue(unsigned int card);
extern void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg);
/* ---------------------------------------------------------- */
/* 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);
......
......@@ -41,13 +41,11 @@
#include <media/video-buf.h>
#include <media/audiochip.h>
#include <media/tuner.h>
#include <media/ir-common.h>
#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 *fh, struct bttv *btv, int lines);
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment