📄 bttv-cards.c
字号:
xternal video-mux */ .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 }, .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1,},{ .name = "PHYTEC VD-009 Combi (bt878)", .video_inputs = 10, .audio_inputs = 0, .tuner = -1, /* card has no tuner */ .svhs = 9, .gpiomask = 0x00, .gpiomask2 = 0x03, /* gpiomask2 defines the bits used to switch audio via the upper nibble of muxsel. here: used for xternal video-mux */ .muxsel = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 }, .audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */ .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = -1,}};const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);/* ----------------------------------------------------------------------- */static unsigned char eeprom_data[256];/* * identify card */void __devinit bttv_idcard(struct bttv *btv){ unsigned int gpiobits; int i,type; unsigned short tmp; /* read PCI subsystem ID */ pci_read_config_word(btv->dev, PCI_SUBSYSTEM_ID, &tmp); btv->cardid = tmp << 16; pci_read_config_word(btv->dev, PCI_SUBSYSTEM_VENDOR_ID, &tmp); btv->cardid |= tmp; if (0 != btv->cardid && 0xffffffff != btv->cardid) { /* look for the card */ for (type = -1, i = 0; cards[i].id != 0; i++) if (cards[i].id == btv->cardid) type = i; if (type != -1) { /* 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->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); btv->type = cards[type].cardnr; } else { /* 404 */ printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n", btv->nr, btv->cardid & 0xffff, (btv->cardid >> 16) & 0xffff); printk(KERN_DEBUG "please mail id, board name and " "the correct card= insmod option to kraxel@bytesex.org\n"); } } /* let the user override the autodetected type */ if (card[btv->nr] < bttv_num_tvcards) btv->type=card[btv->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 ? "insmod option" : "autodetected"); /* overwrite gpio stuff ?? */ if (UNSET == audioall && UNSET == audiomux[0]) return; if (UNSET != audiomux[0]) { gpiobits = 0; for (i = 0; i < 5; i++) { bttv_tvcards[btv->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->type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits; printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", btv->nr,bttv_tvcards[btv->type].gpiomask); for (i = 0; i < 5; i++) { printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->type].audiomux[i]); } printk("\n");}/* * (most) board specific initialisations goes here *//* Some Modular Technology cards have an eeprom, but no subsystem ID */void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]){ int type = -1; if (0 == strncmp(eeprom_data,"GET.MM20xPCTV",13)) type = BTTV_MODTEC_205; else if (0 == strncmp(eeprom_data+20,"Picolo",7)) type = BTTV_EURESYS_PICOLO; else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0) type = BTTV_HAUPPAUGE; /* old bt848 */ if (-1 != type) { btv->type = type; printk("bttv%d: detected by eeprom: %s [card=%d]\n", btv->nr, bttv_tvcards[btv->type].name, btv->type); }}static void flyvideo_gpio(struct bttv *btv){ int gpio,outbits,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); udelay(8); // without this we would see the 0x1800 mask gpio=btread(BT848_GPIO_DATA); btwrite(outbits, BT848_GPIO_OUT_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. // GPIO14-12: n.c. // LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878) // lowest 3 bytes are remote control codes (no handshake needed) // xxxFFF: No remote control chip soldered // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered // Note: Some bits are Audio_Mask ! ttype=(gpio&0x0f0000)>>16; switch(ttype) { case 0x0: tuner=2; // NTSC, e.g. TPI8NSR11P break; case 0x2: tuner=39;// LG NTSC (newer TAPC series) TAPC-H701P break; case 0x4: tuner=5; // Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 break; case 0x6: tuner=37; // LG PAL (newer TAPC series) TAPC-G702P break; 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); } has_remote = gpio & 0x800000; has_radio = gpio & 0x400000; // unknown 0x200000; // unknown2 0x100000; is_capture_only = !(gpio & 0x008000); //GPIO15 has_tda9820_tda9821 = !(gpio & 0x004000); is_lr90 = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only) // gpio & 0x001000 // output bit for audio routing if(is_capture_only) 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); 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 ", is_capture_only?"yes":"no "); if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through btv->tuner_type = tuner; btv->has_radio = has_radio; // LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80 // LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00 // Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio; //todo: if(has_tda9874) btv->audio_hook = fv2000s_audio;}int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1, 14,2,17,1, 4,1,4,3, 1,2,16,1, 4,4,4,4 };int miro_fmtuner[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,1,0,0 };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); id = ((gpio>>10) & 63) -1; msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); if (id < 32) { btv->tuner_type = miro_tunermap[id]; if (0 == (gpio & 0x20)) { btv->has_radio = 1; if (!miro_fmtuner[id]) { btv->has_matchbox = 1; btv->mbox_we = (1<<6); btv->mbox_most = (1<<7); btv->mbox_clk = (1<<8); btv->mbox_data = (1<<9); btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9); } } else { 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; } printk(KERN_INFO "bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n", btv->nr, id+1, btv->tuner_type, !btv->has_radio ? "no" : (btv->has_matchbox ? "matchbox" : "fmtuner"), (-1 == msp) ? "no" : "yes"); } else { /* new cards with microtune tuner */ id = 63 - id; btv->has_radio = 0; switch (id) { case 1: info = "PAL / mono"; break; case 2: info = "PAL+SECAM / stereo"; btv->has_radio = 1; break; case 3: info = "NTSC / stereo"; btv->has_radio = 1; break; case 4: info = "PAL+SECAM / mono"; break; case 5: info = "NTSC / mono"; break; case 6: info = "NTSC / stereo"; break; default: info = "oops: unknown card"; break; } if (-1 != msp) btv->type = BTTV_PINNACLEPRO; printk(KERN_INFO "bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n", btv->nr, id, info, btv->has_radio ? "yes" : "no"); btv->tuner_type = 33; btv->pinnacle_id = id; }}/* GPIO21 L: Buffer aktiv, H: Buffer inaktiv */#define LM1882_SYNC_DRIVE 0x200000Lstatic void init_ids_eagle(struct bttv *btv){ btwrite(0xFFFF37, BT848_GPIO_OUT_EN); btwrite(0x000000, BT848_GPIO_REG_INP); btwrite(0x200020, BT848_GPIO_DATA); /* flash strobe inverter ?! */ btwrite(0x200024, BT848_GPIO_DATA); /* switch sync drive off */ btor(LM1882_SYNC_DRIVE, BT848_GPIO_DATA); /* set BT848 muxel to 2 */ btaor((2)<<5, ~(2<<5), BT848_IFORM);}/* Muxsel helper for the IDS Eagle. * the eagles does not use the standard muxsel-bits but * has its own multiplexer */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);#if 0 /* svhs */ /* wake chroma ADC */ btand(~BT848_ADC_C_SLEEP, BT848_ADC); /* set to YC video */ btor(BT848_CONTROL_COMP, BT848_E_CONTROL); btor(BT848_CONTROL_COMP, BT848_O_CONTROL);#else /* composite */ /* set chroma ADC to sleep */ btor(BT848_ADC_C_SLEEP, BT848_ADC); /* set to composite video */ btand(~BT848_CONTROL_COMP, BT848_E_CONTROL); btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);#endif /* switch sync drive off */ btor(LM1882_SYNC_DRIVE, BT848_GPIO_DATA);}/* ----------------------------------------------------------------------- *//* initialization part one -- before registering i2c bus */void __devinit bttv_init_card1(struct bttv *btv){ switch (btv->type) { case BTTV_HAUPPAUGE: case BTTV_HAUPPAUGE878: boot_msp34xx(btv,5); break; case BTTV_VOODOOTV_FM: boot_msp34xx(btv,20); break; case BTTV_AVERMEDIA98: boot_msp34xx(btv,11); break; case BTTV_HAUPPAUGEPVR: pvr_boot(btv); break; }}/* initialization part two -- after registering i2c bus */void __devinit bttv_init_card2(struct bttv *btv){ btv->tuner_type = -1; if (BTTV_UNKNOWN == btv->type) { bttv_readee(btv,eeprom_data,0xa0); identify_by_eeprom(btv,eeprom_data); } switch (btv->type) { case BTTV_MIRO: case BTTV_MIROPRO: case BTTV_PINNACLE: case BTTV_PINNACLEPRO: /* miro/pinnacle */ miro_pinnacle_gpio(btv); break; case BTTV_FLYVIDEO_98: case BTTV_MAXI: case BTTV_LIFE_FLYKIT: case BTTV_FLYVIDEO: case BTTV_TYPHOON_TVIEW: case BTTV_CHRONOS_VS2: case BTTV_FLYVIDEO_98FM: case BTTV_FLYVIDEO2000: case BTTV_FLYVIDEO98EZ: case BTTV_CONFERENCETV: case BTTV_LIFETEC_9415: flyvideo_gpio(btv); break; case BTTV_HAUPPAUGE: case BTTV_HAUPPAUGE878: case BTTV_HAUPPAUGEPVR: /* pick up some config infos from the eeprom */ bttv_readee(btv,eeprom_data,0xa0); hauppauge_eeprom(btv); break; case BTTV_AVERMEDIA98: case BTTV_AVPHONE98: bttv_readee(btv,eeprom_data,0xa0); avermedia_eeprom(btv); break; case BTTV_PXC200: init_PXC200(btv); break; case BTTV_VHX: btv->has_radio = 1; btv->has_matchbox = 1; btv->mbox_we = 0x20; btv->mbox_most = 0; btv->mbox_clk = 0x08; btv->mbox_data = 0x10; btv->mbox_mask = 0x38; break; case BTTV_VOBIS_BOOSTAR: case BTTV_TERRATV: terratec_active_radio_upgrade(btv); break; case BTTV_MAGICTVIEW061: if (btv->cardid == 0x3002144f) { btv->has_radio=1; printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->nr); } break; case BTTV_STB2: if (btv->cardid == 0x3060121a) { /* Fix up entry for 3DFX VoodooTV 100, which is an OEM STB card variant. */ btv->has_radio=0; btv->tuner_type=TUNER_TEMIC_NTSC; } break; case BTTV_OSPREY1x0: case BTTV_OSPREY1x0_848: case BTTV_OSPREY101_848: case BTTV_OSPREY1x1: case BTTV_OSPREY1x1_SVID: case BTTV_OSPREY2xx: case BTTV_OSPREY2x0_SVID: case BTTV_OSPREY2x0: case BTTV_OSPREY500: case BTTV_OSPREY540: case BTTV_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); osprey_eeprom(btv); break; case BTTV_IDS_EAGLE: init_ids_eagle(btv); break; case BTTV_MODTEC_205: bttv_readee(btv,eeprom_data,0xa0); modtec_eeprom(btv); break; } /* pll configuration */ if (!(btv->id==848 && btv->revision==0x11)) { /* defaults from card list */ if (PLL_28 == bttv_tvcards[btv->type].pll) { btv->pl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -