diff --git a/sys/dev/bktr/CHANGELOG.TXT b/sys/dev/bktr/CHANGELOG.TXT new file mode 100755 index 00000000000..e61341cdc5f --- /dev/null +++ b/sys/dev/bktr/CHANGELOG.TXT @@ -0,0 +1,404 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * CHANGELOG : The Change History: + * These version numbers represent the authors own numbering. + * They are unrelated to Revision Control numbering of FreeBSD or + * any other system. + +1.0 1/24/97 First Alpha release + +1.1 2/20/97 Added video ioctl so we can do PCI To PCI + data transfers. This is for capturing data + directly to a vga frame buffer which has + a linear frame buffer. Minor code clean-up. + +1.3 2/23/97 Fixed system lock-up reported by + Randall Hopper . This + problem seems somehow to be exhibited only + in his system. I changed the setting of + INT_MASK for CAP_CONTINUOUS to be exactly + the same as CAP_SINGLE apparently setting + bit 23 cleared the system lock up. + version 1.1 of the driver has been reported + to work with STB's WinTv, Hauppage's Wincast/Tv + and last but not least with the Intel Smart + Video Recorder. + +1.4 3/9/97 fsmp@freefall.org + Merged code to support tuners on STB and WinCast + cards. + Modifications to the contrast and chroma ioctls. + Textual cleanup. + +1.5 3/15/97 fsmp@freefall.org + new bt848 specific versions of hue/bright/ + contrast/satu/satv. + Amancio's patch to fix "screen freeze" problem. + +1.6 3/19/97 fsmp@freefall.org + new table-driven frequency lookup. + removed disable_intr()/enable_intr() calls from i2c. + misc. cleanup. + +1.7 3/19/97 fsmp@freefall.org + added audio support submitted by: + Michael Petry + +1.8 3/20/97 fsmp@freefall.org + extended audio support. + card auto-detection. + major cleanup, order of routines, declarations, etc. + +1.9 3/22/97 fsmp@freefall.org + merged in Amancio's minor unit for tuner control + mods. + misc. cleanup, especially in the _intr routine. + made AUDIO_SUPPORT mainline code. + +1.10 3/23/97 fsmp@freefall.org + added polled hardware i2c routines, + removed all existing software i2c routines. + created software i2cProbe() routine. + Randall Hopper's fixes of BT848_GHUE & BT848_GBRIG. + eeprom support. + +1.11 3/24/97 fsmp@freefall.org + Louis Mamakos's new bt848 struct. + +1.12 3/25/97 fsmp@freefall.org + japanese freq table from Naohiro Shichijo. + new table structs for tuner lookups. + major scrub for "magic numbers". + +1.13 3/28/97 fsmp@freefall.org + 1st PAL support. + MAGIC_[1-4] demarcates magic #s needing PAL work. + AFC code submitted by Richard Tobin + . + +1.14 3/29/97 richard@cogsci.ed.ac.uk + PAL support: magic numbers moved into + format_params structure. + Revised AFC interface. + fixed DMA_PROG_ALLOC size misdefinition. + +1.15 4/18/97 John-Mark Gurney + Added [SR]RGBMASKs ioctl for byte swapping. + +1.16 4/20/97 Randall Hopper + Generalized RGBMASK ioctls for general pixel + format setting [SG]ACTPIXFMT, and added query API + to return driver-supported pix fmts GSUPPIXFMT. + +1.17 4/21/97 hasty@rah.star-gate.com + Clipping support added. + +1.18 4/23/97 Clean up after failed CAP_SINGLEs where bt + interrupt isn't delivered, and fixed fixing + CAP_SINGLEs that for ODD_ONLY fields. +1.19 9/8/97 improved yuv support , cleaned up weurope + channel table, incorporated cleanup work from + Luigi, fixed pci interface bug due to a + change in the pci interface which disables + interrupts from a PCI device by default, + Added Luigi's, ioctl's BT848_SLNOTCH, + BT848_GLNOTCH (set luma notch and get luma not) +1.20 10/5/97 Keith Sklower submitted + a patch to fix compilation of the BSDI's PCI + interface. + Hideyuki Suzuki + Submitted a patch for Japanese cable channels + Joao Carlos Mendes Luis jonny@gta.ufrj.br + Submitted general ioctl to set video broadcast + formats (PAL, NTSC, etc..) previously we depended + on the Bt848 auto video detect feature. +1.21 10/24/97 Randall Hopper + Fix temporal decimation, disable it when + doing CAP_SINGLEs, and in dual-field capture, don't + capture fields for different frames +1.22 11/08/97 Randall Hopper + Fixes for packed 24bpp - FIFO alignment +1.23 11/17/97 Amancio + Added yuv support mpeg encoding +1.24 12/27/97 Jonathan Hanna + Patch to support Philips FR1236MK2 tuner +1.25 02/02/98 Takeshi Ohashi + submitted + code to support bktr_read . + Flemming Jacobsen + submitted code to support radio available with in + some bt848 based cards;additionally, wrote code to + correctly recognized his bt848 card. + Roger Hardiman submitted + various fixes to smooth out the microcode and made + all modes consistent. +1.26 Moved Luigi's I2CWR ioctl from the video_ioctl + section to the tuner_ioctl section + Changed Major device from 79 to 92 and reserved + our Major device number -- hasty@star-gate.com +1.27 Last batch of patches for radio support from + Flemming Jacobsen . + Added B849 PCI ID submitted by: + Tomi Vainio +1.28 Frank Nobis added tuner support + for the German Phillips PAL tuner and + additional channels for german cable tv. +1.29 Roger Hardiman + Revised autodetection code to correctly handle both + old and new VideoLogic Captivator PCI cards. + Added tsleep of 2 seconds to initialistion code + for PAL users.Corrected clock selection code on + format change. +1.30 Bring back Frank Nobis 's opt_bktr.h + +1.31 Randall Hopper + submitted ioctl to clear the video buffer + prior to starting video capture + Amancio : clean up yuv12 so that it does not + affect rgb capture. Basically, fxtv after + capturing in yuv12 mode , switching to rgb + would cause the video capture to be too bright. +1.32 disable inverse gamma function for rgb and yuv + capture. fixed meteor brightness ioctl it now + converts the brightness value from unsigned to + signed. +1.33 added sysctl: hw.bt848.tuner, hw.bt848.reverse_mute, + hw.bt848.card + card takes a value from 0 to bt848_max_card + tuner takes a value from 0 to bt848_max_tuner + reverse_mute : 0 no effect, 1 reverse tuner + mute function some tuners are wired reversed :( +1.34 reverse mute function for ims turbo card + +1.35 Roger Hardiman + options BROOKTREE_SYSTEM_DEFAULT=BROOKTREE_PAL + in the kernel config file makes the driver's + video_open() function select PAL rather than NTSC. + This fixed all the hangs on my Dual Crystal card + when using a PAL video signal. As a result, you + can loose the tsleep (of 2 seconds - now 0.25!!) + which I previously added. (Unless someone else + wanted the 0.25 second tsleep). + +1.36 added bt848.format sysctl variable. + 1 denotes NTSC , 0 denotes PAL + +1.37 added support for Bt878 and improved Hauppauge's + bt848 tuner recognition +1.38 Further improvements on Hauppauge's rely on + eeprom[9] to determine the tuner type 8) + + AVerMedia card type added + +1.39 08/05/98 Roger Hardiman + Updated Hauppauge detection code for Tuner ID 0x0a + for newer NTSC WinCastTV 404 with Bt878 chipset. + Tidied up PAL default in video_open() + + Soren bumped version from 1.39 to 1.49 to sync + with FreeBSD CVS numbers. + +1.49 10 August 1998 Roger Hardiman + Added Capture Area ioctl - BT848[SG]CAPAREA. + Normally the full 640x480 (768x576 PAL) image + is grabbed. This ioctl allows a smaller area + from anywhere within the video image to be + grabbed, eg a 400x300 image from (50,10). + See restrictions in BT848SCAPAREA. + +1.50 31 August 1998 Roger Hardiman + Renamed BT848[SG]CAPAREA to BT848_[SG]CAPAREA. + Added PR kern/7177 for SECAM Video Highway Xtreme + with single crystal PLL configuration + submitted by Vsevolod Lobko . + In kernel configuration file add + options OVERRIDE_CARD=2 + options OVERRIDE_TUNER=11 + options BKTR_USE_PLL + +1.51 31 August 1998 Roger Hardiman + Fixed bug in Miro Tuner detection. Missing Goto. + Removed Hauppauge EEPROM 0x10 detection as I think + 0x10 should be a PAL tuner, not NTSC. + Reinstated some Tuner Guesswork code from 1.27 + +1.52 3 Sep 1998 Roger Hardiman + Submitted patch by Vsevolod Lobko + to correct SECAM B-Delay and add XUSSR channel set. + +1.53 9 Sep 1998 Roger Hardiman + Changed METEORSINPUT for Hauppauge cards with bt878. + Submitted by Fred Templin + Also fixed video_open defines and 878 support. + +1.54 18 Sep 1998 Roger Hardiman + Changed tuner code to autodetect tuner i2c address. + Addresses were incorrectly hardcoded. + +1.55 21 Sep 1998 Roger Hardiman + Hauppauge Tech Support confirmed all Hauppauge 878 + PAL/SECAM boards will use PLL mode. + Added to card probe. Thanks to Ken and Fred. + +1.56 21 Jan 1999 Roger Hardiman + Added detection of Hauppauge IR remote control. + and MSP34xx Audio chip. Fixed i2c read error. + Hauppauge supplied details of new Tuner Types. + Danny Braniss submitted Bt878 + AverMedia detection with PCI subsystem vendor id. + +1.57 26 Jan 1999 Roger Hardiman + Support for MSP3410D / MSP3415D Stereo/Mono audio + using the audio format Auto Detection Mode. + Nicolas Souchu ported the + msp_read/write/reset functions to smbus/iicbus. + METEOR_INPUT_DEV2 now selects a composite camera on + the SVIDEO port for Johan Larsson + For true SVIDEO, use METEOR_INPUT_DEV_SVIDEO + +1.58 8 Feb 1999 Roger Hardiman + Added check to bktr_mmap from OpenBSD driver. + Improved MSP34xx reset for bt848 Hauppauge boards. + Added detection for Bt848a. + Vsevolod Lobko added + more XUSSR channels. + +1.59 9 Feb 1999 Added ioctl REMOTE_GETKEY for Hauppauge Infra-Red + Remote Control. Submitted by Roger Hardiman. + Added ioctl TVTUNER_GETCHANSET and + BT848_GPIO_SET_EN,BT848_GPIO_SET_DATA (and GETs) + Submitted by Vsevolod Lobko + +1.60 23 Feb 1999 Roger Hardiman + Corrected Mute on Hauppauge Radio cards. + Autodetect MMAC Osprey by looking for "MMAC" in the EEPROM. + Added for Jan Schmidt + Added ALPS Tuner Type from Hiroki Mori + +1.61 29 Apr 1999 Roger Hardiman + Fix row=0/columns=0 bug. From Randal Hopper + Add option to block the reset of the MSP34xx audio chip by + adding options BKTR_NO_MSP_RESET to the kernel config file. + This is usefull if you run another operating system + first to initialise the audio chip, then do a soft reboot. + Added for Yuri Gindin + +1.62 29 Apr 1999 Added new cards: NEC PK-UG-X017 and I/O DATA GV-BCTV2/PCI + Added new tuner: ALPS_TSBH1 (plus FM Radio for ALPS_TSCH5) + Added support for BCTV audio mux. + All submitted by Hiroki Mori + +1.63 29 Apr 1999 Roger Hardiman + Added initial code for VBI capture based on work by + Hiroki Mori and reworked by myself. + This allows software decoding of teletext, intercast and + subtitles via /dev/vbi. + +1.64 7 May 1999 Roger Hardiman + Support LifeView FlyVideo 98 cards. Use EEPROM for card + autodetection. Use bttv's audio mux values. + Thanks to Paul Reece , + Ivan Brawley and + Gilad Rom + Automatically locate the EEPROM i2c address and read the + subsystem_vendor_id from EEPROM and not the PCI registers. + Add NSMBUS checks around smbus/iicbus i2c bus code + making it easier to compile the driver under 2.2.x. + Add GPIO mask for the audio mux to each card type. + Add CARD_ZOLTRIX and CARD_KISS from mailing list searches. + +1.65 18 May 1999 Roger Hardiman + Change Intel GPIO mask to stop turning the Intel Camera off + Fixed tuner selection on Hauppauge card with tuner 0x0a + Replaced none tuner with no tuner for Theo de Raadt. + Ivan Brawley added + the Australian channel frequencies. + +1.66 19 May 1999 Ivan Brawley added better + Australian channel frequencies. + +1.67 23 May 1999 Roger Hardiman + Added rgb_vbi_prog() to capture VBI data and video at the + same time. To capture VBI data, /dev/vbi must be opened + before starting video capture. + +1.68 25 May 1999 Roger Hardiman + Due to differences in PCI bus implementations from various + motherboard chipset manufactuers, the Bt878/Bt879 has 3 + PCI bus compatibility modes. These are + NORMAL PCI 2.1 for proper PCI 2.1 compatible chipsets. + INTEL 430 FX for the Intel 430 FX chipset. + SIS VIA CHIPSET for certain SiS and VIA chipsets. + Older Intel and non-Intel chipsets may also benefit from + either 430_FX or SIS/VIA mode. + + NORMAL PCI mode is enabled by default. + For INTEL 430 FX mode, add this to your kenel config: + options "BKTR_430_FX_MODE" + For SiS / VIA mode, add this to your kernel config: + options "BKTR_SIS_VIA_MODE" + + Using quotes in these options is not needed in FreeBSD 4.x. + + Note. Newer VIA chipsets should be fully PCI 2.1 compatible + and should work fine in the Default mode. + + Also rename 849 to 849A, the correct name for the chip. + +1.69 12 June 1999 Roger Hardiman + Updates for FreeBSD 4.x device driver interface. + BSDI code removed. Will be restored later. + +1.70 12 July 1999 Roger Hardiman + Reorganise OS device dependant parts (based on a port to + linux by Brad Parker). + Make the driver compile on FreeBSD 2.2.x systems again. + Change number of VBI lines from 16 to 12 for NTSC formats. + Changes to probeCard() for better eeprom identification. + Added STB Bt878 card identification. + Add Hauppauge model identification to probeCard(). + Added TDA9850 initialisation code taken from Linux bttv. + Juha.Nurmela@quicknet.inet.fi found/fixed bug in VBI_SLEEP. + Matt Brown added MSP3430G DBX initialisation. + +1.71 30 Aug 1999 Roger Hardiman + Small cleanup of OS dependant code. Remove NPCI usage. + Fix bug in AVerMedia detection. + Update VBI support for the AleVT Teletext package. Parts + from Juha Nurmela's driver + Add support for Hauppauge 627 and Temic 4006 submitted + by Maurice Castro + Tom Jansen added BSDi support again. + +1.72 31 Aug 1999 Juha Nurmela + Clear cap_ctl register when restarting the RISC program. + This fixes the freezes experienced when changing changes. + +1.73 10 Sep 1999 Roger Hardiman + Add Hauppauge tuner #6 for Brian Somers + Add card type for Aimslabs Video Highway Xtreme for + Ladislav Kostal + Added select() code (for VBI) for the 2.2.x driver + tested by Steve Richards + +1.74 17 Sep 1999 Roger Hardiman + Fix bug where FM radio stations were offset after using FXTV + AVerMedia tuner type autodetection added for cards with + a configuration EEPROM (currently their Bt878 range) + Thanks to Frank at AVerMedia for providing the information. + Tested by David La Croix + Tidy up some tuner code and Hauppauge detection code. + New NetBSD code from Bernd Ernesti + +2.00 25 Sep 1999 Roger Hardiman + Split the driver into seperate tuner, card and audio sections. + Update tuner code so Tuner FM radio support to use correct + datasheet values. + + diff --git a/sys/dev/bktr/bktr_audio.c b/sys/dev/bktr/bktr_audio.c new file mode 100644 index 00000000000..9f27a668159 --- /dev/null +++ b/sys/dev/bktr/bktr_audio.c @@ -0,0 +1,432 @@ +/* $FreeBSD$ */ +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_audio : This deals with controlling the audio on TV cards, + * controlling the Audio Multiplexer (audio source selector). + * controlling any MSP34xx stereo audio decoders. + * initialising TDA98xx audio devices. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include /* for DELAY */ + +#include + +#include +#include /* extensions to ioctl_meteor.h */ +#include +#include +#include +#include +#include + + +/* + * Prototypes for the GV_BCTV specific functions. + */ +void set_bctv_audio( bktr_ptr_t bktr ); +void bctv_gpio_write( bktr_ptr_t bktr, int port, int val ); +/*int bctv_gpio_read( bktr_ptr_t bktr, int port );*/ /* Not used */ + + + +/* + * init_audio_devices + * Reset any MSP34xx or TDA98xx audio devices. + */ +void init_audio_devices( bktr_ptr_t bktr ) { + + /* enable stereo if appropriate on TDA audio chip */ + if ( bktr->card.dbx ) + init_BTSC( bktr ); + + /* reset the MSP34xx stereo audio chip */ + if ( bktr->card.msp3400c ) + msp_reset( bktr ); + +} + + +/* + * + */ +#define AUDIOMUX_DISCOVER_NOT +int +set_audio( bktr_ptr_t bktr, int cmd ) +{ + bt848_ptr_t bt848; + u_long temp; + volatile u_char idx; + +#if defined( AUDIOMUX_DISCOVER ) + if ( cmd >= 200 ) + cmd -= 200; + else +#endif /* AUDIOMUX_DISCOVER */ + + /* check for existance of audio MUXes */ + if ( !bktr->card.audiomuxs[ 4 ] ) + return( -1 ); + + switch (cmd) { + case AUDIO_TUNER: +#ifdef BKTR_REVERSEMUTE + bktr->audio_mux_select = 3; +#else + bktr->audio_mux_select = 0; +#endif + + if (bktr->reverse_mute ) + bktr->audio_mux_select = 0; + else + bktr->audio_mux_select = 3; + + break; + case AUDIO_EXTERN: + bktr->audio_mux_select = 1; + break; + case AUDIO_INTERN: + bktr->audio_mux_select = 2; + break; + case AUDIO_MUTE: + bktr->audio_mute_state = TRUE; /* set mute */ + break; + case AUDIO_UNMUTE: + bktr->audio_mute_state = FALSE; /* clear mute */ + break; + default: + printf("bktr: audio cmd error %02x\n", cmd); + return( -1 ); + } + + + /* Most cards have a simple audio multiplexer to select the + * audio source. The I/O_GV card has a more advanced multiplexer + * and requires special handling. + */ + if ( bktr->bt848_card == CARD_IO_GV ) { + set_bctv_audio( bktr ); + return( 0 ); + } + + /* Proceed with the simpler audio multiplexer code for the majority + * of Bt848 cards. + */ + + bt848 = bktr->base; + + /* + * Leave the upper bits of the GPIO port alone in case they control + * something like the dbx or teletext chips. This doesn't guarantee + * success, but follows the rule of least astonishment. + */ + + if ( bktr->audio_mute_state == TRUE ) { +#ifdef BKTR_REVERSEMUTE + idx = 0; +#else + idx = 3; +#endif + + if (bktr->reverse_mute ) + idx = 3; + else + idx = 0; + + } + else + idx = bktr->audio_mux_select; + + temp = bt848->gpio_data & ~bktr->card.gpio_mux_bits; + bt848->gpio_data = +#if defined( AUDIOMUX_DISCOVER ) + bt848->gpio_data = temp | (cmd & 0xff); + printf("cmd: %d audio mux %x temp %x \n", cmd,bktr->card.audiomuxs[ idx ], temp ); +#else + temp | bktr->card.audiomuxs[ idx ]; +#endif /* AUDIOMUX_DISCOVER */ + + return( 0 ); +} + + +/* + * + */ +void +temp_mute( bktr_ptr_t bktr, int flag ) +{ + static int muteState = FALSE; + + if ( flag == TRUE ) { + muteState = bktr->audio_mute_state; + set_audio( bktr, AUDIO_MUTE ); /* prevent 'click' */ + } + else { + tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 ); + if ( muteState == FALSE ) + set_audio( bktr, AUDIO_UNMUTE ); + } +} + +/* address of BTSC/SAP decoder chip */ +#define TDA9850_WADDR 0xb6 +#define TDA9850_RADDR 0xb7 + + +/* registers in the TDA9850 BTSC/dbx chip */ +#define CON1ADDR 0x04 +#define CON2ADDR 0x05 +#define CON3ADDR 0x06 +#define CON4ADDR 0x07 +#define ALI1ADDR 0x08 +#define ALI2ADDR 0x09 +#define ALI3ADDR 0x0a + +/* + * initialise the dbx chip + * taken from the Linux bttv driver TDA9850 initialisation code + */ +void +init_BTSC( bktr_ptr_t bktr ) +{ + i2cWrite(bktr, TDA9850_WADDR, CON1ADDR, 0x08); /* noise threshold st */ + i2cWrite(bktr, TDA9850_WADDR, CON2ADDR, 0x08); /* noise threshold sap */ + i2cWrite(bktr, TDA9850_WADDR, CON3ADDR, 0x40); /* stereo mode */ + i2cWrite(bktr, TDA9850_WADDR, CON4ADDR, 0x07); /* 0 dB input gain? */ + i2cWrite(bktr, TDA9850_WADDR, ALI1ADDR, 0x10); /* wideband alignment? */ + i2cWrite(bktr, TDA9850_WADDR, ALI2ADDR, 0x10); /* spectral alignment? */ + i2cWrite(bktr, TDA9850_WADDR, ALI3ADDR, 0x03); +} + +/* + * setup the dbx chip + * XXX FIXME: alot of work to be done here, this merely unmutes it. + */ +int +set_BTSC( bktr_ptr_t bktr, int control ) +{ + return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) ); +} + +/* + * CARD_GV_BCTV specific functions. + */ + +#define BCTV_AUDIO_MAIN 0x10 /* main audio program */ +#define BCTV_AUDIO_SUB 0x20 /* sub audio program */ +#define BCTV_AUDIO_BOTH 0x30 /* main(L) + sub(R) program */ + +#define BCTV_GPIO_REG0 1 +#define BCTV_GPIO_REG1 3 + +#define BCTV_GR0_AUDIO_MODE 3 +#define BCTV_GR0_AUDIO_MAIN 0 /* main program */ +#define BCTV_GR0_AUDIO_SUB 3 /* sub program */ +#define BCTV_GR0_AUDIO_BOTH 1 /* main(L) + sub(R) */ +#define BCTV_GR0_AUDIO_MUTE 4 /* audio mute */ +#define BCTV_GR0_AUDIO_MONO 8 /* force mono */ + +void +set_bctv_audio( bktr_ptr_t bktr ) +{ + int data; + + switch (bktr->audio_mux_select) { + case 1: /* external */ + case 2: /* internal */ + bctv_gpio_write(bktr, BCTV_GPIO_REG1, 0); + break; + default: /* tuner */ + bctv_gpio_write(bktr, BCTV_GPIO_REG1, 1); + break; + } +/* switch (bktr->audio_sap_select) { */ + switch (BCTV_AUDIO_BOTH) { + case BCTV_AUDIO_SUB: + data = BCTV_GR0_AUDIO_SUB; + break; + case BCTV_AUDIO_BOTH: + data = BCTV_GR0_AUDIO_BOTH; + break; + case BCTV_AUDIO_MAIN: + default: + data = BCTV_GR0_AUDIO_MAIN; + break; + } + if (bktr->audio_mute_state == TRUE) + data |= BCTV_GR0_AUDIO_MUTE; + + bctv_gpio_write(bktr, BCTV_GPIO_REG0, data); + + return; +} + +/* gpio_data bit assignment */ +#define BCTV_GPIO_ADDR_MASK 0x000300 +#define BCTV_GPIO_WE 0x000400 +#define BCTV_GPIO_OE 0x000800 +#define BCTV_GPIO_VAL_MASK 0x00f000 + +#define BCTV_GPIO_PORT_MASK 3 +#define BCTV_GPIO_ADDR_SHIFT 8 +#define BCTV_GPIO_VAL_SHIFT 12 + +/* gpio_out_en value for read/write */ +#define BCTV_GPIO_OUT_RMASK 0x000f00 +#define BCTV_GPIO_OUT_WMASK 0x00ff00 + +#define BCTV_BITS 100 + +void +bctv_gpio_write( bktr_ptr_t bktr, int port, int val ) +{ + bt848_ptr_t bt848 = bktr->base; + u_long data, outbits; + + port &= BCTV_GPIO_PORT_MASK; + switch (port) { + case 1: + case 3: + data = ((val << BCTV_GPIO_VAL_SHIFT) & BCTV_GPIO_VAL_MASK) | + ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) | + BCTV_GPIO_WE | BCTV_GPIO_OE; + outbits = BCTV_GPIO_OUT_WMASK; + break; + default: + return; + } + bt848->gpio_out_en = 0; + bt848->gpio_data = data; + bt848->gpio_out_en = outbits; + DELAY(BCTV_BITS); + bt848->gpio_data = data & ~BCTV_GPIO_WE; + DELAY(BCTV_BITS); + bt848->gpio_data = data; + DELAY(BCTV_BITS); + bt848->gpio_data = ~0; + bt848->gpio_out_en = 0; +} + +/* Not yet used +int +bctv_gpio_read( bktr_ptr_t bktr, int port ) +{ + bt848_ptr_t bt848 = bktr->base; + u_long data, outbits, ret; + + port &= BCTV_GPIO_PORT_MASK; + switch (port) { + case 1: + case 3: + data = ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) | + BCTV_GPIO_WE | BCTV_GPIO_OE; + outbits = BCTV_GPIO_OUT_RMASK; + break; + default: + return( -1 ); + } + bt848->gpio_out_en = 0; + bt848->gpio_data = data; + bt848->gpio_out_en = outbits; + DELAY(BCTV_BITS); + bt848->gpio_data = data & ~BCTV_GPIO_OE; + DELAY(BCTV_BITS); + ret = bt848->gpio_data; + DELAY(BCTV_BITS); + bt848->gpio_data = data; + DELAY(BCTV_BITS); + bt848->gpio_data = ~0; + bt848->gpio_out_en = 0; + return( (ret & BCTV_GPIO_VAL_MASK) >> BCTV_GPIO_VAL_SHIFT ); +} +*/ + +/* + * setup the MSP34xx Stereo Audio Chip + * This uses the Auto Configuration Option on MSP3410D and MSP3415D chips + * and DBX mode selection for MSP3430G chips. + * For MSP3400C support, the full programming sequence is required and is + * not yet supported. + */ + +/* Read the MSP version string */ +void msp_read_id( bktr_ptr_t bktr ){ + int rev1=0, rev2=0; + rev1 = msp_read(bktr, 0x12, 0x001e); + rev2 = msp_read(bktr, 0x12, 0x001f); + + sprintf(bktr->msp_version_string, "34%02d%c-%c%d", + (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f); + +} + + +/* Configure the MSP chip to Auto-detect the audio format */ +void msp_autodetect( bktr_ptr_t bktr ) { + + if (strncmp("3430G", bktr->msp_version_string, 5) == 0){ + + /* For MSP3430G - countries with mono and DBX stereo */ + msp_write(bktr, 0x10, 0x0030,0x2003);/* Enable Auto format detection */ + msp_write(bktr, 0x10, 0x0020,0x0020);/* Standard Select Reg. = BTSC-Stereo*/ + msp_write(bktr, 0x12, 0x000E,0x2403);/* darned if I know */ + msp_write(bktr, 0x12, 0x0008,0x0320);/* Source select = (St or A) */ + /* & Ch. Matrix = St */ + msp_write(bktr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */ + + } else { + + /* For MSP3410 / 3415 - countries with mono, stereo using 2 FM channels + and NICAM */ + msp_write(bktr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */ + msp_write(bktr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */ + msp_write(bktr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */ + } + + /* uncomment the following line to enable the MSP34xx 1Khz Tone Generator */ + /* turn your speaker volume down low before trying this */ + /* msp_write(bktr, 0x12, 0x0014, 0x7f40); */ +} diff --git a/sys/dev/bktr/bktr_audio.h b/sys/dev/bktr/bktr_audio.h new file mode 100644 index 00000000000..79bb3661435 --- /dev/null +++ b/sys/dev/bktr/bktr_audio.h @@ -0,0 +1,76 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_audio : This deals with controlling the audio on TV cards, + * controlling the Audio Multiplexer (audio source selector). + * controlling any MSP34xx stereo audio decoders. + * initialising TDA98xx audio devices. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Select Audio source, and allow muting + */ +int set_audio( bktr_ptr_t bktr, int mode ); +void temp_mute( bktr_ptr_t bktr, int flag ); + + +/* + * Initialise any MSP or TDA devices + */ +void init_audio_devices( bktr_ptr_t bktr ); + + +/* + * MSP34xx Audio Chip functions. + */ +void msp_autodetect( bktr_ptr_t bktr ); +void msp_read_id( bktr_ptr_t bktr ); + + +/* + * TDA98xx Audio Chip functions. + */ +void init_BTSC( bktr_ptr_t bktr ); +int set_BTSC( bktr_ptr_t bktr, int control ); + + + diff --git a/sys/dev/bktr/bktr_card.c b/sys/dev/bktr/bktr_card.c new file mode 100644 index 00000000000..5975b4d1bc8 --- /dev/null +++ b/sys/dev/bktr/bktr_card.c @@ -0,0 +1,1069 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_card : This deals with identifying TV cards. + * trying to find the card make and model of card. + * trying to find the type of tuner fitted. + * reading the configuration EEPROM. + * locating i2c devices. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include /* for DELAY */ + +#include + +#include +#include /* extensions to ioctl_meteor.h */ +#include +#include +#include +#include +#include + +/* Various defines */ +#define HAUP_REMOTE_INT_WADDR 0x30 +#define HAUP_REMOTE_INT_RADDR 0x31 + +#define HAUP_REMOTE_EXT_WADDR 0x34 +#define HAUP_REMOTE_EXT_RADDR 0x35 + +/* address of BTSC/SAP decoder chip */ +#define TDA9850_WADDR 0xb6 +#define TDA9850_RADDR 0xb7 + +/* address of MSP3400C chip */ +#define MSP3400C_WADDR 0x80 +#define MSP3400C_RADDR 0x81 + + +/* EEProm (128 * 8) on an STB card */ +#define X24C01_WADDR 0xae +#define X24C01_RADDR 0xaf + + +/* EEProm (256 * 8) on a Hauppauge card */ +/* and on most BT878s cards to store the sub-system vendor id */ +#define PFC8582_WADDR 0xa0 +#define PFC8582_RADDR 0xa1 + +#if BROOKTREE_SYSTEM_DEFAULT == BROOKTREE_PAL +#define DEFAULT_TUNER PHILIPS_PALI +#else +#define DEFAULT_TUNER PHILIPS_NTSC +#endif + + + + +/* + * the data for each type of card + * + * Note: + * these entried MUST be kept in the order defined by the CARD_XXX defines! + */ +static const struct CARDTYPE cards[] = { + + { CARD_UNKNOWN, /* the card id */ + "Unknown", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx unknown */ + 0, + 0, /* EEProm unknown */ + 0, /* EEProm unknown */ + { 0, 0, 0, 0, 0 }, + 0 }, /* GPIO mask */ + + { CARD_MIRO, /* the card id */ + "Miro TV", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx unknown */ + 0, + 0, /* EEProm unknown */ + 0, /* size unknown */ + { 0x02, 0x01, 0x00, 0x0a, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_HAUPPAUGE, /* the card id */ + "Hauppauge WinCast/TV", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + PFC8582_WADDR, /* EEProm type */ + (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ + { 0x00, 0x02, 0x01, 0x04, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_STB, /* the card id */ + "STB TV/PCI", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + X24C01_WADDR, /* EEProm type */ + (u_char)(128 / EEPROMBLOCKSIZE), /* 128 bytes */ + { 0x00, 0x01, 0x02, 0x02, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_INTEL, /* the card id */ + "Intel Smart Video III/VideoLogic Captivator PCI", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0 }, /* audio MUX values */ + 0x00 }, /* GPIO mask */ + + { CARD_IMS_TURBO, /* the card id */ + "IMS TV Turbo", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + PFC8582_WADDR, /* EEProm type */ + (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ + { 0x01, 0x02, 0x01, 0x00, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_AVER_MEDIA, /* the card id */ + "AVer Media TV/FM", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + 0, /* EEProm type */ + 0, /* EEProm size */ + { 0x0c, 0x00, 0x0b, 0x0b, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_OSPREY, /* the card id */ + "MMAC Osprey", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + PFC8582_WADDR, /* EEProm type */ + (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ + { 0x00, 0x00, 0x00, 0x00, 0 }, /* audio MUX values */ + 0 }, /* GPIO mask */ + + { CARD_NEC_PK, /* the card id */ + "NEC PK-UG-X017", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + 0, /* EEProm type */ + 0, /* EEProm size */ + { 0x01, 0x02, 0x01, 0x00, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_IO_GV, /* the card id */ + "I/O DATA GV-BCTV2/PCI", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, + 0, /* EEProm type */ + 0, /* EEProm size */ + { 0x00, 0x00, 0x00, 0x00, 1 }, /* Has special MUX handler */ + 0x0f }, /* GPIO mask */ + + { CARD_FLYVIDEO, /* the card id */ + "FlyVideo", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, /* msp34xx is optional */ + 0xac, /* EEProm type */ + (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ + { 0x000, 0x800, 0x400, 0x8dff00, 1 },/* audio MUX values */ + 0x8dff00 }, /* GPIO mask */ + + { CARD_ZOLTRIX, /* the card id */ + "Zoltrix", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, /* msp34xx is optional */ + 0, /* EEProm type */ + 0, /* EEProm size */ + { 0x04, 0x01, 0x00, 0x0a, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_KISS, /* the card id */ + "KISS TV/FM PCI", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, /* msp34xx is optional */ + 0, /* EEProm type */ + 0, /* EEProm size */ + { 0x0c, 0x00, 0x0b, 0x0b, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + + { CARD_VIDEO_HIGHWAY_XTREME, /* the card id */ + "Video Highway Xtreme", /* the 'name' */ + NULL, /* the tuner */ + 0, /* the tuner i2c address */ + 0, /* dbx is optional */ + 0, /* msp34xx is optional */ + 0, /* EEProm type */ + 0, /* EEProm size */ + { 0x00, 0x02, 0x01, 0x04, 1 }, /* audio MUX values */ + 0x0f }, /* GPIO mask */ + +}; + +struct bt848_card_sig bt848_card_signature[1]= { + /* IMS TURBO TV : card 5 */ + { 5,9, {00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 02, 00, 00, 00}} + + +}; + + +/* + * Write to the configuration EEPROM on the card. + * This is dangerous and will mess up your card. Therefore it is not + * implemented. + */ +int +writeEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data ) +{ + return( -1 ); +} + +/* + * Read the contents of the configuration EEPROM on the card. + * (This is not fitted to all makes of card. All Hauppuage cards have them + * and so do newer Bt878 based cards. + */ +int +readEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data ) +{ + int x; + int addr; + int max; + int byte; + + /* get the address of the EEProm */ + addr = (int)(bktr->card.eepromAddr & 0xff); + if ( addr == 0 ) + return( -1 ); + + max = (int)(bktr->card.eepromSize * EEPROMBLOCKSIZE); + if ( (offset + count) > max ) + return( -1 ); + + /* set the start address */ + if ( i2cWrite( bktr, addr, offset, -1 ) == -1 ) + return( -1 ); + + /* the read cycle */ + for ( x = 0; x < count; ++x ) { + if ( (byte = i2cRead( bktr, (addr | 1) )) == -1 ) + return( -1 ); + data[ x ] = byte; + } + + return( 0 ); +} + + +#define ABSENT (-1) + +/* + * get a signature of the card + * read all 128 possible i2c read addresses from 0x01 thru 0xff + * build a bit array with a 1 bit for each i2c device that responds + * + * XXX FIXME: use offset & count args + */ +int +signCard( bktr_ptr_t bktr, int offset, int count, u_char* sig ) +{ + int x; + + for ( x = 0; x < 16; ++x ) + sig[ x ] = 0; + + for ( x = 0; x < count; ++x ) { + if ( i2cRead( bktr, (2 * x) + 1 ) != ABSENT ) { + sig[ x / 8 ] |= (1 << (x % 8) ); + } + } + + return( 0 ); +} + + +/* + * check_for_i2c_devices. + * Some BT848 cards have no tuner and no additional i2c devices + * eg stereo decoder. These are used for video conferencing or capture from + * a video camera. (eg VideoLogic Captivator PCI, Intel SmartCapture card). + * + * Determine if there are any i2c devices present. There are none present if + * a) reading from all 128 devices returns ABSENT (-1) for each one + * (eg VideoLogic Captivator PCI with BT848) + * b) reading from all 128 devices returns 0 for each one + * (eg VideoLogic Captivator PCI rev. 2F with BT848A) + */ +static int check_for_i2c_devices( bktr_ptr_t bktr ){ + int x, temp_read; + int i2c_all_0 = 1; + int i2c_all_absent = 1; + for ( x = 0; x < 128; ++x ) { + temp_read = i2cRead( bktr, (2 * x) + 1 ); + if (temp_read != 0) i2c_all_0 = 0; + if (temp_read != ABSENT) i2c_all_absent = 0; + } + + if ((i2c_all_0) || (i2c_all_absent)) return 0; + else return 1; +} + + +/* + * Temic/Philips datasheets say tuners can be at i2c addresses 0xc0, 0xc2, + * 0xc4 or 0xc6, settable by links on the tuner. + * Determine the actual address used on the TV card by probing read addresses. + */ +static int locate_tuner_address( bktr_ptr_t bktr) { + if (i2cRead( bktr, 0xc1) != ABSENT) return 0xc0; + if (i2cRead( bktr, 0xc3) != ABSENT) return 0xc2; + if (i2cRead( bktr, 0xc5) != ABSENT) return 0xc4; + if (i2cRead( bktr, 0xc7) != ABSENT) return 0xc6; + return -1; /* no tuner found */ +} + + +/* + * Search for a configuration EEPROM on the i2c bus by looking at i2c addresses + * where EEPROMs are usually found. + * On some cards, the EEPROM appears in several locations, but all in the + * range 0xa0 to 0xae. + */ +static int locate_eeprom_address( bktr_ptr_t bktr) { + if (i2cRead( bktr, 0xa0) != ABSENT) return 0xa0; + if (i2cRead( bktr, 0xac) != ABSENT) return 0xac; + if (i2cRead( bktr, 0xae) != ABSENT) return 0xae; + return -1; /* no eeprom found */ +} + + +/* + * determine the card brand/model + * OVERRIDE_CARD, OVERRIDE_TUNER, OVERRIDE_DBX and OVERRIDE_MSP + * can be used to select a specific device, regardless of the + * autodetection and i2c device checks. + * + * The scheme used for probing cards faces these problems: + * It is impossible to work out which type of tuner is actually fitted, + * (the driver cannot tell if the Tuner is PAL or NTSC, Temic or Philips) + * It is impossible to determine what audio-mux hardware is connected. + * It is impossible to determine if there is extra hardware connected to the + * GPIO pins (eg radio chips or MSP34xx reset logic) + * + * However some makes of card (eg Hauppauge) come with a configuration eeprom + * which tells us the make of the card. Most eeproms also tell us the + * tuner type and other features of the the cards. + * + * The current probe code works as follows + * A) If the card uses a Bt878/879: + * 1) Read the sub-system vendor id from the configuration EEPROM. + * Select the required tuner, audio mux arrangement and any other + * onboard features. If this fails, move to step B. + * B) If it card uses a Bt848, 848A, 849A or an unknown Bt878/879: + * 1) Look for I2C devices. If there are none fitted, it is an Intel or + * VideoLogic cards. + * 2) Look for a configuration EEPROM. + * 2a) If there is one at I2C address 0xa0 it may be + * a Hauppauge or an Osprey. Check the EEPROM contents to determine which + * one it is. For Hauppauge, select the tuner type and audio hardware. + * 2b) If there is an EEPROM at I2C address 0xa8 it will be an STB card. + * We still have to guess on the tuner type. + * + * C) If we do not know the card type from (A) or (B), guess at the tuner + * type based on the I2C address of the tuner. + * + * D) After determining the Tuner Type, we probe the i2c bus for other + * devices at known locations, eg IR-Remote Control, MSP34xx and TDA + * stereo chips. + */ + + +/* + * These are the sub-system vendor ID codes stored in the + * configuration EEPROM used on Bt878/879 cards. They should match the + * number assigned to the company by the PCI Special Interest Group + */ +#define VENDOR_AVER_MEDIA 0x1461 +#define VENDOR_HAUPPAUGE 0x0070 +#define VENDOR_FLYVIDEO 0x1851 +#define VENDOR_STB 0x10B4 + + +void +probeCard( bktr_ptr_t bktr, int verbose, int unit ) +{ + int card, i,j, card_found; + int status; + bt848_ptr_t bt848; + u_char probe_signature[128], *probe_temp; + int any_i2c_devices; + u_char eeprom[256]; + u_char tuner_code = 0; + int tuner_i2c_address = -1; + int eeprom_i2c_address = -1; + + bt848 = bktr->base; + + /* Select all GPIO bits as inputs */ + bt848->gpio_out_en = 0; + if (bootverbose) + printf("bktr: GPIO is 0x%08x\n", bt848->gpio_data); + +#ifdef HAUPPAUGE_MSP_RESET + /* Reset the MSP34xx audio chip. This resolves bootup card + * detection problems with old Bt848 based Hauppauge cards with + * MSP34xx stereo audio chips. This must be user enabled because + * at this point the probe function does not know the card type. */ + bt848->gpio_out_en = bt848->gpio_out_en | (1<<5); + bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ + DELAY(2500); /* wait 2.5ms */ + bt848->gpio_data = bt848->gpio_data & ~(1<<5); /* write '0' */ + DELAY(2500); /* wait 2.5ms */ + bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ + DELAY(2500); /* wait 2.5ms */ +#endif + + /* Check for the presence of i2c devices */ + any_i2c_devices = check_for_i2c_devices( bktr ); + + + /* Check for a user specified override on the card selection */ +#if defined( OVERRIDE_CARD ) + bktr->card = cards[ (card = OVERRIDE_CARD) ]; + goto checkEEPROM; +#endif + if (bktr->bt848_card != -1 ) { + bktr->card = cards[ (card = bktr->bt848_card) ]; + goto checkEEPROM; + } + + + /* No override, so try and determine the make of the card */ + + /* On BT878/879 cards, read the sub-system vendor id */ + /* This identifies the manufacturer of the card and the model */ + /* In theory this can be read from PCI registers but this does not */ + /* appear to work on the FlyVideo 98. Hauppauge also warned that */ + /* the PCI registers are sometimes not loaded correctly. */ + /* Therefore, I will read the sub-system vendor ID from the EEPROM */ + /* (just like the Bt878 does during power up initialisation) */ + + if ((bktr->id==BROOKTREE_878) || (bktr->id==BROOKTREE_879)) { + /* Try and locate the EEPROM */ + eeprom_i2c_address = locate_eeprom_address( bktr ); + if (eeprom_i2c_address != -1) { + + unsigned int subsystem_vendor_id; /* vendors PCI-SIG ID */ + unsigned int subsystem_id; /* board model number */ + unsigned int byte_252, byte_253, byte_254, byte_255; + + bktr->card = cards[ (card = CARD_UNKNOWN) ]; + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + + readEEProm(bktr, 0, 256, (u_char *) &eeprom ); + byte_252 = (unsigned int)eeprom[252]; + byte_253 = (unsigned int)eeprom[253]; + byte_254 = (unsigned int)eeprom[254]; + byte_255 = (unsigned int)eeprom[255]; + + subsystem_id = (byte_252 << 8) | byte_253; + subsystem_vendor_id = (byte_254 << 8) | byte_255; + + if ( bootverbose ) + printf("subsytem 0x%04x 0x%04x\n",subsystem_vendor_id, + subsystem_id); + + if (subsystem_vendor_id == VENDOR_AVER_MEDIA) { + bktr->card = cards[ (card = CARD_AVER_MEDIA) ]; + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + goto checkTuner; + } + + if (subsystem_vendor_id == VENDOR_HAUPPAUGE) { + bktr->card = cards[ (card = CARD_HAUPPAUGE) ]; + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + goto checkTuner; + } + + if (subsystem_vendor_id == VENDOR_FLYVIDEO) { + bktr->card = cards[ (card = CARD_FLYVIDEO) ]; + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + goto checkTuner; + } + + if (subsystem_vendor_id == VENDOR_STB) { + bktr->card = cards[ (card = CARD_STB) ]; + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + goto checkTuner; + } + + /* Vendor is unknown. We will use the standard probe code */ + /* which may not give best results */ + printf("Warning - card vendor 0x%04x (model 0x%04x) unknown.\n",subsystem_vendor_id,subsystem_id); + } + else + { + printf("Card has no configuration EEPROM. Cannot determine card make.\n"); + } + } /* end of bt878/bt879 card detection code */ + + /* If we get to this point, we must have a Bt848/848A/849A card */ + /* or a Bt878/879 with an unknown subsystem vendor id */ + /* Try and determine the make of card by clever i2c probing */ + + /* Check for i2c devices. If none, move on */ + if (!any_i2c_devices) { + bktr->card = cards[ (card = CARD_INTEL) ]; + bktr->card.eepromAddr = 0; + bktr->card.eepromSize = 0; + goto checkTuner; + } + + /* Look for Hauppauge, STB and Osprey cards by the presence */ + /* of an EEPROM */ + /* Note: Bt878 based cards also use EEPROMs so we can only do this */ + /* test on BT848/848A and 849A based cards. */ + if ((bktr->id==BROOKTREE_848) || + (bktr->id==BROOKTREE_848A) || + (bktr->id==BROOKTREE_849A)) { + + /* At i2c address 0xa0, look for Hauppauge and Osprey cards */ + if ( (status = i2cRead( bktr, PFC8582_RADDR )) != ABSENT ) { + + /* Read the eeprom contents */ + bktr->card = cards[ (card = CARD_UNKNOWN) ]; + bktr->card.eepromAddr = PFC8582_WADDR; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + readEEProm(bktr, 0, 128, (u_char *) &eeprom ); + + /* For Hauppauge, check the EEPROM begins with 0x84 */ + if (eeprom[0] == 0x84) { + bktr->card = cards[ (card = CARD_HAUPPAUGE) ]; + bktr->card.eepromAddr = PFC8582_WADDR; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + goto checkTuner; + } + + /* For Osprey, check the EEPROM begins with "MMAC" */ + if ( (eeprom[0] == 'M') &&(eeprom[1] == 'M') + &&(eeprom[2] == 'A') &&(eeprom[3] == 'C')) { + bktr->card = cards[ (card = CARD_OSPREY) ]; + bktr->card.eepromAddr = PFC8582_WADDR; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + goto checkTuner; + } + printf("Warning: Unknown card type. EEPROM data not recognised\n"); + printf("%x %x %x %x\n",eeprom[0],eeprom[1],eeprom[2],eeprom[3]); + } + + /* look for an STB card */ + if ( (status = i2cRead( bktr, X24C01_RADDR )) != ABSENT ) { + bktr->card = cards[ (card = CARD_STB) ]; + bktr->card.eepromAddr = X24C01_WADDR; + bktr->card.eepromSize = (u_char)(128 / EEPROMBLOCKSIZE); + goto checkTuner; + } + + } + + signCard( bktr, 1, 128, (u_char *) &probe_signature ); + + if (bootverbose) { + printf("card signature \n"); + for (j = 0; j < Bt848_MAX_SIGN; j++) { + printf(" %02x ", probe_signature[j]); + } + printf("\n\n"); + } + for (i = 0; + i < (sizeof bt848_card_signature)/ sizeof (struct bt848_card_sig); + i++ ) { + + card_found = 1; + probe_temp = (u_char *) &bt848_card_signature[i].signature; + + for (j = 0; j < Bt848_MAX_SIGN; j++) { + if ((probe_temp[j] & 0xf) != (probe_signature[j] & 0xf)) { + card_found = 0; + break; + } + + } + if (card_found) { + bktr->card = cards[ card = bt848_card_signature[i].card]; + select_tuner( bktr, bt848_card_signature[i].tuner ); + eeprom_i2c_address = locate_eeprom_address( bktr ); + if (eeprom_i2c_address != -1) { + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + } else { + bktr->card.eepromAddr = 0; + bktr->card.eepromSize = 0; + } + goto checkDBX; + } + } + + /* We do not know the card type. Default to Miro */ + bktr->card = cards[ (card = CARD_MIRO) ]; + + +checkEEPROM: + /* look for a configuration eeprom */ + eeprom_i2c_address = locate_eeprom_address( bktr ); + if (eeprom_i2c_address != -1) { + bktr->card.eepromAddr = eeprom_i2c_address; + bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); + } else { + bktr->card.eepromAddr = 0; + bktr->card.eepromSize = 0; + } + + +checkTuner: + + /* look for a tuner */ + tuner_i2c_address = locate_tuner_address( bktr ); + if ( tuner_i2c_address == -1 ) { + select_tuner( bktr, NO_TUNER ); + goto checkDBX; + } + +#if defined( OVERRIDE_TUNER ) + select_tuner( bktr, OVERRIDE_TUNER ); + goto checkDBX; +#endif + if (bktr->bt848_tuner != -1 ) { + select_tuner( bktr, bktr->bt848_tuner & 0xff ); + goto checkDBX; + } + + /* Check for i2c devices */ + if (!any_i2c_devices) { + select_tuner( bktr, NO_TUNER ); + goto checkDBX; + } + + /* differentiate type of tuner */ + + switch (card) { + case CARD_MIRO: + switch (((bt848->gpio_data >> 10)-1)&7) { + case 0: select_tuner( bktr, TEMIC_PAL ); break; + case 1: select_tuner( bktr, PHILIPS_PAL ); break; + case 2: select_tuner( bktr, PHILIPS_NTSC ); break; + case 3: select_tuner( bktr, PHILIPS_SECAM ); break; + case 4: select_tuner( bktr, NO_TUNER ); break; + case 5: select_tuner( bktr, PHILIPS_PALI ); break; + case 6: select_tuner( bktr, TEMIC_NTSC ); break; + case 7: select_tuner( bktr, TEMIC_PALI ); break; + } + goto checkDBX; + break; + + case CARD_HAUPPAUGE: + /* Hauppauge kindly supplied the following Tuner Table */ + /* FIXME: I think the tuners the driver selects for types */ + /* 0x08 and 0x15 may be incorrect but no one has complained. */ + /* + ID Tuner Model Format We select Format + 0 NONE + 1 EXTERNAL + 2 OTHER + 3 Philips FI1216 BG + 4 Philips FI1216MF BGLL' + 5 Philips FI1236 MN PHILIPS_NTSC + 6 Philips FI1246 I PHILIPS_PALI + 7 Philips FI1256 DK + 8 Philips FI1216 MK2 BG PHILIPS_PALI + 9 Philips FI1216MF MK2 BGLL' + a Philips FI1236 MK2 MN PHILIPS_NTSC + b Philips FI1246 MK2 I PHILIPS_PALI + c Philips FI1256 MK2 DK + d Temic 4032FY5 NTSC TEMIC_NTSC + e Temic 4002FH5 BG TEMIC_PAL + f Temic 4062FY5 I TEMIC_PALI + 10 Philips FR1216 MK2 BG + 11 Philips FR1216MF MK2 BGLL' + 12 Philips FR1236 MK2 MN PHILIPS_FR1236_NTSC + 13 Philips FR1246 MK2 I + 14 Philips FR1256 MK2 DK + 15 Philips FM1216 BG PHILIPS_FR1216_PAL + 16 Philips FM1216MF BGLL' + 17 Philips FM1236 MN PHILIPS_FR1236_NTSC + 18 Philips FM1246 I + 19 Philips FM1256 DK + 1a Temic 4036FY5 MN - FI1236 MK2 clone + 1b Samsung TCPN9082D MN + 1c Samsung TCPM9092P Pal BG/I/DK + 1d Temic 4006FH5 BG PHILIPS_PALI clone + 1e Samsung TCPN9085D MN/Radio + 1f Samsung TCPB9085P Pal BG/I/DK / Radio + 20 Samsung TCPL9091P Pal BG & Secam L/L' + 21 Temic 4039FY5 NTSC Radio + + */ + + + + /* Determine the model number from the eeprom */ + if (bktr->card.eepromAddr != 0) { + u_int model; + u_int revision; + + readEEProm(bktr, 0, 128, (u_char *) &eeprom ); + + model = (eeprom[12] << 8 | eeprom[11]); + revision = (eeprom[15] << 16 | eeprom[14] << 8 | eeprom[13]); + if (verbose) + printf("bktr%d: Hauppauge Model %d %c%c%c%c\n", + unit, + model, + ((revision >> 18) & 0x3f) + 32, + ((revision >> 12) & 0x3f) + 32, + ((revision >> 6) & 0x3f) + 32, + ((revision >> 0) & 0x3f) + 32 ); + + /* Determine the tuner type from the eeprom */ + tuner_code = eeprom[9]; + switch (tuner_code) { + + case 0x5: + case 0x0a: + case 0x1a: + select_tuner( bktr, PHILIPS_NTSC ); + goto checkDBX; + + case 0x12: + case 0x17: + select_tuner( bktr, PHILIPS_FR1236_NTSC ); + goto checkDBX; + + case 0x6: + case 0x8: + case 0xb: + case 0x1d: + select_tuner( bktr, PHILIPS_PALI ); + goto checkDBX; + + case 0xd: + select_tuner( bktr, TEMIC_NTSC ); + goto checkDBX; + + case 0xe: + select_tuner( bktr, TEMIC_PAL ); + goto checkDBX; + + case 0xf: + select_tuner( bktr, TEMIC_PALI ); + goto checkDBX; + + case 0x15: + select_tuner( bktr, PHILIPS_FR1216_PAL ); + goto checkDBX; + + default : + printf("Warning - Unknown Hauppauge Tuner 0x%x\n",tuner_code); + } + } + break; + + + case CARD_AVER_MEDIA: + /* AVerMedia kindly supplied some details of their EEPROM contents + * which allow us to auto select the Tuner Type. + * Only the newer AVerMedia cards actually have an EEPROM. + */ + if (bktr->card.eepromAddr != 0) { + + u_char tuner_make; /* Eg Philips, Temic */ + u_char tuner_tv_fm; /* TV or TV with FM Radio */ + u_char tuner_format; /* Eg NTSC, PAL, SECAM */ + int tuner; + + int tuner_0_table[] = { + PHILIPS_NTSC, PHILIPS_PAL, + PHILIPS_PAL, PHILIPS_PAL, + PHILIPS_PAL, PHILIPS_PAL, + PHILIPS_SECAM, PHILIPS_SECAM, + PHILIPS_SECAM, PHILIPS_PAL}; + + int tuner_0_fm_table[] = { + PHILIPS_FR1236_NTSC, PHILIPS_FR1216_PAL, + PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL, + PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL, + PHILIPS_FR1236_SECAM, PHILIPS_FR1236_SECAM, + PHILIPS_FR1236_SECAM, PHILIPS_FR1216_PAL}; + + int tuner_1_table[] = { + TEMIC_NTSC, TEMIC_PAL, TEMIC_PAL, + TEMIC_PAL, TEMIC_PAL, TEMIC_PAL, + TEMIC_SECAM, TEMIC_SECAM, TEMIC_SECAM, + TEMIC_PAL}; + + + /* Extract information from the EEPROM data */ + readEEProm(bktr, 0, 128, (u_char *) &eeprom ); + + tuner_make = (eeprom[0x41] & 0x7); + tuner_tv_fm = (eeprom[0x41] & 0x18) >> 3; + tuner_format = (eeprom[0x42] & 0xf0) >> 4; + + /* Treat tuner make 0 (Philips) and make 2 (LG) the same */ + if ( ((tuner_make == 0) || (tuner_make == 2)) + && (tuner_format <= 9) && (tuner_tv_fm == 0) ) { + tuner = tuner_0_table[tuner_format]; + select_tuner( bktr, tuner ); + goto checkDBX; + } + + if ( ((tuner_make == 0) || (tuner_make == 2)) + && (tuner_format <= 9) && (tuner_tv_fm == 1) ) { + tuner = tuner_0_fm_table[tuner_format]; + select_tuner( bktr, tuner ); + goto checkDBX; + } + + if ( (tuner_make == 1) && (tuner_format <= 9) ) { + tuner = tuner_1_table[tuner_format]; + select_tuner( bktr, tuner ); + goto checkDBX; + } + + printf("Warning - Unknown AVerMedia Tuner Make %d Format %d\n", + tuner_make, tuner_format); + } + break; + + } /* end switch(card) */ + + + /* At this point, a goto checkDBX has not occured */ + /* We have not been able to select a Tuner */ + /* Some cards make use of the tuner address to */ + /* identify the make/model of tuner */ + + /* At address 0xc0/0xc1 we often find a TEMIC NTSC */ + if ( i2cRead( bktr, 0xc1 ) != ABSENT ) { + select_tuner( bktr, TEMIC_NTSC ); + goto checkDBX; + } + + /* At address 0xc6/0xc7 we often find a PHILIPS NTSC Tuner */ + if ( i2cRead( bktr, 0xc7 ) != ABSENT ) { + select_tuner( bktr, PHILIPS_NTSC ); + goto checkDBX; + } + + /* Address 0xc2/0xc3 is default (or common address) for several */ + /* tuners and we cannot tell which is which. */ + /* And for all other tuner i2c addresses, select the default */ + select_tuner( bktr, DEFAULT_TUNER ); + + +checkDBX: +#if defined( OVERRIDE_DBX ) + bktr->card.dbx = OVERRIDE_DBX; + goto checkMSP; +#endif + /* Check for i2c devices */ + if (!any_i2c_devices) { + goto checkMSP; + } + + /* probe for BTSC (dbx) chip */ + if ( i2cRead( bktr, TDA9850_RADDR ) != ABSENT ) + bktr->card.dbx = 1; + +checkMSP: + /* If this is a Hauppauge Bt878 card, we need to enable the + * MSP 34xx audio chip. + * If this is a Hauppauge Bt848 card, reset the MSP device. + * The MSP reset line is wired to GPIO pin 5. On Bt878 cards a pulldown + * resistor holds the device in reset until we set GPIO pin 5. + */ + + /* Optionally skip the MSP reset. This is handy if you initialise the + * MSP audio in another operating system (eg Windows) first and then + * do a soft reboot. + */ + +#ifndef BKTR_NO_MSP_RESET + if (card == CARD_HAUPPAUGE) { + bt848->gpio_out_en = bt848->gpio_out_en | (1<<5); + bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ + DELAY(2500); /* wait 2.5ms */ + bt848->gpio_data = bt848->gpio_data & ~(1<<5); /* write '0' */ + DELAY(2500); /* wait 2.5ms */ + bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ + DELAY(2500); /* wait 2.5ms */ + } +#endif + +#if defined( OVERRIDE_MSP ) + bktr->card.msp3400c = OVERRIDE_MSP; + goto checkMSPEnd; +#endif + + /* Check for i2c devices */ + if (!any_i2c_devices) { + goto checkMSPEnd; + } + + if ( i2cRead( bktr, MSP3400C_RADDR ) != ABSENT ) { + bktr->card.msp3400c = 1; + } + +checkMSPEnd: + + if (bktr->card.msp3400c) { + bktr->msp_addr = MSP3400C_WADDR; + msp_read_id( bktr ); + printf("bktr%d: Detected a MSP%s at 0x%x\n", unit, + bktr->msp_version_string, + bktr->msp_addr); + + } + + +/* Start of Check Remote */ + /* Check for the Hauppauge IR Remote Control */ + /* If there is an external unit, the internal will be ignored */ + + bktr->remote_control = 0; /* initial value */ + + if (any_i2c_devices) { + if (i2cRead( bktr, HAUP_REMOTE_EXT_RADDR ) != ABSENT ) + { + bktr->remote_control = 1; + bktr->remote_control_addr = HAUP_REMOTE_EXT_RADDR; + } + else if (i2cRead( bktr, HAUP_REMOTE_INT_RADDR ) != ABSENT ) + { + bktr->remote_control = 1; + bktr->remote_control_addr = HAUP_REMOTE_INT_RADDR; + } + + } + /* If a remote control is found, poll it 5 times to turn off the LED */ + if (bktr->remote_control) { + int i; + for (i=0; i<5; i++) + i2cRead( bktr, bktr->remote_control_addr ); + } +/* End of Check Remote */ + +#if defined( BKTR_USE_PLL ) + bktr->xtal_pll_mode = BT848_USE_PLL; + goto checkPLLEnd; +#endif + /* Default is to use XTALS and not PLL mode */ + bktr->xtal_pll_mode = BT848_USE_XTALS; + + /* Enable PLL mode for PAL/SECAM users on Hauppauge 878 cards */ + if ((card == CARD_HAUPPAUGE) && + (bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) ) + bktr->xtal_pll_mode = BT848_USE_PLL; + + + /* Enable PLL mode for OSPREY users */ + if (card == CARD_OSPREY) + bktr->xtal_pll_mode = BT848_USE_PLL; + + + /* Enable PLL mode for PAL/SECAM users on FlyVideo 878 cards */ + if ((card == CARD_FLYVIDEO) && + (bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) ) + bktr->xtal_pll_mode = BT848_USE_PLL; + + +#if defined( BKTR_USE_PLL ) +checkPLLEnd: +#endif + + + bktr->card.tuner_pllAddr = tuner_i2c_address; + + if ( verbose ) { + printf( "%s", bktr->card.name ); + if ( bktr->card.tuner ) + printf( ", %s tuner", bktr->card.tuner->name ); + if ( bktr->card.dbx ) + printf( ", dbx stereo" ); + if ( bktr->card.msp3400c ) + printf( ", msp3400c stereo" ); + if ( bktr->remote_control ) + printf( ", remote control" ); + printf( ".\n" ); + } +} + +#undef ABSENT diff --git a/sys/dev/bktr/bktr_card.h b/sys/dev/bktr/bktr_card.h new file mode 100644 index 00000000000..d6257430a84 --- /dev/null +++ b/sys/dev/bktr/bktr_card.h @@ -0,0 +1,84 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_card : This deals with identifying TV cards. + * trying to find the card make and model of card. + * trying to find the type of tuner fitted. + * reading the configuration EEPROM. + * locating i2c devices. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * If probeCard() fails to detect the correct card on boot you can + * override it by setting adding the following option to your kernel config + * options OVERRIDE_CARD + * eg options OVERRIDE CARD=1 + * + * or using the sysclt hw.bt848.card + * eg sysctl -w hw.bt848.card=1 + * + * where is one of the following card defines. + */ + +#define CARD_UNKNOWN 0 +#define CARD_MIRO 1 +#define CARD_HAUPPAUGE 2 +#define CARD_STB 3 +#define CARD_INTEL 4 /* Also for VideoLogic Captivator PCI */ +#define CARD_IMS_TURBO 5 +#define CARD_AVER_MEDIA 6 +#define CARD_OSPREY 7 +#define CARD_NEC_PK 8 +#define CARD_IO_GV 9 +#define CARD_FLYVIDEO 10 +#define CARD_ZOLTRIX 11 +#define CARD_KISS 12 +#define CARD_VIDEO_HIGHWAY_XTREME 13 +#define Bt848_MAX_CARD 14 + + +int signCard( bktr_ptr_t bktr, int offset, int count, u_char* sig ); +void probeCard( bktr_ptr_t bktr, int verbose, int unit); + +int writeEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data ); +int readEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data ); + diff --git a/sys/dev/bktr/bktr_core.c b/sys/dev/bktr/bktr_core.c index cffa17a284d..538c0058911 100644 --- a/sys/dev/bktr/bktr_core.c +++ b/sys/dev/bktr/bktr_core.c @@ -1,25 +1,34 @@ /* $FreeBSD$ */ -/* BT848 Driver for Brooktree's Bt848, Bt848A, Bt849A, Bt878, Bt879 based cards. - The Brooktree BT848 Driver driver is based upon Mark Tinguely and + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_core : This deals with the Bt848/849/878/879 PCI Frame Grabber, + * Handles all the open, close, ioctl and read userland calls. + * Sets the Bt848 registers and generates RISC pograms. + * Controls the i2c bus and GPIO interface. + * Contains the interface to the kernel. + * (eg probe/attach and open/close/ioctl) + * + */ + + /* + The Brooktree BT848 Driver driver is based upon Mark Tinguely and Jim Lowe's driver for the Matrox Meteor PCI card . The Philips SAA 7116 and SAA 7196 are very different chipsets than - the BT848. For starters, the BT848 is a one chipset solution and - it incorporates a RISC engine to control the DMA transfers -- - that is it the actual dma process is control by a program which - resides in the hosts memory also the register definitions between - the Philips chipsets and the Bt848 are very different. + the BT848. The original copyright notice by Mark and Jim is included mostly to honor their fantastic work in the Matrox Meteor driver! - Enjoy, - Amancio - */ /* * 1. Redistributions of source code must retain the - * Copyright (c) 1997 Amancio Hasty + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,7 +41,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by Amancio Hasty + * This product includes software developed by Amancio Hasty and + * Roger Hardiman * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * @@ -84,391 +94,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* Change History: -Note: These version numbers represent the authors own numbering. -They are unrelated to Revision Control numbering of FreeBSD or any other system. -1.0 1/24/97 First Alpha release - -1.1 2/20/97 Added video ioctl so we can do PCI To PCI - data transfers. This is for capturing data - directly to a vga frame buffer which has - a linear frame buffer. Minor code clean-up. - -1.3 2/23/97 Fixed system lock-up reported by - Randall Hopper . This - problem seems somehow to be exhibited only - in his system. I changed the setting of - INT_MASK for CAP_CONTINUOUS to be exactly - the same as CAP_SINGLE apparently setting - bit 23 cleared the system lock up. - version 1.1 of the driver has been reported - to work with STB's WinTv, Hauppage's Wincast/Tv - and last but not least with the Intel Smart - Video Recorder. - -1.4 3/9/97 fsmp@freefall.org - Merged code to support tuners on STB and WinCast - cards. - Modifications to the contrast and chroma ioctls. - Textual cleanup. - -1.5 3/15/97 fsmp@freefall.org - new bt848 specific versions of hue/bright/ - contrast/satu/satv. - Amancio's patch to fix "screen freeze" problem. - -1.6 3/19/97 fsmp@freefall.org - new table-driven frequency lookup. - removed disable_intr()/enable_intr() calls from i2c. - misc. cleanup. - -1.7 3/19/97 fsmp@freefall.org - added audio support submitted by: - Michael Petry - -1.8 3/20/97 fsmp@freefall.org - extended audio support. - card auto-detection. - major cleanup, order of routines, declarations, etc. - -1.9 3/22/97 fsmp@freefall.org - merged in Amancio's minor unit for tuner control - mods. - misc. cleanup, especially in the _intr routine. - made AUDIO_SUPPORT mainline code. - -1.10 3/23/97 fsmp@freefall.org - added polled hardware i2c routines, - removed all existing software i2c routines. - created software i2cProbe() routine. - Randall Hopper's fixes of BT848_GHUE & BT848_GBRIG. - eeprom support. - -1.11 3/24/97 fsmp@freefall.org - Louis Mamakos's new bt848 struct. - -1.12 3/25/97 fsmp@freefall.org - japanese freq table from Naohiro Shichijo. - new table structs for tuner lookups. - major scrub for "magic numbers". - -1.13 3/28/97 fsmp@freefall.org - 1st PAL support. - MAGIC_[1-4] demarcates magic #s needing PAL work. - AFC code submitted by Richard Tobin - . - -1.14 3/29/97 richard@cogsci.ed.ac.uk - PAL support: magic numbers moved into - format_params structure. - Revised AFC interface. - fixed DMA_PROG_ALLOC size misdefinition. - -1.15 4/18/97 John-Mark Gurney - Added [SR]RGBMASKs ioctl for byte swapping. - -1.16 4/20/97 Randall Hopper - Generalized RGBMASK ioctls for general pixel - format setting [SG]ACTPIXFMT, and added query API - to return driver-supported pix fmts GSUPPIXFMT. - -1.17 4/21/97 hasty@rah.star-gate.com - Clipping support added. - -1.18 4/23/97 Clean up after failed CAP_SINGLEs where bt - interrupt isn't delivered, and fixed fixing - CAP_SINGLEs that for ODD_ONLY fields. -1.19 9/8/97 improved yuv support , cleaned up weurope - channel table, incorporated cleanup work from - Luigi, fixed pci interface bug due to a - change in the pci interface which disables - interrupts from a PCI device by default, - Added Luigi's, ioctl's BT848_SLNOTCH, - BT848_GLNOTCH (set luma notch and get luma not) -1.20 10/5/97 Keith Sklower submitted - a patch to fix compilation of the BSDI's PCI - interface. - Hideyuki Suzuki - Submitted a patch for Japanese cable channels - Joao Carlos Mendes Luis jonny@gta.ufrj.br - Submitted general ioctl to set video broadcast - formats (PAL, NTSC, etc..) previously we depended - on the Bt848 auto video detect feature. -1.21 10/24/97 Randall Hopper - Fix temporal decimation, disable it when - doing CAP_SINGLEs, and in dual-field capture, don't - capture fields for different frames -1.22 11/08/97 Randall Hopper - Fixes for packed 24bpp - FIFO alignment -1.23 11/17/97 Amancio - Added yuv support mpeg encoding -1.24 12/27/97 Jonathan Hanna - Patch to support Philips FR1236MK2 tuner -1.25 02/02/98 Takeshi Ohashi - submitted - code to support bktr_read . - Flemming Jacobsen - submitted code to support radio available with in - some bt848 based cards;additionally, wrote code to - correctly recognized his bt848 card. - Roger Hardiman submitted - various fixes to smooth out the microcode and made - all modes consistent. -1.26 Moved Luigi's I2CWR ioctl from the video_ioctl - section to the tuner_ioctl section - Changed Major device from 79 to 92 and reserved - our Major device number -- hasty@star-gate.com -1.27 Last batch of patches for radio support from - Flemming Jacobsen . - Added B849 PCI ID submitted by: - Tomi Vainio -1.28 Frank Nobis added tuner support - for the German Phillips PAL tuner and - additional channels for german cable tv. -1.29 Roger Hardiman - Revised autodetection code to correctly handle both - old and new VideoLogic Captivator PCI cards. - Added tsleep of 2 seconds to initialistion code - for PAL users.Corrected clock selection code on - format change. -1.30 Bring back Frank Nobis 's opt_bktr.h - -1.31 Randall Hopper - submitted ioctl to clear the video buffer - prior to starting video capture - Amancio : clean up yuv12 so that it does not - affect rgb capture. Basically, fxtv after - capturing in yuv12 mode , switching to rgb - would cause the video capture to be too bright. -1.32 disable inverse gamma function for rgb and yuv - capture. fixed meteor brightness ioctl it now - converts the brightness value from unsigned to - signed. -1.33 added sysctl: hw.bt848.tuner, hw.bt848.reverse_mute, - hw.bt848.card - card takes a value from 0 to bt848_max_card - tuner takes a value from 0 to bt848_max_tuner - reverse_mute : 0 no effect, 1 reverse tuner - mute function some tuners are wired reversed :( -1.34 reverse mute function for ims turbo card - -1.35 Roger Hardiman - options BROOKTREE_SYSTEM_DEFAULT=BROOKTREE_PAL - in the kernel config file makes the driver's - video_open() function select PAL rather than NTSC. - This fixed all the hangs on my Dual Crystal card - when using a PAL video signal. As a result, you - can loose the tsleep (of 2 seconds - now 0.25!!) - which I previously added. (Unless someone else - wanted the 0.25 second tsleep). - -1.36 added bt848.format sysctl variable. - 1 denotes NTSC , 0 denotes PAL - -1.37 added support for Bt878 and improved Hauppauge's - bt848 tuner recognition -1.38 Further improvements on Hauppauge's rely on - eeprom[9] to determine the tuner type 8) - - AVerMedia card type added - -1.39 08/05/98 Roger Hardiman - Updated Hauppauge detection code for Tuner ID 0x0a - for newer NTSC WinCastTV 404 with Bt878 chipset. - Tidied up PAL default in video_open() - -1.49 10 August 1998 Roger Hardiman - Added Capture Area ioctl - BT848[SG]CAPAREA. - Normally the full 640x480 (768x576 PAL) image - is grabbed. This ioctl allows a smaller area - from anywhere within the video image to be - grabbed, eg a 400x300 image from (50,10). - See restrictions in BT848SCAPAREA. - -1.50 31 August 1998 Roger Hardiman - Renamed BT848[SG]CAPAREA to BT848_[SG]CAPAREA. - Added PR kern/7177 for SECAM Video Highway Xtreme - with single crystal PLL configuration - submitted by Vsevolod Lobko . - In kernel configuration file add - options OVERRIDE_CARD=2 - options OVERRIDE_TUNER=11 - options BKTR_USE_PLL - -1.51 31 August 1998 Roger Hardiman - Fixed bug in Miro Tuner detection. Missing Goto. - Removed Hauppauge EEPROM 0x10 detection as I think - 0x10 should be a PAL tuner, not NTSC. - Reinstated some Tuner Guesswork code from 1.27 - -1.52 3 Sep 1998 Roger Hardiman - Submitted patch by Vsevolod Lobko - to correct SECAM B-Delay and add XUSSR channel set. - -1.53 9 Sep 1998 Roger Hardiman - Changed METEORSINPUT for Hauppauge cards with bt878. - Submitted by Fred Templin - Also fixed video_open defines and 878 support. - -1.54 18 Sep 1998 Roger Hardiman - Changed tuner code to autodetect tuner i2c address. - Addresses were incorrectly hardcoded. - -1.55 21 Sep 1998 Roger Hardiman - Hauppauge Tech Support confirmed all Hauppauge 878 - PAL/SECAM boards will use PLL mode. - Added to card probe. Thanks to Ken and Fred. - -1.56 21 Jan 1999 Roger Hardiman - Added detection of Hauppauge IR remote control. - and MSP34xx Audio chip. Fixed i2c read error. - Hauppauge supplied details of new Tuner Types. - Danny Braniss submitted Bt878 - AverMedia detection with PCI subsystem vendor id. - -1.57 26 Jan 1999 Roger Hardiman - Support for MSP3410D / MSP3415D Stereo/Mono audio - using the audio format Auto Detection Mode. - Nicolas Souchu ported the - msp_read/write/reset functions to smbus/iicbus. - METEOR_INPUT_DEV2 now selects a composite camera on - the SVIDEO port for Johan Larsson - For true SVIDEO, use METEOR_INPUT_DEV_SVIDEO - -1.58 8 Feb 1999 Roger Hardiman - Added check to bktr_mmap from OpenBSD driver. - Improved MSP34xx reset for bt848 Hauppauge boards. - Added detection for Bt848a. - Vsevolod Lobko added - more XUSSR channels. - -1.59 9 Feb 1999 Added ioctl REMOTE_GETKEY for Hauppauge Infra-Red - Remote Control. Submitted by Roger Hardiman. - Added ioctl TVTUNER_GETCHANSET and - BT848_GPIO_SET_EN,BT848_GPIO_SET_DATA (and GETs) - Submitted by Vsevolod Lobko - -1.60 23 Feb 1999 Roger Hardiman - Corrected Mute on Hauppauge Radio cards. - Autodetect MMAC Osprey by looking for "MMAC" in the EEPROM. - Added for Jan Schmidt - Added ALPS Tuner Type from Hiroki Mori - -1.61 29 Apr 1999 Roger Hardiman - Fix row=0/columns=0 bug. From Randal Hopper - Add option to block the reset of the MSP34xx audio chip by - adding options BKTR_NO_MSP_RESET to the kernel config file. - This is usefull if you run another operating system - first to initialise the audio chip, then do a soft reboot. - Added for Yuri Gindin - -1.62 29 Apr 1999 Added new cards: NEC PK-UG-X017 and I/O DATA GV-BCTV2/PCI - Added new tuner: ALPS_TSBH1 (plus FM Radio for ALPS_TSCH5) - Added support for BCTV audio mux. - All submitted by Hiroki Mori - -1.63 29 Apr 1999 Roger Hardiman - Added initial code for VBI capture based on work by - Hiroki Mori and reworked by myself. - This allows software decoding of teletext, intercast and - subtitles via /dev/vbi. - -1.64 7 May 1999 Roger Hardiman - Support LifeView FlyVideo 98 cards. Use EEPROM for card - autodetection. Use bttv's audio mux values. - Thanks to Paul Reece , - Ivan Brawley and - Gilad Rom - Automatically locate the EEPROM i2c address and read the - subsystem_vendor_id from EEPROM and not the PCI registers. - Add NSMBUS checks around smbus/iicbus i2c bus code - making it easier to compile the driver under 2.2.x. - Add GPIO mask for the audio mux to each card type. - Add CARD_ZOLTRIX and CARD_KISS from mailing list searches. - -1.65 18 May 1999 Roger Hardiman - Change Intel GPIO mask to stop turning the Intel Camera off - Fixed tuner selection on Hauppauge card with tuner 0x0a - Replaced none tuner with no tuner for Theo de Raadt. - Ivan Brawley added - the Australian channel frequencies. - -1.66 19 May 1999 Ivan Brawley added better - Australian channel frequencies. - -1.67 23 May 1999 Roger Hardiman - Added rgb_vbi_prog() to capture VBI data and video at the - same time. To capture VBI data, /dev/vbi must be opened - before starting video capture. - -1.68 25 May 1999 Roger Hardiman - Due to differences in PCI bus implementations from various - motherboard chipset manufactuers, the Bt878/Bt879 has 3 - PCI bus compatibility modes. These are - NORMAL PCI 2.1 for proper PCI 2.1 compatible chipsets. - INTEL 430 FX for the Intel 430 FX chipset. - SIS VIA CHIPSET for certain SiS and VIA chipsets. - Older Intel and non-Intel chipsets may also benefit from - either 430_FX or SIS/VIA mode. - - NORMAL PCI mode is enabled by default. - For INTEL 430 FX mode, add this to your kenel config: - options "BKTR_430_FX_MODE" - For SiS / VIA mode, add this to your kernel config: - options "BKTR_SIS_VIA_MODE" - - Using quotes in these options is not needed in FreeBSD 4.x. - - Note. Newer VIA chipsets should be fully PCI 2.1 compatible - and should work fine in the Default mode. - - Also rename 849 to 849A, the correct name for the chip. - -1.69 12 June 1999 Roger Hardiman - Updates for FreeBSD 4.x device driver interface. - BSDI code removed. Will be restored later. - -1.70 12 July 1999 Roger Hardiman - Reorganise OS device dependant parts (based on a port to - linux by Brad Parker). - Make the driver compile on FreeBSD 2.2.x systems again. - Change number of VBI lines from 16 to 12 for NTSC formats. - Changes to probeCard() for better eeprom identification. - Added STB Bt878 card identification. - Add Hauppauge model identification to probeCard(). - Added TDA9850 initialisation code taken from Linux bttv. - Juha.Nurmela@quicknet.inet.fi found/fixed bug in VBI_SLEEP. - Matt Brown added MSP3430G DBX initialisation. - -1.71 30 Aug 1999 Roger Hardiman - Small cleanup of OS dependant code. Remove NPCI usage. - Fix bug in AVerMedia detection. - Update VBI support for the AleVT Teletext package. Parts - from Juha Nurmela's driver - Add support for Hauppauge 627 and Temic 4006 submitted - by Maurice Castro - Tom Jansen added BSDi support again. - -1.72 31 Aug 1999 Juha Nurmela - Clear cap_ctl register when restarting the RISC program. - This fixes the freezes experienced when changing changes. - -1.73 10 Sep 1999 Roger Hardiman - Add Hauppauge tuner #6 for Brian Somers - Add card type for Aimslabs Video Highway Xtreme for - Ladislav Kostal - Added select() code (for VBI) for the 2.2.x driver - tested by Steve Richards - -1.74 17 Sep 1999 Roger Hardiman - Fix bug where FM radio stations were offset after using FXTV - AVerMedia tuner type autodetection added for cards with - a configuration EEPROM (currently their Bt878 range) - Thanks to Frank at AVerMedia for providing the information. - Tested by David La Croix - Tidy up some tuner code and Hauppauge detection code. - New NetBSD code from Bernd Ernesti -*/ #ifdef __FreeBSD__ #include "bktr.h" @@ -491,11 +116,8 @@ They are unrelated to Revision Control numbering of FreeBSD or any other system. #include #include #include -#include #include #include -#include -#include #include #include @@ -508,45 +130,21 @@ They are unrelated to Revision Control numbering of FreeBSD or any other system. /*******************/ #ifdef __FreeBSD__ -/* __FreeBSD_version is not defined on 2.2.x systems */ -#ifndef __FreeBSD_version -#define __FreeBSD_version 228000 -#endif - -#if (__FreeBSD_version >= 300000) -#include -#endif - -/* Read NSMBUS on FreeBSD 3.1 or later */ -#if (__FreeBSD_version >= 310000) -#include "smbus.h" -#else -#define NSMBUS 0 -#endif - -#if (__FreeBSD_version < 400000) -#ifdef DEVFS -#include -#endif /* DEVFS */ -#endif - #if (__FreeBSD_version >=400000) || (NSMBUS > 0) #include /* used by smbus and newbus */ #endif -#if (__FreeBSD_version >=400000) -#include /* used by newbus */ -#include /* used by newbus */ -#include /* used by newbus */ -#endif - #include /* for DELAY */ #include -#include #include #include /* extensions to ioctl_meteor.h */ #include +#include +#include +#include +#include +#include #if (NSMBUS > 0) #include @@ -556,26 +154,9 @@ They are unrelated to Revision Control numbering of FreeBSD or any other system. #include "iicbus_if.h" #endif -#include -static int bt848_card = -1; -static int bt848_tuner = -1; -static int bt848_reverse_mute = -1; -static int bt848_format = -1; - -SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); -SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); -SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); -SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); -SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); - -#if (__FreeBSD_version >= 300000) -typedef u_long ioctl_cmd_t; -#endif #if (__FreeBSD__ == 2) -typedef int ioctl_cmd_t; typedef unsigned int uintptr_t; -#define PCIR_REVID PCI_CLASS_REG #endif #endif /* __FreeBSD__ */ @@ -644,21 +225,6 @@ typedef u_char bool_t; #define ODD_F 0x01 #define EVEN_F 0x02 -/* - * Defines for userland processes blocked in this driver - * For /dev/bktr[n] use memory address of bktr structure - * For /dev/vbi[n] use memory address of bktr structure + 1 - * this is ok as the bktr structure is > 1 byte - */ -#define BKTR_SLEEP ((caddr_t)bktr ) -#define VBI_SLEEP ((caddr_t)bktr + 1) - -/* - * This is for start-up convenience only, NOT mandatory. - */ -#if !defined( DEFAULT_CHNLSET ) -#define DEFAULT_CHNLSET CHNLSET_WEUROPE -#endif /* * Parameters describing size of transmitted image. @@ -755,98 +321,6 @@ static struct { #define WSWAP (BT848_COLOR_CTL_WSWAP_ODD | BT848_COLOR_CTL_WSWAP_EVEN) -/* experimental code for Automatic Frequency Control */ -#define TUNER_AFC -#define TEST_TUNER_AFC_NOT - -#if defined( TUNER_AFC ) -#define AFC_DELAY 10000 /* 10 millisend delay */ -#define AFC_BITS 0x07 -#define AFC_FREQ_MINUS_125 0x00 -#define AFC_FREQ_MINUS_62 0x01 -#define AFC_FREQ_CENTERED 0x02 -#define AFC_FREQ_PLUS_62 0x03 -#define AFC_FREQ_PLUS_125 0x04 -#define AFC_MAX_STEP (5 * FREQFACTOR) /* no more than 5 MHz */ -#endif /* TUNER_AFC */ - -/* - * i2c things: - */ - -#define TSA552x_CB_MSB (0x80) -#define TSA552x_CB_CP (1<<6) -#define TSA552x_CB_T2 (1<<5) -#define TSA552x_CB_T1 (1<<4) -#define TSA552x_CB_T0 (1<<3) -#define TSA552x_CB_RSA (1<<2) -#define TSA552x_CB_RSB (1<<1) -#define TSA552x_CB_OS (1<<0) -#define TSA552x_RADIO (TSA552x_CB_MSB | \ - TSA552x_CB_T0) - -/* Add RADIO_OFFSET to the "frequency" to indicate that we want to tune */ -/* the radio (if present) not the TV tuner. */ -/* 20000 is equivalent to 20000MHz/16 = 1.25GHz - this area is unused. */ -#define RADIO_OFFSET 20000 - -/* address(s) of the Hauppauge Infra-Red Remote Control adapter */ -#define HAUP_REMOTE_INT_WADDR 0x30 -#define HAUP_REMOTE_INT_RADDR 0x31 - -#define HAUP_REMOTE_EXT_WADDR 0x34 -#define HAUP_REMOTE_EXT_RADDR 0x35 - -/* address of BTSC/SAP decoder chip */ -#define TDA9850_WADDR 0xb6 -#define TDA9850_RADDR 0xb7 - -/* address of MSP3400C chip */ -#define MSP3400C_WADDR 0x80 -#define MSP3400C_RADDR 0x81 - - -/* EEProm (128 * 8) on an STB card */ -#define X24C01_WADDR 0xae -#define X24C01_RADDR 0xaf - - -/* EEProm (256 * 8) on a Hauppauge card */ -/* and on most BT878s cards to store the sub-system vendor id */ -#define PFC8582_WADDR 0xa0 -#define PFC8582_RADDR 0xa1 - - -/* registers in the TDA9850 BTSC/dbx chip */ -#define CON1ADDR 0x04 -#define CON2ADDR 0x05 -#define CON3ADDR 0x06 -#define CON4ADDR 0x07 -#define ALI1ADDR 0x08 -#define ALI2ADDR 0x09 -#define ALI3ADDR 0x0a - - -/* raise the charge pump voltage for fast tuning */ -#define TSA552x_FCONTROL (TSA552x_CB_MSB | \ - TSA552x_CB_CP | \ - TSA552x_CB_T0 | \ - TSA552x_CB_RSA | \ - TSA552x_CB_RSB) - -/* lower the charge pump voltage for better residual oscillator FM */ -#define TSA552x_SCONTROL (TSA552x_CB_MSB | \ - TSA552x_CB_T0 | \ - TSA552x_CB_RSA | \ - TSA552x_CB_RSB) - -/* The control value for the ALPS TSCH5 Tuner */ -#define TSCH5_FCONTROL 0x82 -#define TSCH5_RADIO 0x86 - -/* The control value for the ALPS TSBH1 Tuner */ -#define TSBH1_FCONTROL 0xce - /* sync detect threshold */ #if 0 @@ -858,407 +332,6 @@ static struct { #endif -/* - * the data for each type of tuner - * - * if probeCard() fails to detect the proper tuner on boot you can - * override it by setting the following define to the tuner present: - * -#define OVERRIDE_TUNER - * - * where is one of the following tuner defines. - */ - -/* indexes into tuners[] */ -#define NO_TUNER 0 -#define TEMIC_NTSC 1 -#define TEMIC_PAL 2 -#define TEMIC_SECAM 3 -#define PHILIPS_NTSC 4 -#define PHILIPS_PAL 5 -#define PHILIPS_SECAM 6 -#define TEMIC_PALI 7 -#define PHILIPS_PALI 8 -#define PHILIPS_FR1236_NTSC 9 /* These have FM Radio support */ -#define PHILIPS_FR1216_PAL 10 /* These have FM Radio support */ -#define PHILIPS_FR1236_SECAM 11 /* These have FM Radio support */ -#define ALPS_TSCH5 12 -#define ALPS_TSBH1 13 -#define Bt848_MAX_TUNER 14 - -/* If we do not know the tuner type, make a guess based on the - video format -*/ -#if BROOKTREE_SYSTEM_DEFAULT == BROOKTREE_PAL -#define DEFAULT_TUNER PHILIPS_PALI -#else -#define DEFAULT_TUNER PHILIPS_NTSC -#endif - -/* XXX FIXME: this list is incomplete */ - -/* input types */ -#define TTYPE_XXX 0 -#define TTYPE_NTSC 1 -#define TTYPE_NTSC_J 2 -#define TTYPE_PAL 3 -#define TTYPE_PAL_M 4 -#define TTYPE_PAL_N 5 -#define TTYPE_SECAM 6 - -/** -struct TUNER { - char* name; - u_char type; - u_char pllControl; - u_char bandLimits[ 2 ]; - u_char bandAddrs[ 3 ]; -}; - */ -static const struct TUNER tuners[] = { -/* XXX FIXME: fill in the band-switch crosspoints */ - /* NO_TUNER */ - { "", /* the 'name' */ - TTYPE_XXX, /* input type */ - { 0x00, /* control byte for Tuner PLL */ - 0x00, - 0x00, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x00, 0x00, 0x00,0x00} }, /* the band-switch values */ - - /* TEMIC_NTSC */ - { "Temic NTSC", /* the 'name' */ - TTYPE_NTSC, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ - - /* TEMIC_PAL */ - { "Temic PAL", /* the 'name' */ - TTYPE_PAL, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ - - /* TEMIC_SECAM */ - { "Temic SECAM", /* the 'name' */ - TTYPE_SECAM, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ - - /* PHILIPS_NTSC */ - { "Philips NTSC", /* the 'name' */ - TTYPE_NTSC, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ - - /* PHILIPS_PAL */ - { "Philips PAL", /* the 'name' */ - TTYPE_PAL, /* input type */ - { TSA552x_FCONTROL, /* control byte for Tuner PLL */ - TSA552x_FCONTROL, - TSA552x_FCONTROL, - TSA552x_RADIO }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ - - /* PHILIPS_SECAM */ - { "Philips SECAM", /* the 'name' */ - TTYPE_SECAM, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - TSA552x_RADIO }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30,0xa4 } }, /* the band-switch values */ - - /* TEMIC_PAL I */ - { "Temic PAL I", /* the 'name' */ - TTYPE_PAL, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ - - /* PHILIPS_PALI */ - { "Philips PAL I", /* the 'name' */ - TTYPE_PAL, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30,0x00 } }, /* the band-switch values */ - - /* PHILIPS_FR1236_NTSC */ - { "Philips FR1236 NTSC FM", /* the 'name' */ - TTYPE_NTSC, /* input type */ - { TSA552x_SCONTROL, /* control byte for Tuner PLL */ - TSA552x_SCONTROL, - TSA552x_SCONTROL, - TSA552x_RADIO }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ - - /* PHILIPS_FR1216_PAL */ - { "Philips FR1216 PAL FM" , /* the 'name' */ - TTYPE_PAL, /* input type */ - { TSA552x_FCONTROL, /* control byte for Tuner PLL */ - TSA552x_FCONTROL, - TSA552x_FCONTROL, - TSA552x_RADIO }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ - - /* PHILIPS_FR1236_SECAM */ - { "Philips FR1236 SECAM FM", /* the 'name' */ - TTYPE_SECAM, /* input type */ - { TSA552x_FCONTROL, /* control byte for Tuner PLL */ - TSA552x_FCONTROL, - TSA552x_FCONTROL, - TSA552x_RADIO }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ - - /* ALPS TSCH5 NTSC */ - { "ALPS TSCH5 NTSC FM", /* the 'name' */ - TTYPE_NTSC, /* input type */ - { TSCH5_FCONTROL, /* control byte for Tuner PLL */ - TSCH5_FCONTROL, - TSCH5_FCONTROL, - TSCH5_RADIO }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x14, 0x12, 0x11, 0x04 } }, /* the band-switch values */ - - /* ALPS TSBH1 NTSC */ - { "ALPS TSBH1 NTSC", /* the 'name' */ - TTYPE_NTSC, /* input type */ - { TSBH1_FCONTROL, /* control byte for Tuner PLL */ - TSBH1_FCONTROL, - TSBH1_FCONTROL, - 0x00 }, - { 0x00, 0x00 }, /* band-switch crosspoints */ - { 0x01, 0x02, 0x08, 0x00 } } /* the band-switch values */ -}; - -/****************************************************************************** - * card probe - */ - - -/* - * the recognized cards, used as indexes of several tables. - * - * if probeCard() fails to detect the proper card on boot you can - * override it by setting the following define to the card you are using: - * -#define OVERRIDE_CARD - * - * where is one of the following card defines. - */ -#define CARD_UNKNOWN 0 -#define CARD_MIRO 1 -#define CARD_HAUPPAUGE 2 -#define CARD_STB 3 -#define CARD_INTEL 4 -#define CARD_IMS_TURBO 5 -#define CARD_AVER_MEDIA 6 -#define CARD_OSPREY 7 -#define CARD_NEC_PK 8 -#define CARD_IO_GV 9 -#define CARD_FLYVIDEO 10 -#define CARD_ZOLTRIX 11 -#define CARD_KISS 12 -#define CARD_VIDEO_HIGHWAY_XTREME 13 -#define Bt848_MAX_CARD 14 - -/* - * the data for each type of card - * - * Note: - * these entried MUST be kept in the order defined by the CARD_XXX defines! - */ -static const struct CARDTYPE cards[] = { - - { CARD_UNKNOWN, /* the card id */ - "Unknown", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx unknown */ - 0, - 0, /* EEProm unknown */ - 0, /* EEProm unknown */ - { 0, 0, 0, 0, 0 }, - 0 }, /* GPIO mask */ - - { CARD_MIRO, /* the card id */ - "Miro TV", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx unknown */ - 0, - 0, /* EEProm unknown */ - 0, /* size unknown */ - { 0x02, 0x01, 0x00, 0x0a, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_HAUPPAUGE, /* the card id */ - "Hauppauge WinCast/TV", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - PFC8582_WADDR, /* EEProm type */ - (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ - { 0x00, 0x02, 0x01, 0x04, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_STB, /* the card id */ - "STB TV/PCI", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - X24C01_WADDR, /* EEProm type */ - (u_char)(128 / EEPROMBLOCKSIZE), /* 128 bytes */ - { 0x00, 0x01, 0x02, 0x02, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_INTEL, /* the card id */ - "Intel Smart Video III/VideoLogic Captivator PCI", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, - 0, - 0, - 0, - { 0, 0, 0, 0, 0 }, /* audio MUX values */ - 0x00 }, /* GPIO mask */ - - { CARD_IMS_TURBO, /* the card id */ - "IMS TV Turbo", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - PFC8582_WADDR, /* EEProm type */ - (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ - { 0x01, 0x02, 0x01, 0x00, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_AVER_MEDIA, /* the card id */ - "AVer Media TV/FM", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - 0, /* EEProm type */ - 0, /* EEProm size */ - { 0x0c, 0x00, 0x0b, 0x0b, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_OSPREY, /* the card id */ - "MMAC Osprey", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - PFC8582_WADDR, /* EEProm type */ - (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ - { 0x00, 0x00, 0x00, 0x00, 0 }, /* audio MUX values */ - 0 }, /* GPIO mask */ - - { CARD_NEC_PK, /* the card id */ - "NEC PK-UG-X017", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - 0, /* EEProm type */ - 0, /* EEProm size */ - { 0x01, 0x02, 0x01, 0x00, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_IO_GV, /* the card id */ - "I/O DATA GV-BCTV2/PCI", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - 0, /* EEProm type */ - 0, /* EEProm size */ - { 0x00, 0x00, 0x00, 0x00, 1 }, /* Has special MUX handler */ - 0x0f }, /* GPIO mask */ - - { CARD_FLYVIDEO, /* the card id */ - "FlyVideo", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, /* msp34xx is optional */ - 0xac, /* EEProm type */ - (u_char)(256 / EEPROMBLOCKSIZE), /* 256 bytes */ - { 0x000, 0x800, 0x400, 0x8dff00, 1 },/* audio MUX values */ - 0x8dff00 }, /* GPIO mask */ - - { CARD_ZOLTRIX, /* the card id */ - "Zoltrix", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, /* msp34xx is optional */ - 0, /* EEProm type */ - 0, /* EEProm size */ - { 0x04, 0x01, 0x00, 0x0a, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_KISS, /* the card id */ - "KISS TV/FM PCI", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, /* msp34xx is optional */ - 0, /* EEProm type */ - 0, /* EEProm size */ - { 0x0c, 0x00, 0x0b, 0x0b, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - - { CARD_VIDEO_HIGHWAY_XTREME, /* the card id */ - "Video Highway Xtreme", /* the 'name' */ - NULL, /* the tuner */ - 0, /* the tuner i2c address */ - 0, /* dbx is optional */ - 0, - 0, /* EEProm type */ - 0, /* EEProm size */ - { 0x00, 0x02, 0x01, 0x04, 1 }, /* audio MUX values */ - 0x0f }, /* GPIO mask */ - -}; - -struct bt848_card_sig bt848_card_signature[1]= { - /* IMS TURBO TV : card 5 */ - { 5,9, {00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 02, 00, 00, 00}} - - -}; /* debug utility for holding previous INT_STAT contents */ @@ -1284,28 +357,6 @@ static u_long status_sum = 0; #define TDEC_BITS (BT848_INT_FDSR | BT848_INT_FBUS) -/* - * misc. support routines. - */ -static int signCard( bktr_ptr_t bktr, int offset, - int count, u_char* sig ); -static void probeCard( bktr_ptr_t bktr, int verbose, int unit); - -static void common_bktr_attach( bktr_ptr_t bktr, int unit, - u_long pci_id, u_int rev ); - -/**************************************************/ -/* *** Memory Allocation is still OS specific *** */ -/**************************************************/ -#if (defined(__FreeBSD__) || defined(__bsdi__)) -static vm_offset_t get_bktr_mem( int unit, unsigned size ); -#endif - -#if (defined(__NetBSD__) || defined(__OpenBSD__)) -static vm_offset_t get_bktr_mem(bktr_ptr_t, bus_dmamap_t *, unsigned size); -static void free_bktr_mem(bktr_ptr_t, bus_dmamap_t, vm_offset_t); -#endif - static int oformat_meteor_to_bt( u_long format ); @@ -1335,57 +386,10 @@ static bool_t notclipped(bktr_reg_t * , int , int); static bool_t split(bktr_reg_t *, volatile u_long **, int, u_long, int, volatile u_char ** , int ); -/* - * video & video capture specific routines. - */ -static int video_open( bktr_ptr_t bktr ); -static int video_close( bktr_ptr_t bktr ); -static int video_read( bktr_ptr_t bktr, int unit, dev_t dev, struct uio *uio ); -static int video_ioctl( bktr_ptr_t bktr, int unit, - int cmd, caddr_t arg, struct proc* pr ); - static void start_capture( bktr_ptr_t bktr, unsigned type ); static void set_fps( bktr_ptr_t bktr, u_short fps ); -/* - * tuner specific functions. - */ -static int tuner_open( bktr_ptr_t bktr ); -static int tuner_close( bktr_ptr_t bktr ); -static int tuner_ioctl( bktr_ptr_t bktr, int unit, - int cmd, caddr_t arg, struct proc* pr ); -static int tuner_getchnlset( struct bktr_chnlset *chnlset ); - -static int tv_channel( bktr_ptr_t bktr, int channel ); -static int tv_freq( bktr_ptr_t bktr, int frequency ); -#if defined( TUNER_AFC ) -static int do_afc( bktr_ptr_t bktr, int addr, int frequency ); -#endif /* TUNER_AFC */ - -/* - * vbi specific functions. - */ -static int vbi_open( bktr_ptr_t bktr ); -static int vbi_close( bktr_ptr_t bktr ); -static int vbi_read( bktr_ptr_t bktr, struct uio *uio, int ioflag ); - -/* - * audio specific functions. - */ -static int set_audio( bktr_ptr_t bktr, int mode ); -static void temp_mute( bktr_ptr_t bktr, int flag ); - -static void init_BTSC( bktr_ptr_t bktr ); -static int set_BTSC( bktr_ptr_t bktr, int control ); - -static void msp_autodetect( bktr_ptr_t bktr ); -static void msp_read_id( bktr_ptr_t bktr, int unit ); -static void msp_reset( bktr_ptr_t bktr ); -static unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, - unsigned int addr); -static void msp_write( bktr_ptr_t bktr, unsigned char dev, - unsigned int addr, unsigned int data); /* * Remote Control Functions @@ -1400,16 +404,6 @@ static int common_ioctl( bktr_ptr_t bktr, bt848_ptr_t bt848, int cmd, caddr_t arg ); -/* - * i2c primitives - */ -static int i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ); -static int i2cRead( bktr_ptr_t bktr, int addr ); -static int writeEEProm( bktr_ptr_t bktr, int offset, int count, - u_char* data ); -static int readEEProm( bktr_ptr_t bktr, int offset, int count, - u_char* data ); - #if ((!defined(__FreeBSD__)) || (NSMBUS == 0) ) /* * i2c primatives for low level control of i2c bus. Added for MSP34xx control @@ -1420,18 +414,12 @@ static int i2c_write_byte( bktr_ptr_t bktr, unsigned char data); static int i2c_read_byte( bktr_ptr_t bktr, unsigned char *data, int last ); #endif -/* - * CARD_GV_BCTV specific functions. - */ -static void set_bctv_audio( bktr_ptr_t bktr ); -static void bctv_gpio_write( bktr_ptr_t bktr, int port, int val ); -/*static int bctv_gpio_read( bktr_ptr_t bktr, int port );*/ /* Not used */ /* * the common attach code, used by all OS versions. */ -static void +void common_bktr_attach( bktr_ptr_t bktr, int unit, u_long pci_id, u_int rev ) { bt848_ptr_t bt848; @@ -1531,7 +519,7 @@ common_bktr_attach( bktr_ptr_t bktr, int unit, u_long pci_id, u_int rev ) bktr->tuner.channel = 0; bktr->tuner.chnlset = DEFAULT_CHNLSET; bktr->tuner.afc = 0; - bktr->tuner.radio_mode = 0; + bktr->tuner.radio_mode = 0; bktr->audio_mux_select = 0; bktr->audio_mute_state = FALSE; bktr->bt848_card = -1; @@ -1540,9 +528,8 @@ common_bktr_attach( bktr_ptr_t bktr, int unit, u_long pci_id, u_int rev ) probeCard( bktr, TRUE, unit ); - /* If there is an MSP Audio device, reset it and display the model */ - if (bktr->card.msp3400c)msp_reset(bktr); - if (bktr->card.msp3400c)msp_read_id(bktr, unit); + /* Initialise any MSP34xx or TDA98xx audio chips */ + init_audio_devices( bktr ); } @@ -1567,7 +554,8 @@ static void vbidecode(bktr_ptr_t bktr) { /* Write the VBI sequence number to the end of the vbi data */ /* This is used by the AleVT teletext program */ - seq_dest = (unsigned int *)((unsigned char *)bktr->vbibuffer + bktr->vbiinsert + seq_dest = (unsigned int *)((unsigned char *)bktr->vbibuffer + + bktr->vbiinsert + (VBI_DATA_SIZE - sizeof(bktr->vbi_sequence_number))); *seq_dest = bktr->vbi_sequence_number; @@ -1593,7 +581,7 @@ static void vbidecode(bktr_ptr_t bktr) { * In the OS specific section, bktr_intr() is defined which calls this * common interrupt handler. */ -static int +int common_bktr_intr( void *arg ) { bktr_ptr_t bktr; @@ -1867,7 +855,8 @@ common_bktr_intr( void *arg ) /* * */ -static int +extern int bt848_format; /* used to set the default format, PAL or NTSC */ +int video_open( bktr_ptr_t bktr ) { bt848_ptr_t bt848; @@ -1977,7 +966,7 @@ video_open( bktr_ptr_t bktr ) return( 0 ); } -static int +int vbi_open( bktr_ptr_t bktr ) { if (bktr->vbiflags & VBI_OPEN) /* device is busy */ @@ -2001,7 +990,7 @@ vbi_open( bktr_ptr_t bktr ) /* * */ -static int +int tuner_open( bktr_ptr_t bktr ) { if ( !(bktr->tflags & TUNER_INITALIZED) ) /* device not found */ @@ -2015,7 +1004,7 @@ tuner_open( bktr_ptr_t bktr ) bktr->tuner.channel = 0; bktr->tuner.chnlset = DEFAULT_CHNLSET; bktr->tuner.afc = 0; - bktr->tuner.radio_mode = 0; + bktr->tuner.radio_mode = 0; /* enable drivers on the GPIO port that control the MUXes */ bktr->base->gpio_out_en |= bktr->card.gpio_mux_bits; @@ -2023,13 +1012,8 @@ tuner_open( bktr_ptr_t bktr ) /* unmute the audio stream */ set_audio( bktr, AUDIO_UNMUTE ); - /* enable stereo if appropriate on TDA audio chip */ - if ( bktr->card.dbx ) - init_BTSC( bktr ); - - /* reset the MSP34xx stereo audio chip */ - if ( bktr->card.msp3400c ) - msp_reset( bktr ); + /* Initialise any audio chips, eg MSP34xx or TDA98xx */ + init_audio_devices( bktr ); return( 0 ); } @@ -2040,7 +1024,7 @@ tuner_open( bktr_ptr_t bktr ) /* * */ -static int +int video_close( bktr_ptr_t bktr ) { bt848_ptr_t bt848; @@ -2070,7 +1054,7 @@ video_close( bktr_ptr_t bktr ) * tuner close handle, * place holder for tuner specific operations on a close. */ -static int +int tuner_close( bktr_ptr_t bktr ) { bktr->tflags &= ~TUNER_OPEN; @@ -2084,7 +1068,7 @@ tuner_close( bktr_ptr_t bktr ) return( 0 ); } -static int +int vbi_close( bktr_ptr_t bktr ) { @@ -2096,7 +1080,7 @@ vbi_close( bktr_ptr_t bktr ) /* * */ -static int +int video_read(bktr_ptr_t bktr, int unit, dev_t dev, struct uio *uio) { bt848_ptr_t bt848; @@ -2153,7 +1137,7 @@ video_read(bktr_ptr_t bktr, int unit, dev_t dev, struct uio *uio) * vbistart is the actual position in the buffer we want to read from * vbisize is the exact number of bytes in the buffer left to read */ -static int +int vbi_read(bktr_ptr_t bktr, struct uio *uio, int ioflag) { int readsize, readsize2; @@ -2200,7 +1184,7 @@ vbi_read(bktr_ptr_t bktr, struct uio *uio, int ioflag) bktr->vbistart += readsize; bktr->vbistart = bktr->vbistart % VBI_BUFFER_SIZE; /* wrap around if needed */ -return( status ); + return( status ); } @@ -2209,7 +1193,7 @@ return( status ); /* * video ioctls */ -static int +int video_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) { bt848_ptr_t bt848; @@ -2813,7 +1797,7 @@ video_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) /* * tuner ioctls */ -static int +int tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) { bt848_ptr_t bt848; @@ -2852,15 +1836,18 @@ tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) case TVTUNER_SETCHNL: temp_mute( bktr, TRUE ); temp = tv_channel( bktr, (int)*(unsigned long *)arg ); - temp_mute( bktr, FALSE ); - if ( temp < 0 ) + if ( temp < 0 ) { + temp_mute( bktr, FALSE ); return( EINVAL ); + } *(unsigned long *)arg = temp; /* after every channel change, we must restart the MSP34xx */ /* audio chip to reselect NICAM STEREO or MONO audio */ if ( bktr->card.msp3400c ) msp_autodetect( bktr ); + + temp_mute( bktr, FALSE ); break; case TVTUNER_GETCHNL: @@ -2879,22 +1866,26 @@ tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) break; case TVTUNER_GETSTATUS: - temp = i2cRead( bktr, bktr->card.tuner_pllAddr + 1 ); + temp = get_tuner_status( bktr ); *(unsigned long *)arg = temp & 0xff; break; case TVTUNER_SETFREQ: temp_mute( bktr, TRUE ); - temp = tv_freq( bktr, (int)*(unsigned long *)arg ); + temp = tv_freq( bktr, (int)*(unsigned long *)arg, TV_FREQUENCY); temp_mute( bktr, FALSE ); - if ( temp < 0 ) + if ( temp < 0 ) { + temp_mute( bktr, FALSE ); return( EINVAL ); + } *(unsigned long *)arg = temp; /* after every channel change, we must restart the MSP34xx */ /* audio chip to reselect NICAM STEREO or MONO audio */ if ( bktr->card.msp3400c ) msp_autodetect( bktr ); + + temp_mute( bktr, FALSE ); break; case TVTUNER_GETFREQ: @@ -3133,7 +2124,7 @@ tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) break; case RADIO_GETFREQ: - *(unsigned long *)arg = (bktr->tuner.frequency+407)*5; + *(unsigned long *)arg = bktr->tuner.frequency; break; case RADIO_SETFREQ: @@ -3141,20 +2132,7 @@ tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) ** freq*100. */ - /* The radio in my stereo and the linear regression function - ** in my HP48 have reached the conclusion that in order to - ** set the radio tuner of the FM1216 to f MHz, the value to - ** enter into the Tuner PLL is: f*20-407 - ** If anyone has the exact values from the spec. sheet - ** please forward them -- fj@login.dknet.dk - */ - - if(bktr->bt848_tuner == ALPS_TSCH5) { - temp=((int)*(unsigned long *)arg + 4125) * 32; - temp=temp/100 + (temp%100 >= 50 ? 1 : 0) +RADIO_OFFSET; - } else { - temp=(int)*(unsigned long *)arg/5-407 +RADIO_OFFSET; - } + temp=(int)*(unsigned long *)arg; #ifdef BKTR_RADIO_DEBUG printf("bktr%d: arg=%d temp=%d\n",unit,(int)*(unsigned long *)arg,temp); @@ -3163,13 +2141,13 @@ tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) #ifndef BKTR_RADIO_NOFREQCHECK /* According to the spec. sheet the band: 87.5MHz-108MHz */ /* is supported. */ - if(temp<1343+RADIO_OFFSET || temp>1753+RADIO_OFFSET) { + if(temp<8750 || temp>10800) { printf("bktr%d: Radio frequency out of range\n",unit); return(EINVAL); } #endif temp_mute( bktr, TRUE ); - temp = tv_freq( bktr, temp ); + temp = tv_freq( bktr, temp, FM_RADIO_FREQUENCY ); temp_mute( bktr, FALSE ); #ifdef BKTR_RADIO_DEBUG if(temp) @@ -3179,7 +2157,8 @@ tuner_ioctl( bktr_ptr_t bktr, int unit, int cmd, caddr_t arg, struct proc* pr ) return( EINVAL ); *(unsigned long *)arg = temp; break; - /* Luigi's I2CWR ioctl */ + + /* Luigi's I2CWR ioctl */ case BT848_I2CWR: par = *(u_long *)arg; write = (par >> 24) & 0xff ; @@ -3609,7 +2588,7 @@ rgb_vbi_prog( bktr_ptr_t bktr, char i_flag, int cols, int rows, int interlace ) bt848_ptr_t bt848; volatile u_long target_buffer, buffer, target,width; volatile u_long pitch; - volatile u_long *dma_prog; /* DMA prog is an array of + volatile u_long *dma_prog; /* DMA prog is an array of 32 bit RISC instructions */ volatile u_long *loop_point; struct meteor_pixfmt_internal *pf_int = &pixfmt_table[ bktr->pixfmt ]; @@ -4710,7 +3689,7 @@ static int oformat_meteor_to_bt( u_long format ) /* * The hardware interface is actually SMB commands */ -static int +int i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ) { char cmd; @@ -4736,7 +3715,7 @@ i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ) return( 0 ); } -static int +int i2cRead( bktr_ptr_t bktr, int addr ) { char result; @@ -4762,7 +3741,7 @@ i2cRead( bktr_ptr_t bktr, int addr ) /* Therefore we need low level control of the i2c bus hardware */ /* Write to the MSP registers */ -static void +void msp_write(bktr_ptr_t bktr, unsigned char dev, unsigned int addr, unsigned int data) { unsigned char addr_l, addr_h, data_h, data_l ; @@ -4772,7 +3751,7 @@ msp_write(bktr_ptr_t bktr, unsigned char dev, unsigned int addr, unsigned int da data_h = (data >>8) & 0xff; data_l = data & 0xff; - iicbus_start(IICBUS(bktr), MSP3400C_WADDR, 0 /* no timeout? */); + iicbus_start(IICBUS(bktr), bktr->msp_addr, 0 /* no timeout? */); iicbus_write_byte(IICBUS(bktr), dev, 0); iicbus_write_byte(IICBUS(bktr), addr_h, 0); @@ -4786,7 +3765,7 @@ msp_write(bktr_ptr_t bktr, unsigned char dev, unsigned int addr, unsigned int da } /* Write to the MSP registers */ -static unsigned int +unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int addr) { unsigned int data; @@ -4799,13 +3778,13 @@ msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int addr) dev_r = dev+1; /* XXX errors ignored */ - iicbus_start(IICBUS(bktr), MSP3400C_WADDR, 0 /* no timeout? */); + iicbus_start(IICBUS(bktr), bktr->msp_addr, 0 /* no timeout? */); iicbus_write_byte(IICBUS(bktr), dev_r, 0); iicbus_write_byte(IICBUS(bktr), addr_h, 0); iicbus_write_byte(IICBUS(bktr), addr_l, 0); - iicbus_repeated_start(IICBUS(bktr), MSP3400C_RADDR, 0 /* no timeout? */); + iicbus_repeated_start(IICBUS(bktr), bktr->msp_addr +1, 0 /* no timeout? */); iicbus_read(IICBUS(bktr), data_read, 2, &read, IIC_LAST_READ, 0); iicbus_stop(IICBUS(bktr)); @@ -4818,20 +3797,20 @@ msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int addr) /* The user can block the reset (which is handy if you initialise the * MSP audio in another operating system first (eg in Windows) */ -static void +void msp_reset( bktr_ptr_t bktr ) { #ifndef BKTR_NO_MSP_RESET /* put into reset mode */ - iicbus_start(IICBUS(bktr), MSP3400C_WADDR, 0 /* no timeout? */); + iicbus_start(IICBUS(bktr), bktr->msp_addr, 0 /* no timeout? */); iicbus_write_byte(IICBUS(bktr), 0x00, 0); iicbus_write_byte(IICBUS(bktr), 0x80, 0); iicbus_write_byte(IICBUS(bktr), 0x00, 0); iicbus_stop(IICBUS(bktr)); /* put back to operational mode */ - iicbus_start(IICBUS(bktr), MSP3400C_WADDR, 0 /* no timeout? */); + iicbus_start(IICBUS(bktr), bktr->msp_addr, 0 /* no timeout? */); iicbus_write_byte(IICBUS(bktr), 0x00, 0); iicbus_write_byte(IICBUS(bktr), 0x00, 0); iicbus_write_byte(IICBUS(bktr), 0x00, 0); @@ -4856,7 +3835,7 @@ static void remote_read(bktr_ptr_t bktr, struct bktr_remote *remote) { /* * Program the i2c bus directly */ -static int +int i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ) { u_long x; @@ -4902,7 +3881,7 @@ i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ) /* * */ -static int +int i2cRead( bktr_ptr_t bktr, int addr ) { u_long x; @@ -5041,8 +4020,8 @@ static int i2c_read_byte( bktr_ptr_t bktr, unsigned char *data, int last ) { #undef BITD /* Write to the MSP registers */ -static void msp_write( bktr_ptr_t bktr, unsigned char dev, unsigned int addr, unsigned int data){ - unsigned int msp_w_addr = MSP3400C_WADDR; +void msp_write( bktr_ptr_t bktr, unsigned char dev, unsigned int addr, unsigned int data){ + unsigned int msp_w_addr = bktr->msp_addr; unsigned char addr_l, addr_h, data_h, data_l ; addr_h = (addr >>8) & 0xff; addr_l = addr & 0xff; @@ -5060,7 +4039,7 @@ static void msp_write( bktr_ptr_t bktr, unsigned char dev, unsigned int addr, un } /* Write to the MSP registers */ -static unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int addr){ +unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int addr){ unsigned int data; unsigned char addr_l, addr_h, data_1, data_2, dev_r ; addr_h = (addr >>8) & 0xff; @@ -5068,13 +4047,13 @@ static unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int ad dev_r = dev+1; i2c_start(bktr); - i2c_write_byte(bktr,MSP3400C_WADDR); + i2c_write_byte(bktr,bktr->msp_addr); i2c_write_byte(bktr,dev_r); i2c_write_byte(bktr,addr_h); i2c_write_byte(bktr,addr_l); i2c_start(bktr); - i2c_write_byte(bktr,MSP3400C_RADDR); + i2c_write_byte(bktr,bktr->msp_addr+1); i2c_read_byte(bktr,&data_1, 0); i2c_read_byte(bktr,&data_2, 1); i2c_stop(bktr); @@ -5086,12 +4065,12 @@ static unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int ad /* The user can block the reset (which is handy if you initialise the * MSP audio in another operating system first (eg in Windows) */ -static void msp_reset( bktr_ptr_t bktr ) { +void msp_reset( bktr_ptr_t bktr ) { #ifndef BKTR_NO_MSP_RESET /* put into reset mode */ i2c_start(bktr); - i2c_write_byte(bktr, MSP3400C_WADDR); + i2c_write_byte(bktr, bktr->msp_addr); i2c_write_byte(bktr, 0x00); i2c_write_byte(bktr, 0x80); i2c_write_byte(bktr, 0x00); @@ -5099,7 +4078,7 @@ static void msp_reset( bktr_ptr_t bktr ) { /* put back to operational mode */ i2c_start(bktr); - i2c_write_byte(bktr, MSP3400C_WADDR); + i2c_write_byte(bktr, bktr->msp_addr); i2c_write_byte(bktr, 0x00); i2c_write_byte(bktr, 0x00); i2c_write_byte(bktr, 0x00); @@ -5197,2321 +4176,7 @@ i2cProbe( bktr_ptr_t bktr, int addr ) #endif /* I2C_SOFTWARE_PROBE */ -/* - * - */ -static int -writeEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data ) -{ - return( -1 ); -} - - -/* - * - */ -static int -readEEProm( bktr_ptr_t bktr, int offset, int count, u_char *data ) -{ - int x; - int addr; - int max; - int byte; - - /* get the address of the EEProm */ - addr = (int)(bktr->card.eepromAddr & 0xff); - if ( addr == 0 ) - return( -1 ); - - max = (int)(bktr->card.eepromSize * EEPROMBLOCKSIZE); - if ( (offset + count) > max ) - return( -1 ); - - /* set the start address */ - if ( i2cWrite( bktr, addr, offset, -1 ) == -1 ) - return( -1 ); - - /* the read cycle */ - for ( x = 0; x < count; ++x ) { - if ( (byte = i2cRead( bktr, (addr | 1) )) == -1 ) - return( -1 ); - data[ x ] = byte; - } - - return( 0 ); -} - #define ABSENT (-1) -/* - * get a signature of the card - * read all 128 possible i2c read addresses from 0x01 thru 0xff - * build a bit array with a 1 bit for each i2c device that responds - * - * XXX FIXME: use offset & count args - */ -static int -signCard( bktr_ptr_t bktr, int offset, int count, u_char* sig ) -{ - int x; - - for ( x = 0; x < 16; ++x ) - sig[ x ] = 0; - - for ( x = 0; x < count; ++x ) { - if ( i2cRead( bktr, (2 * x) + 1 ) != ABSENT ) { - sig[ x / 8 ] |= (1 << (x % 8) ); - } - } - - return( 0 ); -} - -/* - * any_i2c_devices. - * Some BT848/BT848A cards have no tuner and no additional i2c devices - * eg stereo decoder. These are used for video conferencing or capture from - * a video camera. (VideoLogic Captivator PCI, Intel SmartCapture card). - * - * Determine if there are any i2c devices present. There are none present if - * a) reading from all 128 devices returns ABSENT (-1) for each one - * (eg VideoLogic Captivator PCI with BT848) - * b) reading from all 128 devices returns 0 for each one - * (eg VideoLogic Captivator PCI rev. 2F with BT848A) - */ -static int check_for_i2c_devices( bktr_ptr_t bktr ){ - int x, temp_read; - int i2c_all_0 = 1; - int i2c_all_absent = 1; - for ( x = 0; x < 128; ++x ) { - temp_read = i2cRead( bktr, (2 * x) + 1 ); - if (temp_read != 0) i2c_all_0 = 0; - if (temp_read != ABSENT) i2c_all_absent = 0; - } - - if ((i2c_all_0) || (i2c_all_absent)) return 0; - else return 1; -} - -/* - * Temic/Philips datasheets say tuners can be at i2c addresses 0xc0, 0xc2, - * 0xc4 or 0xc6, settable by links on the tuner - * Determine the actual address used on the TV card by probing read addresses - */ -static int locate_tuner_address( bktr_ptr_t bktr) { - if (i2cRead( bktr, 0xc1) != ABSENT) return 0xc0; - if (i2cRead( bktr, 0xc3) != ABSENT) return 0xc2; - if (i2cRead( bktr, 0xc5) != ABSENT) return 0xc4; - if (i2cRead( bktr, 0xc7) != ABSENT) return 0xc6; - return -1; /* no tuner found */ -} - -/* - * Search for a configuration EEPROM on the i2c bus by looking at i2c addresses - * where EEPROMs are usually found. - */ -static int locate_eeprom_address( bktr_ptr_t bktr) { - if (i2cRead( bktr, 0xa0) != ABSENT) return 0xa0; - if (i2cRead( bktr, 0xac) != ABSENT) return 0xac; - if (i2cRead( bktr, 0xae) != ABSENT) return 0xae; - return -1; /* no eeprom found */ -} - -/* - * determine the card brand/model - * OVERRIDE_CARD, OVERRIDE_TUNER, OVERRIDE_DBX and OVERRIDE_MSP - * can be used to select a specific device, regardless of the - * autodetection and i2c device checks. - * - * The scheme used for probing cards has one major drawback: - * on bt848/849 based cards, it is impossible to work out which type - * of tuner is actually fitted, or if there is extra hardware on board - * connected to GPIO pins (eg radio chips or MSP34xx reset logic) - * The driver cannot tell if the Tuner is PAL,NTSC, Temic or Philips. - * - * All Hauppauge cards have a configuration eeprom which tells us the - * tuner type and other features of the their cards. - * Also, Bt878 based cards (certainly Hauppauge and AverMedia) should support - * sub-system vendor id, identifying the make and model of the card. - * - * The current probe code works as follows - * 1) Check if it is a BT878. If so, read the sub-system vendor id. - * Select the required tuner and other onboard features. - * 2) If it is a BT848, 848A or 849A, continue on: - * 3) Some cards have no I2C devices. Check if the i2c bus is empty - * and if so, our detection job is nearly over. - * 4) Check I2C address 0xa0. If present this will be a Hauppauge card - * or an Osprey card. The Hauppauge EEPROM can determine on board tuner - * type and other features. - * 4) Check I2C address 0xa8. If present this is a STB card. - * Still have to guess on the tuner type. - * 5) Otherwise we are in the dark. Miro cards have the tuner type - * hard-coded on the GPIO pins, but we do not actually know if we have - * a Miro card. - * Some older makes of card put Philips tuners and Temic tuners at - * different I2C addresses, so an i2c bus probe can help, but it is - * really just a guess. - * - * 6) After determining the Tuner Type, we probe the i2c bus for other - * devices at known locations, eg IR-Remote Control, MSP34xx and TDA - * stereo chips. - */ - -#define VENDOR_AVER_MEDIA 0x1461 -#define VENDOR_HAUPPAUGE 0x0070 -#define VENDOR_FLYVIDEO 0x1851 -#define VENDOR_STB 0x10B4 - -static void -probeCard( bktr_ptr_t bktr, int verbose, int unit ) -{ - int card, i,j, card_found; - int status; - bt848_ptr_t bt848; - u_char probe_signature[128], *probe_temp; - int any_i2c_devices; - u_char eeprom[256]; - int tuner_i2c_address = -1; - int eeprom_i2c_address = -1; - - bt848 = bktr->base; - - /* Select all GPIO bits as inputs */ - bt848->gpio_out_en = 0; - if (bootverbose) - printf("bktr: GPIO is 0x%08x\n", bt848->gpio_data); - -#ifdef HAUPPAUGE_MSP_RESET - /* Reset the MSP34xx audio chip. This resolves bootup card - * detection problems with old Bt848 based Hauppauge cards with - * MSP34xx stereo audio chips. This must be user enabled because - * at this point the probe function does not know the card type. */ - bt848->gpio_out_en = bt848->gpio_out_en | (1<<5); - bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ - DELAY(2500); /* wait 2.5ms */ - bt848->gpio_data = bt848->gpio_data & ~(1<<5); /* write '0' */ - DELAY(2500); /* wait 2.5ms */ - bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ - DELAY(2500); /* wait 2.5ms */ -#endif - - /* Check for the presence of i2c devices */ - any_i2c_devices = check_for_i2c_devices( bktr ); - - - /* Check for a user specified override on the card selection */ -#if defined( OVERRIDE_CARD ) - bktr->card = cards[ (card = OVERRIDE_CARD) ]; - goto checkEEPROM; -#endif - if (bktr->bt848_card != -1 ) { - bktr->card = cards[ (card = bktr->bt848_card) ]; - goto checkEEPROM; - } - - - /* No override, so try and determine the make of the card */ - - /* On BT878/879 cards, read the sub-system vendor id */ - /* This identifies the manufacturer of the card and the model */ - /* In theory this can be read from PCI registers but this does not */ - /* appear to work on the FlyVideo 98. Hauppauge also warned that */ - /* the PCI registers are sometimes not loaded correctly. */ - /* Therefore, I will read the sub-system vendor ID from the EEPROM */ - /* (just like the Bt878 does during power up initialisation) */ - - if (bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) { - - /* Try and locate the EEPROM */ - eeprom_i2c_address = locate_eeprom_address( bktr ); - if (eeprom_i2c_address != -1) { - - unsigned int subsystem_vendor_id; /* vendors PCI-SIG ID */ - unsigned int subsystem_id; /* board model number */ - unsigned int byte_252, byte_253, byte_254, byte_255; - - bktr->card = cards[ (card = CARD_UNKNOWN) ]; - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - - readEEProm(bktr, 0, 256, (u_char *) &eeprom ); - byte_252 = (unsigned int)eeprom[252]; - byte_253 = (unsigned int)eeprom[253]; - byte_254 = (unsigned int)eeprom[254]; - byte_255 = (unsigned int)eeprom[255]; - - subsystem_id = (byte_252 << 8) | byte_253; - subsystem_vendor_id = (byte_254 << 8) | byte_255; - - if ( bootverbose ) - printf("subsytem 0x%04x 0x%04x\n",subsystem_vendor_id, - subsystem_id); - - if (subsystem_vendor_id == VENDOR_AVER_MEDIA) { - bktr->card = cards[ (card = CARD_AVER_MEDIA) ]; - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - goto checkTuner; - } - - if (subsystem_vendor_id == VENDOR_HAUPPAUGE) { - bktr->card = cards[ (card = CARD_HAUPPAUGE) ]; - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - goto checkTuner; - } - - if (subsystem_vendor_id == VENDOR_FLYVIDEO) { - bktr->card = cards[ (card = CARD_FLYVIDEO) ]; - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - goto checkTuner; - } - - if (subsystem_vendor_id == VENDOR_STB) { - bktr->card = cards[ (card = CARD_STB) ]; - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - goto checkTuner; - } - - /* Vendor is unknown. We will use the standard probe code */ - /* which may not give best results */ - printf("Warning - card vendor 0x%04x (model 0x%04x) unknown. This may cause poor performance\n",subsystem_vendor_id,subsystem_id); - } - else - { - printf("Warning - card has no configuration EEPROM. Cannot determine card make. This may cause poor performance\n"); - } - } /* end of bt878/bt879 card detection code */ - - /* If we get to this point, we must have a Bt848/848A/849A card */ - /* or a Bt878/879 with an unknown subsystem vendor id */ - /* Try and determine the make of card by clever i2c probing */ - - /* Check for i2c devices. If none, move on */ - if (!any_i2c_devices) { - bktr->card = cards[ (card = CARD_INTEL) ]; - bktr->card.eepromAddr = 0; - bktr->card.eepromSize = 0; - goto checkTuner; - } - - - /* Look for Hauppauge, STB and Osprey cards by the presence */ - /* of an EEPROM */ - /* Note: Bt878 based cards also use EEPROMs so we can only do this */ - /* test on BT848/848A and 849A based cards. */ - if ((bktr->id==BROOKTREE_848) || - (bktr->id==BROOKTREE_848A) || - (bktr->id==BROOKTREE_849A)) { - - /* At i2c address 0xa0, look for Hauppauge and Osprey cards */ - if ( (status = i2cRead( bktr, PFC8582_RADDR )) != ABSENT ) { - - /* Read the eeprom contents */ - bktr->card = cards[ (card = CARD_UNKNOWN) ]; - bktr->card.eepromAddr = PFC8582_WADDR; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - readEEProm(bktr, 0, 128, (u_char *) &eeprom ); - - /* For Hauppauge, check the EEPROM begins with 0x84 */ - if (eeprom[0] == 0x84) { - bktr->card = cards[ (card = CARD_HAUPPAUGE) ]; - bktr->card.eepromAddr = PFC8582_WADDR; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - goto checkTuner; - } - - /* For Osprey, check the EEPROM begins with "MMAC" */ - if ( (eeprom[0] == 'M') &&(eeprom[1] == 'M') - &&(eeprom[2] == 'A') &&(eeprom[3] == 'C')) { - bktr->card = cards[ (card = CARD_OSPREY) ]; - bktr->card.eepromAddr = PFC8582_WADDR; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - goto checkTuner; - } - printf("Warning: Unknown card type. EEPROM data not recognised\n"); - printf("%x %x %x %x\n",eeprom[0],eeprom[1],eeprom[2],eeprom[3]); - } - - /* look for an STB card */ - if ( (status = i2cRead( bktr, X24C01_RADDR )) != ABSENT ) { - bktr->card = cards[ (card = CARD_STB) ]; - bktr->card.eepromAddr = X24C01_WADDR; - bktr->card.eepromSize = (u_char)(128 / EEPROMBLOCKSIZE); - goto checkTuner; - } - - } - - signCard( bktr, 1, 128, (u_char *) &probe_signature ); - - if (bootverbose) { - printf("card signature \n"); - for (j = 0; j < Bt848_MAX_SIGN; j++) { - printf(" %02x ", probe_signature[j]); - } - printf("\n\n"); - } - for (i = 0; - i < (sizeof bt848_card_signature)/ sizeof (struct bt848_card_sig); - i++ ) { - - card_found = 1; - probe_temp = (u_char *) &bt848_card_signature[i].signature; - - for (j = 0; j < Bt848_MAX_SIGN; j++) { - if ((probe_temp[j] & 0xf) != (probe_signature[j] & 0xf)) { - card_found = 0; - break; - } - - } - if (card_found) { - bktr->card = cards[ card = bt848_card_signature[i].card]; - bktr->card.tuner = &tuners[ bt848_card_signature[i].tuner]; - eeprom_i2c_address = locate_eeprom_address( bktr ); - if (eeprom_i2c_address != -1) { - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - } else { - bktr->card.eepromAddr = 0; - bktr->card.eepromSize = 0; - } - goto checkDBX; - } - } - - /* We do not know the card type. Default to Miro */ - bktr->card = cards[ (card = CARD_MIRO) ]; - - -checkEEPROM: - /* look for a configuration eeprom */ - eeprom_i2c_address = locate_eeprom_address( bktr ); - if (eeprom_i2c_address != -1) { - bktr->card.eepromAddr = eeprom_i2c_address; - bktr->card.eepromSize = (u_char)(256 / EEPROMBLOCKSIZE); - } else { - bktr->card.eepromAddr = 0; - bktr->card.eepromSize = 0; - } - - -checkTuner: - - /* look for a tuner */ - tuner_i2c_address = locate_tuner_address( bktr ); - if ( tuner_i2c_address == -1 ) { - bktr->card.tuner = &tuners[ NO_TUNER ]; - goto checkDBX; - } - -#if defined( OVERRIDE_TUNER ) - bktr->card.tuner = &tuners[ OVERRIDE_TUNER ]; - goto checkDBX; -#endif - if (bktr->bt848_tuner != -1 ) { - bktr->card.tuner = &tuners[ bktr->bt848_tuner & 0xff ]; - goto checkDBX; - } - - /* Check for i2c devices */ - if (!any_i2c_devices) { - bktr->card.tuner = &tuners[ NO_TUNER ]; - goto checkDBX; - } - - /* differentiate type of tuner */ - - switch (card) { - case CARD_MIRO: - switch (((bt848->gpio_data >> 10)-1)&7) { - case 0: bktr->card.tuner = &tuners[ TEMIC_PAL ]; break; - case 1: bktr->card.tuner = &tuners[ PHILIPS_PAL ]; break; - case 2: bktr->card.tuner = &tuners[ PHILIPS_NTSC ]; break; - case 3: bktr->card.tuner = &tuners[ PHILIPS_SECAM ]; break; - case 4: bktr->card.tuner = &tuners[ NO_TUNER ]; break; - case 5: bktr->card.tuner = &tuners[ PHILIPS_PALI ]; break; - case 6: bktr->card.tuner = &tuners[ TEMIC_NTSC ]; break; - case 7: bktr->card.tuner = &tuners[ TEMIC_PALI ]; break; - } - goto checkDBX; - break; - - case CARD_HAUPPAUGE: - /* Hauppauge kindly supplied the following Tuner Table */ - /* FIXME: I think the tuners the driver selects for types */ - /* 0x08 and 0x15 may be incorrect but no one has complained. */ - /* - ID Tuner Model Format We select Format - 0 NONE - 1 EXTERNAL - 2 OTHER - 3 Philips FI1216 BG - 4 Philips FI1216MF BGLL' - 5 Philips FI1236 MN PHILIPS_NTSC - 6 Philips FI1246 I PHILIPS_PALI - 7 Philips FI1256 DK - 8 Philips FI1216 MK2 BG PHILIPS_PALI - 9 Philips FI1216MF MK2 BGLL' - a Philips FI1236 MK2 MN PHILIPS_NTSC - b Philips FI1246 MK2 I PHILIPS_PALI - c Philips FI1256 MK2 DK - d Temic 4032FY5 NTSC TEMIC_NTSC - e Temic 4002FH5 BG TEMIC_PAL - f Temic 4062FY5 I TEMIC_PALI - 10 Philips FR1216 MK2 BG - 11 Philips FR1216MF MK2 BGLL' - 12 Philips FR1236 MK2 MN PHILIPS_FR1236_NTSC - 13 Philips FR1246 MK2 I - 14 Philips FR1256 MK2 DK - 15 Philips FM1216 BG PHILIPS_FR1216_PAL - 16 Philips FM1216MF BGLL' - 17 Philips FM1236 MN PHILIPS_FR1236_NTSC - 18 Philips FM1246 I - 19 Philips FM1256 DK - 1a Temic 4036FY5 MN - FI1236 MK2 clone - 1b Samsung TCPN9082D MN - 1c Samsung TCPM9092P Pal BG/I/DK - 1d Temic 4006FH5 BG PHILIPS_PALI clone - 1e Samsung TCPN9085D MN/Radio - 1f Samsung TCPB9085P Pal BG/I/DK / Radio - 20 Samsung TCPL9091P Pal BG & Secam L/L' - 21 Temic 4039FY5 NTSC Radio - - */ - - if (bktr->card.eepromAddr != 0) { - u_char tuner_code; - u_int model; - u_int revision; - - readEEProm(bktr, 0, 128, (u_char *) &eeprom ); - - - /* Determine the model number from the eeprom */ - model = (eeprom[12] << 8 | eeprom[11]); - revision = (eeprom[15] << 16 | eeprom[14] << 8 | eeprom[13]); - if (verbose) - printf("bktr%d: Hauppauge Model %d %c%c%c%c\n", - unit, - model, - ((revision >> 18) & 0x3f) + 32, - ((revision >> 12) & 0x3f) + 32, - ((revision >> 6) & 0x3f) + 32, - ((revision >> 0) & 0x3f) + 32 ); - - /* Determine the tuner type from the eeprom */ - tuner_code = eeprom[9]; - switch (tuner_code) { - - case 0x5: - case 0x0a: - case 0x1a: - bktr->card.tuner = &tuners[ PHILIPS_NTSC ]; - goto checkDBX; - - case 0x12: - case 0x17: - bktr->card.tuner = &tuners[ PHILIPS_FR1236_NTSC ]; - goto checkDBX; - - case 0x6: - case 0x8: - case 0xb: - case 0x1d: - bktr->card.tuner = &tuners[ PHILIPS_PALI ]; - goto checkDBX; - - case 0xd: - bktr->card.tuner = &tuners[ TEMIC_NTSC ]; - goto checkDBX; - - case 0xe: - bktr->card.tuner = &tuners[ TEMIC_PAL]; - goto checkDBX; - - case 0xf: - bktr->card.tuner = &tuners[ TEMIC_PALI ]; - goto checkDBX; - - case 0x15: - bktr->card.tuner = &tuners[ PHILIPS_FR1216_PAL]; - goto checkDBX; - - default : - printf("Warning - Unknown Hauppauge Tuner 0x%x\n",tuner_code); - } - } - break; - - case CARD_AVER_MEDIA: - /* AVerMedia kindly supplied some details of their EEPROM contents - * which allow us to auto select the Tuner Type. - * Only the newer AVerMedia cards actually have an EEPROM. - */ - if (bktr->card.eepromAddr != 0) { - - u_char tuner_make; /* Eg Philips, Temic */ - u_char tuner_tv_fm; /* TV or TV with FM Radio */ - u_char tuner_format; /* Eg NTSC, PAL, SECAM */ - int tuner; - - int tuner_0_table[] = { - PHILIPS_NTSC, PHILIPS_PAL, - PHILIPS_PAL, PHILIPS_PAL, - PHILIPS_PAL, PHILIPS_PAL, - PHILIPS_SECAM, PHILIPS_SECAM, - PHILIPS_SECAM, PHILIPS_PAL}; - - int tuner_0_fm_table[] = { - PHILIPS_FR1236_NTSC, PHILIPS_FR1216_PAL, - PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL, - PHILIPS_FR1216_PAL, PHILIPS_FR1216_PAL, - PHILIPS_FR1236_SECAM, PHILIPS_FR1236_SECAM, - PHILIPS_FR1236_SECAM, PHILIPS_FR1216_PAL}; - - int tuner_1_table[] = { - TEMIC_NTSC, TEMIC_PAL, TEMIC_PAL, - TEMIC_PAL, TEMIC_PAL, TEMIC_PAL, - TEMIC_SECAM, TEMIC_SECAM, TEMIC_SECAM, - TEMIC_PAL}; - - - /* Extract information from the EEPROM data */ - readEEProm(bktr, 0, 128, (u_char *) &eeprom ); - tuner_make = (eeprom[0x41] & 0x7); - tuner_tv_fm = (eeprom[0x41] & 0x18) >> 3; - tuner_format = (eeprom[0x42] & 0xf0) >> 4; - - /* Treat tuner makes 0 (Philips) and 2 (LG) the same */ - if ( ((tuner_make == 0) || (tuner_make == 2)) - && (tuner_format <= 9) && (tuner_tv_fm == 0) ) { - tuner = tuner_0_table[tuner_format]; - bktr->card.tuner = &tuners[ tuner ]; - goto checkDBX; - } - - if ( ((tuner_make == 0) || (tuner_make == 2)) - && (tuner_format <= 9) && (tuner_tv_fm == 1) ) { - tuner = tuner_0_fm_table[tuner_format]; - bktr->card.tuner = &tuners[ tuner ]; - goto checkDBX; - } - - if ( (tuner_make == 1) && (tuner_format <= 9) ) { - tuner = tuner_1_table[tuner_format]; - bktr->card.tuner = &tuners[ tuner ]; - goto checkDBX; - } - - printf("Warning - Unknown AVerMedia Tuner Make %d Format %d\n", - tuner_make, tuner_format); - } - break; - - } /* end switch(card) */ - - /* At this point, a goto checkDBX has not occured */ - /* We have not been able to select a Tuner */ - /* Some cards make use of the tuner address to */ - /* identify the make/model of tuner */ - - /* At address 0xc0/0xc1 we often find a TEMIC NTSC */ - if ( i2cRead( bktr, 0xc1 ) != ABSENT ) { - bktr->card.tuner = &tuners[ TEMIC_NTSC ]; - goto checkDBX; - } - - /* At address 0xc6/0xc7 we often find a PHILIPS NTSC Tuner */ - if ( i2cRead( bktr, 0xc7 ) != ABSENT ) { - bktr->card.tuner = &tuners[ PHILIPS_NTSC ]; - goto checkDBX; - } - - /* Address 0xc2/0xc3 is default (or common address) for several */ - /* tuners and we cannot tell which is which. */ - /* And for all other tuner i2c addresses, select the default */ - bktr->card.tuner = &tuners[ DEFAULT_TUNER ]; - - -checkDBX: -#if defined( OVERRIDE_DBX ) - bktr->card.dbx = OVERRIDE_DBX; - goto checkMSP; -#endif - /* Check for i2c devices */ - if (!any_i2c_devices) { - goto checkMSP; - } - - /* probe for BTSC (dbx) chip */ - if ( i2cRead( bktr, TDA9850_RADDR ) != ABSENT ) - bktr->card.dbx = 1; - -checkMSP: - /* If this is a Hauppauge Bt878 card, we need to enable the - * MSP 34xx audio chip. - * If this is a Hauppauge Bt848 card, reset the MSP device. - * The MSP reset line is wired to GPIO pin 5. On Bt878 cards a pulldown - * resistor holds the device in reset until we set GPIO pin 5. - */ - - /* Optionally skip the MSP reset. This is handy if you initialise the - * MSP audio in another operating system (eg Windows) first and then - * do a soft reboot. - */ - -#ifndef BKTR_NO_MSP_RESET - if (card == CARD_HAUPPAUGE) { - bt848->gpio_out_en = bt848->gpio_out_en | (1<<5); - bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ - DELAY(2500); /* wait 2.5ms */ - bt848->gpio_data = bt848->gpio_data & ~(1<<5); /* write '0' */ - DELAY(2500); /* wait 2.5ms */ - bt848->gpio_data = bt848->gpio_data | (1<<5); /* write '1' */ - DELAY(2500); /* wait 2.5ms */ - } -#endif - -#if defined( OVERRIDE_MSP ) - bktr->card.msp3400c = OVERRIDE_MSP; - goto checkMSPEnd; -#endif - - /* Check for i2c devices */ - if (!any_i2c_devices) { - goto checkMSPEnd; - } - - if ( i2cRead( bktr, MSP3400C_RADDR ) != ABSENT ) - bktr->card.msp3400c = 1; - -checkMSPEnd: - -/* Start of Check Remote */ - /* Check for the Hauppauge IR Remote Control */ - /* If there is an external unit, the internal will be ignored */ - - bktr->remote_control = 0; /* initial value */ - - if (any_i2c_devices) { - if (i2cRead( bktr, HAUP_REMOTE_EXT_RADDR ) != ABSENT ) - { - bktr->remote_control = 1; - bktr->remote_control_addr = HAUP_REMOTE_EXT_RADDR; - } - else if (i2cRead( bktr, HAUP_REMOTE_INT_RADDR ) != ABSENT ) - { - bktr->remote_control = 1; - bktr->remote_control_addr = HAUP_REMOTE_INT_RADDR; - } - - } - /* If a remote control is found, poll it 5 times to turn off the LED */ - if (bktr->remote_control) { - int i; - for (i=0; i<5; i++) - i2cRead( bktr, bktr->remote_control_addr ); - } -/* End of Check Remote */ - -#if defined( BKTR_USE_PLL ) - bktr->xtal_pll_mode = BT848_USE_PLL; - goto checkPLLEnd; -#endif - /* Default is to use XTALS and not PLL mode */ - bktr->xtal_pll_mode = BT848_USE_XTALS; - - /* Enable PLL mode for PAL/SECAM users on Hauppauge 878 cards */ - if ((card == CARD_HAUPPAUGE) && - (bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) ) - bktr->xtal_pll_mode = BT848_USE_PLL; - - - /* Enable PLL mode for OSPREY users */ - if (card == CARD_OSPREY) - bktr->xtal_pll_mode = BT848_USE_PLL; - - /* Enable PLL mode for PAL/SECAM users on FlyVideo 878 cards */ - if ((card == CARD_FLYVIDEO) && - (bktr->id==BROOKTREE_878 || bktr->id==BROOKTREE_879) ) - bktr->xtal_pll_mode = BT848_USE_PLL; - - /* Enable PLL mode for Video Highway Xtreme users */ - if (card == CARD_VIDEO_HIGHWAY_XTREME) - bktr->xtal_pll_mode = BT848_USE_PLL; - -#if defined( BKTR_USE_PLL ) -checkPLLEnd: -#endif - - - bktr->card.tuner_pllAddr = tuner_i2c_address; - - if ( verbose ) { - printf( "%s", bktr->card.name ); - if ( bktr->card.tuner ) - printf( ", %s tuner", bktr->card.tuner->name ); - if ( bktr->card.dbx ) - printf( ", dbx stereo" ); - if ( bktr->card.msp3400c ) - printf( ", msp3400c stereo" ); - if ( bktr->remote_control ) - printf( ", remote control" ); - printf( ".\n" ); - } -} -#undef ABSENT - - -/****************************************************************************** - * tuner specific routines: - */ - - -/* scaling factor for frequencies expressed as ints */ -#define FREQFACTOR 16 - -/* - * Format: - * entry 0: MAX legal channel - * entry 1: IF frequency - * expressed as fi{mHz} * 16, - * eg 45.75mHz == 45.75 * 16 = 732 - * entry 2: [place holder/future] - * entry 3: base of channel record 0 - * entry 3 + (x*3): base of channel record 'x' - * entry LAST: NULL channel entry marking end of records - * - * Record: - * int 0: base channel - * int 1: frequency of base channel, - * expressed as fb{mHz} * 16, - * int 2: offset frequency between channels, - * expressed as fo{mHz} * 16, - */ - -/* - * North American Broadcast Channels: - * - * 2: 55.25 mHz - 4: 67.25 mHz - * 5: 77.25 mHz - 6: 83.25 mHz - * 7: 175.25 mHz - 13: 211.25 mHz - * 14: 471.25 mHz - 83: 885.25 mHz - * - * IF freq: 45.75 mHz - */ -#define OFFSET 6.00 -static int nabcst[] = { - 83, (int)( 45.75 * FREQFACTOR), 0, - 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 0 -}; -#undef OFFSET - -/* - * North American Cable Channels, IRC: - * - * 2: 55.25 mHz - 4: 67.25 mHz - * 5: 77.25 mHz - 6: 83.25 mHz - * 7: 175.25 mHz - 13: 211.25 mHz - * 14: 121.25 mHz - 22: 169.25 mHz - * 23: 217.25 mHz - 94: 643.25 mHz - * 95: 91.25 mHz - 99: 115.25 mHz - * - * IF freq: 45.75 mHz - */ -#define OFFSET 6.00 -static int irccable[] = { - 99, (int)( 45.75 * FREQFACTOR), 0, - 95, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 23, (int)(217.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 14, (int)(121.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 0 -}; -#undef OFFSET - -/* - * North American Cable Channels, HRC: - * - * 2: 54 mHz - 4: 66 mHz - * 5: 78 mHz - 6: 84 mHz - * 7: 174 mHz - 13: 210 mHz - * 14: 120 mHz - 22: 168 mHz - * 23: 216 mHz - 94: 642 mHz - * 95: 90 mHz - 99: 114 mHz - * - * IF freq: 45.75 mHz - */ -#define OFFSET 6.00 -static int hrccable[] = { - 99, (int)( 45.75 * FREQFACTOR), 0, - 95, (int)( 90.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 23, (int)(216.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 14, (int)(120.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 5, (int)( 78.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 2, (int)( 54.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 0 -}; -#undef OFFSET - -/* - * Western European broadcast channels: - * - * (there are others that appear to vary between countries - rmt) - * - * here's the table Philips provides: - * caution, some of the offsets don't compute... - * - * 1 4525 700 N21 - * - * 2 4825 700 E2 - * 3 5525 700 E3 - * 4 6225 700 E4 - * - * 5 17525 700 E5 - * 6 18225 700 E6 - * 7 18925 700 E7 - * 8 19625 700 E8 - * 9 20325 700 E9 - * 10 21025 700 E10 - * 11 21725 700 E11 - * 12 22425 700 E12 - * - * 13 5375 700 ITA - * 14 6225 700 ITB - * - * 15 8225 700 ITC - * - * 16 17525 700 ITD - * 17 18325 700 ITE - * - * 18 19225 700 ITF - * 19 20125 700 ITG - * 20 21025 700 ITH - * - * 21 47125 800 E21 - * 22 47925 800 E22 - * 23 48725 800 E23 - * 24 49525 800 E24 - * 25 50325 800 E25 - * 26 51125 800 E26 - * 27 51925 800 E27 - * 28 52725 800 E28 - * 29 53525 800 E29 - * 30 54325 800 E30 - * 31 55125 800 E31 - * 32 55925 800 E32 - * 33 56725 800 E33 - * 34 57525 800 E34 - * 35 58325 800 E35 - * 36 59125 800 E36 - * 37 59925 800 E37 - * 38 60725 800 E38 - * 39 61525 800 E39 - * 40 62325 800 E40 - * 41 63125 800 E41 - * 42 63925 800 E42 - * 43 64725 800 E43 - * 44 65525 800 E44 - * 45 66325 800 E45 - * 46 67125 800 E46 - * 47 67925 800 E47 - * 48 68725 800 E48 - * 49 69525 800 E49 - * 50 70325 800 E50 - * 51 71125 800 E51 - * 52 71925 800 E52 - * 53 72725 800 E53 - * 54 73525 800 E54 - * 55 74325 800 E55 - * 56 75125 800 E56 - * 57 75925 800 E57 - * 58 76725 800 E58 - * 59 77525 800 E59 - * 60 78325 800 E60 - * 61 79125 800 E61 - * 62 79925 800 E62 - * 63 80725 800 E63 - * 64 81525 800 E64 - * 65 82325 800 E65 - * 66 83125 800 E66 - * 67 83925 800 E67 - * 68 84725 800 E68 - * 69 85525 800 E69 - * - * 70 4575 800 IA - * 71 5375 800 IB - * 72 6175 800 IC - * - * 74 6925 700 S01 - * 75 7625 700 S02 - * 76 8325 700 S03 - * - * 80 10525 700 S1 - * 81 11225 700 S2 - * 82 11925 700 S3 - * 83 12625 700 S4 - * 84 13325 700 S5 - * 85 14025 700 S6 - * 86 14725 700 S7 - * 87 15425 700 S8 - * 88 16125 700 S9 - * 89 16825 700 S10 - * 90 23125 700 S11 - * 91 23825 700 S12 - * 92 24525 700 S13 - * 93 25225 700 S14 - * 94 25925 700 S15 - * 95 26625 700 S16 - * 96 27325 700 S17 - * 97 28025 700 S18 - * 98 28725 700 S19 - * 99 29425 700 S20 - * - * - * Channels S21 - S41 are taken from - * http://gemma.apple.com:80/dev/technotes/tn/tn1012.html - * - * 100 30325 800 S21 - * 101 31125 800 S22 - * 102 31925 800 S23 - * 103 32725 800 S24 - * 104 33525 800 S25 - * 105 34325 800 S26 - * 106 35125 800 S27 - * 107 35925 800 S28 - * 108 36725 800 S29 - * 109 37525 800 S30 - * 110 38325 800 S31 - * 111 39125 800 S32 - * 112 39925 800 S33 - * 113 40725 800 S34 - * 114 41525 800 S35 - * 115 42325 800 S36 - * 116 43125 800 S37 - * 117 43925 800 S38 - * 118 44725 800 S39 - * 119 45525 800 S40 - * 120 46325 800 S41 - * - * 121 3890 000 IFFREQ - * - */ -static int weurope[] = { - 121, (int)( 38.90 * FREQFACTOR), 0, - 100, (int)(303.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 90, (int)(231.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), - 80, (int)(105.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), - 74, (int)( 69.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), - 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 17, (int)(183.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), - 16, (int)(175.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), - 15, (int)(82.25 * FREQFACTOR), (int)(8.50 * FREQFACTOR), - 13, (int)(53.75 * FREQFACTOR), (int)(8.50 * FREQFACTOR), - 5, (int)(175.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), - 2, (int)(48.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), - 0 -}; - -/* - * Japanese Broadcast Channels: - * - * 1: 91.25MHz - 3: 103.25MHz - * 4: 171.25MHz - 7: 189.25MHz - * 8: 193.25MHz - 12: 217.25MHz (VHF) - * 13: 471.25MHz - 62: 765.25MHz (UHF) - * - * IF freq: 45.75 mHz - * OR - * IF freq: 58.75 mHz - */ -#define OFFSET 6.00 -#define IF_FREQ 45.75 -static int jpnbcst[] = { - 62, (int)(IF_FREQ * FREQFACTOR), 0, - 13, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 0 -}; -#undef IF_FREQ -#undef OFFSET - -/* - * Japanese Cable Channels: - * - * 1: 91.25MHz - 3: 103.25MHz - * 4: 171.25MHz - 7: 189.25MHz - * 8: 193.25MHz - 12: 217.25MHz - * 13: 109.25MHz - 21: 157.25MHz - * 22: 165.25MHz - * 23: 223.25MHz - 63: 463.25MHz - * - * IF freq: 45.75 mHz - */ -#define OFFSET 6.00 -#define IF_FREQ 45.75 -static int jpncable[] = { - 63, (int)(IF_FREQ * FREQFACTOR), 0, - 23, (int)(223.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 22, (int)(165.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 13, (int)(109.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 0 -}; -#undef IF_FREQ -#undef OFFSET - -/* - * xUSSR Broadcast Channels: - * - * 1: 49.75MHz - 2: 59.25MHz - * 3: 77.25MHz - 5: 93.25MHz - * 6: 175.25MHz - 12: 223.25MHz - * 13-20 - not exist - * 21: 471.25MHz - 34: 575.25MHz - * 35: 583.25MHz - 69: 855.25MHz - * - * Cable channels - * - * 70: 111.25MHz - 77: 167.25MHz - * 78: 231.25MHz -107: 463.25MHz - * - * IF freq: 38.90 MHz - */ -#define IF_FREQ 38.90 -static int xussr[] = { - 107, (int)(IF_FREQ * FREQFACTOR), 0, - 78, (int)(231.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 70, (int)(111.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 35, (int)(583.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 6, (int)(175.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 3, (int)( 77.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), - 1, (int)( 49.75 * FREQFACTOR), (int)(9.50 * FREQFACTOR), - 0 -}; -#undef IF_FREQ - -/* - * Australian broadcast channels - */ -#define OFFSET 7.00 -static int australia[] = { - 83, (int)( 45.00 * FREQFACTOR), 0, - 28, (int)(520.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 11, (int)(214.50 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 10, (int)(201.50 * FREQFACTOR), (int)( 13.00 * FREQFACTOR), - 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 3, (int)( 85.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 2, (int)( 56.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), - 0 -}; -#undef OFFSET - -static struct { - int *ptr; - char name[BT848_MAX_CHNLSET_NAME_LEN]; -} freqTable[] = { - {NULL, ""}, - {nabcst, "nabcst"}, - {irccable, "cableirc"}, - {hrccable, "cablehrc"}, - {weurope, "weurope"}, - {jpnbcst, "jpnbcst"}, - {jpncable, "jpncable"}, - {xussr, "xussr"}, - {australia, "australia"}, - -}; - -#define TBL_CHNL freqTable[ bktr->tuner.chnlset ].ptr[ x ] -#define TBL_BASE_FREQ freqTable[ bktr->tuner.chnlset ].ptr[ x + 1 ] -#define TBL_OFFSET freqTable[ bktr->tuner.chnlset ].ptr[ x + 2 ] -static int -frequency_lookup( bktr_ptr_t bktr, int channel ) -{ - int x; - - /* check for "> MAX channel" */ - x = 0; - if ( channel > TBL_CHNL ) - return( -1 ); - - /* search the table for data */ - for ( x = 3; TBL_CHNL; x += 3 ) { - if ( channel >= TBL_CHNL ) { - return( TBL_BASE_FREQ + - ((channel - TBL_CHNL) * TBL_OFFSET) ); - } - } - - /* not found, must be below the MIN channel */ - return( -1 ); -} -#undef TBL_OFFSET -#undef TBL_BASE_FREQ -#undef TBL_CHNL - - -#define TBL_IF freqTable[ bktr->tuner.chnlset ].ptr[ 1 ] -/* - * set the frequency of the tuner - */ -static int -tv_freq( bktr_ptr_t bktr, int frequency ) -{ - const struct TUNER* tuner; - u_char addr; - u_char control; - u_char band; - int N; - - tuner = bktr->card.tuner; - if ( tuner == NULL ) - return( -1 ); - - /* - * select the band based on frequency - * XXX FIXME: get the cross-over points from the tuner struct - */ - if ( frequency < (160 * FREQFACTOR) ) - N = 0; - else if ( frequency < (454 * FREQFACTOR) ) - N = 1; - else - N = 2; - - if(frequency > RADIO_OFFSET) { - N=3; - frequency -= RADIO_OFFSET; - } - - /* set the address of the PLL */ - addr = bktr->card.tuner_pllAddr; - control = tuner->pllControl[ N ]; - band = tuner->bandAddrs[ N ]; - if(!(band && control)) /* Don't try to set un- */ - return(-1); /* supported modes. */ - - if(N==3) - band |= bktr->tuner.radio_mode; - - /* - * N = 16 * { fRF(pc) + fIF(pc) } - * where: - * pc is picture carrier, fRF & fIF are in mHz - * - * frequency was passed in as mHz * 16 - */ -#if defined( TEST_TUNER_AFC ) - if ( bktr->tuner.afc ) - frequency -= 4; -#endif - - if(bktr->bt848_tuner == ALPS_TSCH5 && N == 3) /* for FM frequency */ - N = frequency; - else - N = frequency + TBL_IF; - - if ( frequency > bktr->tuner.frequency ) { - i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); - i2cWrite( bktr, addr, control, band ); - } - else { - i2cWrite( bktr, addr, control, band ); - i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); - } - -#if defined( TUNER_AFC ) - if ( bktr->tuner.afc == TRUE ) { - if ( (N = do_afc( bktr, addr, N )) < 0 ) { - /* AFC failed, restore requested frequency */ - N = frequency + TBL_IF; - i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); - } - else - frequency = N - TBL_IF; - } -#endif /* TUNER_AFC */ - - /* update frequency */ - bktr->tuner.frequency = frequency; - - return( 0 ); -} - -#if defined( TUNER_AFC ) -/* - * - */ -static int -do_afc( bktr_ptr_t bktr, int addr, int frequency ) -{ - int step; - int status; - int origFrequency; - - origFrequency = frequency; - - /* wait for first setting to take effect */ - tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 ); - - if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) - return( -1 ); - -#if defined( TEST_TUNER_AFC ) - printf( "\nOriginal freq: %d, status: 0x%02x\n", frequency, status ); -#endif - for ( step = 0; step < AFC_MAX_STEP; ++step ) { - if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) - goto fubar; - if ( !(status & 0x40) ) { -#if defined( TEST_TUNER_AFC ) - printf( "no lock!\n" ); -#endif - goto fubar; - } - - switch( status & AFC_BITS ) { - case AFC_FREQ_CENTERED: -#if defined( TEST_TUNER_AFC ) - printf( "Centered, freq: %d, status: 0x%02x\n", frequency, status ); -#endif - return( frequency ); - - case AFC_FREQ_MINUS_125: - case AFC_FREQ_MINUS_62: -#if defined( TEST_TUNER_AFC ) - printf( "Low, freq: %d, status: 0x%02x\n", frequency, status ); -#endif - --frequency; - break; - - case AFC_FREQ_PLUS_62: - case AFC_FREQ_PLUS_125: -#if defined( TEST_TUNER_AFC ) - printf( "Hi, freq: %d, status: 0x%02x\n", frequency, status ); -#endif - ++frequency; - break; - } - - i2cWrite( bktr, addr, - (frequency>>8) & 0x7f, frequency & 0xff ); - DELAY( AFC_DELAY ); - } - - fubar: - i2cWrite( bktr, addr, - (origFrequency>>8) & 0x7f, origFrequency & 0xff ); - - return( -1 ); -} -#endif /* TUNER_AFC */ -#undef TBL_IF - - -/* - * set the channel of the tuner - */ -static int -tv_channel( bktr_ptr_t bktr, int channel ) -{ - int frequency; - - /* calculate the frequency according to tuner type */ - if ( (frequency = frequency_lookup( bktr, channel )) < 0 ) - return( -1 ); - - /* set the new frequency */ - if ( tv_freq( bktr, frequency ) < 0 ) - return( -1 ); - - /* OK to update records */ - return( (bktr->tuner.channel = channel) ); -} - -/* - * get channelset name - */ -static int -tuner_getchnlset(struct bktr_chnlset *chnlset) -{ - if (( chnlset->index < CHNLSET_MIN ) || - ( chnlset->index > CHNLSET_MAX )) - return( EINVAL ); - - memcpy(&chnlset->name, &freqTable[chnlset->index].name, - BT848_MAX_CHNLSET_NAME_LEN); - - chnlset->max_channel=freqTable[chnlset->index].ptr[0]; - return( 0 ); -} -/****************************************************************************** - * audio specific routines: - */ - - -/* - * - */ -#define AUDIOMUX_DISCOVER_NOT -static int -set_audio( bktr_ptr_t bktr, int cmd ) -{ - bt848_ptr_t bt848; - u_long temp; - volatile u_char idx; - -#if defined( AUDIOMUX_DISCOVER ) - if ( cmd >= 200 ) - cmd -= 200; - else -#endif /* AUDIOMUX_DISCOVER */ - - /* check for existance of audio MUXes */ - if ( !bktr->card.audiomuxs[ 4 ] ) - return( -1 ); - - switch (cmd) { - case AUDIO_TUNER: -#ifdef BKTR_REVERSEMUTE - bktr->audio_mux_select = 3; -#else - bktr->audio_mux_select = 0; -#endif - - if (bktr->reverse_mute ) - bktr->audio_mux_select = 0; - else - bktr->audio_mux_select = 3; - - break; - case AUDIO_EXTERN: - bktr->audio_mux_select = 1; - break; - case AUDIO_INTERN: - bktr->audio_mux_select = 2; - break; - case AUDIO_MUTE: - bktr->audio_mute_state = TRUE; /* set mute */ - break; - case AUDIO_UNMUTE: - bktr->audio_mute_state = FALSE; /* clear mute */ - break; - default: - printf("bktr: audio cmd error %02x\n", cmd); - return( -1 ); - } - - - /* Most cards have a simple audio multiplexer to select the - * audio source. The I/O_GV card has a more advanced multiplexer - * and requires special handling. - */ - if ( bktr->bt848_card == CARD_IO_GV ) { - set_bctv_audio( bktr ); - return( 0 ); - } - - /* Proceed with the simpler audio multiplexer code for the majority - * of Bt848 cards. - */ - - bt848 = bktr->base; - - /* - * Leave the upper bits of the GPIO port alone in case they control - * something like the dbx or teletext chips. This doesn't guarantee - * success, but follows the rule of least astonishment. - */ - - if ( bktr->audio_mute_state == TRUE ) { -#ifdef BKTR_REVERSEMUTE - idx = 0; -#else - idx = 3; -#endif - - if (bktr->reverse_mute ) - idx = 3; - else - idx = 0; - - } - else - idx = bktr->audio_mux_select; - - temp = bt848->gpio_data & ~bktr->card.gpio_mux_bits; - bt848->gpio_data = -#if defined( AUDIOMUX_DISCOVER ) - bt848->gpio_data = temp | (cmd & 0xff); - printf("cmd: %d audio mux %x temp %x \n", cmd,bktr->card.audiomuxs[ idx ], temp ); -#else - temp | bktr->card.audiomuxs[ idx ]; -#endif /* AUDIOMUX_DISCOVER */ - - return( 0 ); -} - - -/* - * - */ -static void -temp_mute( bktr_ptr_t bktr, int flag ) -{ - static int muteState = FALSE; - - if ( flag == TRUE ) { - muteState = bktr->audio_mute_state; - set_audio( bktr, AUDIO_MUTE ); /* prevent 'click' */ - } - else { - tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 ); - if ( muteState == FALSE ) - set_audio( bktr, AUDIO_UNMUTE ); - } -} - - -/* - * initialise the dbx chip - * taken from the Linux bttv driver TDA9850 initialisation code - */ -static void -init_BTSC( bktr_ptr_t bktr ) -{ - i2cWrite(bktr, TDA9850_WADDR, CON1ADDR, 0x08); /* noise threshold st */ - i2cWrite(bktr, TDA9850_WADDR, CON2ADDR, 0x08); /* noise threshold sap */ - i2cWrite(bktr, TDA9850_WADDR, CON3ADDR, 0x40); /* stereo mode */ - i2cWrite(bktr, TDA9850_WADDR, CON4ADDR, 0x07); /* 0 dB input gain? */ - i2cWrite(bktr, TDA9850_WADDR, ALI1ADDR, 0x10); /* wideband alignment? */ - i2cWrite(bktr, TDA9850_WADDR, ALI2ADDR, 0x10); /* spectral alignment? */ - i2cWrite(bktr, TDA9850_WADDR, ALI3ADDR, 0x03); -} - -/* - * setup the dbx chip - * XXX FIXME: alot of work to be done here, this merely unmutes it. - */ -static int -set_BTSC( bktr_ptr_t bktr, int control ) -{ - return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) ); -} - -/* - * CARD_GV_BCTV specific functions. - */ - -#define BCTV_AUDIO_MAIN 0x10 /* main audio program */ -#define BCTV_AUDIO_SUB 0x20 /* sub audio program */ -#define BCTV_AUDIO_BOTH 0x30 /* main(L) + sub(R) program */ - -#define BCTV_GPIO_REG0 1 -#define BCTV_GPIO_REG1 3 - -#define BCTV_GR0_AUDIO_MODE 3 -#define BCTV_GR0_AUDIO_MAIN 0 /* main program */ -#define BCTV_GR0_AUDIO_SUB 3 /* sub program */ -#define BCTV_GR0_AUDIO_BOTH 1 /* main(L) + sub(R) */ -#define BCTV_GR0_AUDIO_MUTE 4 /* audio mute */ -#define BCTV_GR0_AUDIO_MONO 8 /* force mono */ - -static void -set_bctv_audio( bktr_ptr_t bktr ) -{ - int data; - - switch (bktr->audio_mux_select) { - case 1: /* external */ - case 2: /* internal */ - bctv_gpio_write(bktr, BCTV_GPIO_REG1, 0); - break; - default: /* tuner */ - bctv_gpio_write(bktr, BCTV_GPIO_REG1, 1); - break; - } -/* switch (bktr->audio_sap_select) { */ - switch (BCTV_AUDIO_BOTH) { - case BCTV_AUDIO_SUB: - data = BCTV_GR0_AUDIO_SUB; - break; - case BCTV_AUDIO_BOTH: - data = BCTV_GR0_AUDIO_BOTH; - break; - case BCTV_AUDIO_MAIN: - default: - data = BCTV_GR0_AUDIO_MAIN; - break; - } - if (bktr->audio_mute_state == TRUE) - data |= BCTV_GR0_AUDIO_MUTE; - - bctv_gpio_write(bktr, BCTV_GPIO_REG0, data); - - return; -} - -/* gpio_data bit assignment */ -#define BCTV_GPIO_ADDR_MASK 0x000300 -#define BCTV_GPIO_WE 0x000400 -#define BCTV_GPIO_OE 0x000800 -#define BCTV_GPIO_VAL_MASK 0x00f000 - -#define BCTV_GPIO_PORT_MASK 3 -#define BCTV_GPIO_ADDR_SHIFT 8 -#define BCTV_GPIO_VAL_SHIFT 12 - -/* gpio_out_en value for read/write */ -#define BCTV_GPIO_OUT_RMASK 0x000f00 -#define BCTV_GPIO_OUT_WMASK 0x00ff00 - -#define BCTV_BITS 100 - -static void -bctv_gpio_write( bktr_ptr_t bktr, int port, int val ) -{ - bt848_ptr_t bt848 = bktr->base; - u_long data, outbits; - - port &= BCTV_GPIO_PORT_MASK; - switch (port) { - case 1: - case 3: - data = ((val << BCTV_GPIO_VAL_SHIFT) & BCTV_GPIO_VAL_MASK) | - ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) | - BCTV_GPIO_WE | BCTV_GPIO_OE; - outbits = BCTV_GPIO_OUT_WMASK; - break; - default: - return; - } - bt848->gpio_out_en = 0; - bt848->gpio_data = data; - bt848->gpio_out_en = outbits; - DELAY(BCTV_BITS); - bt848->gpio_data = data & ~BCTV_GPIO_WE; - DELAY(BCTV_BITS); - bt848->gpio_data = data; - DELAY(BCTV_BITS); - bt848->gpio_data = ~0; - bt848->gpio_out_en = 0; -} - -/* Not yet used -static int -bctv_gpio_read( bktr_ptr_t bktr, int port ) -{ - bt848_ptr_t bt848 = bktr->base; - u_long data, outbits, ret; - - port &= BCTV_GPIO_PORT_MASK; - switch (port) { - case 1: - case 3: - data = ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) | - BCTV_GPIO_WE | BCTV_GPIO_OE; - outbits = BCTV_GPIO_OUT_RMASK; - break; - default: - return( -1 ); - } - bt848->gpio_out_en = 0; - bt848->gpio_data = data; - bt848->gpio_out_en = outbits; - DELAY(BCTV_BITS); - bt848->gpio_data = data & ~BCTV_GPIO_OE; - DELAY(BCTV_BITS); - ret = bt848->gpio_data; - DELAY(BCTV_BITS); - bt848->gpio_data = data; - DELAY(BCTV_BITS); - bt848->gpio_data = ~0; - bt848->gpio_out_en = 0; - return( (ret & BCTV_GPIO_VAL_MASK) >> BCTV_GPIO_VAL_SHIFT ); -} -*/ - -/* - * setup the MSP34xx Stereo Audio Chip - * This uses the Auto Configuration Option on MSP3410D and MSP3415D chips - * and DBX mode selection for MSP3430G chips. - * For MSP3400C support, the full programming sequence is required and is - * not yet supported. - */ - -/* Read the MSP version string */ -static void msp_read_id( bktr_ptr_t bktr, int unit ){ - int rev1=0, rev2=0; - rev1 = msp_read(bktr, 0x12, 0x001e); - rev2 = msp_read(bktr, 0x12, 0x001f); - - sprintf(bktr->msp_version_string, "34%02d%c-%c%d", - (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f); - - printf("bktr%d: Detected a MSP%s\n",unit,bktr->msp_version_string); -} - - -/* Configure the MSP chip to Auto-detect the audio format */ -static void msp_autodetect( bktr_ptr_t bktr ) { - - if (strncmp("3430G", bktr->msp_version_string, 5) == 0){ - - /* For MSP3430G - countries with mono and DBX stereo */ - msp_write(bktr, 0x10, 0x0030,0x2003);/* Enable Auto format detection */ - msp_write(bktr, 0x10, 0x0020,0x0020);/* Standard Select Reg. = BTSC-Stereo*/ - msp_write(bktr, 0x12, 0x000E,0x2403);/* darned if I know */ - msp_write(bktr, 0x12, 0x0008,0x0320);/* Source select = (St or A) */ - /* & Ch. Matrix = St */ - msp_write(bktr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */ - - } else { - - /* For MSP3410 / 3415 - countries with mono, FM stereo and NICAM */ - msp_write(bktr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */ - msp_write(bktr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */ - msp_write(bktr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */ - } - - /* uncomment the following line to enable the MSP34xx 1Khz Tone Generator */ - /* turn your speaker volume down low before trying this */ - /* msp_write(bktr, 0x12, 0x0014, 0x7f40); */ -} - - - -/* - * - * Operating System Dependant Parts - * This section contains OS Dependant code like - * probe and attach and the cdev open/close/read/mmap interface - * - */ - -/****************************/ -/* *** FreeBSD 4.x code *** */ -/****************************/ -#if (__FreeBSD_version >= 400000) - -static int bktr_probe( device_t dev ); -static int bktr_attach( device_t dev ); -static int bktr_detach( device_t dev ); -static int bktr_shutdown( device_t dev ); -static void bktr_intr(void *arg) { common_bktr_intr(arg); } - -static device_method_t bktr_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, bktr_probe), - DEVMETHOD(device_attach, bktr_attach), - DEVMETHOD(device_detach, bktr_detach), - DEVMETHOD(device_shutdown, bktr_shutdown), - - { 0, 0 } -}; - -static driver_t bktr_driver = { - "bktr", - bktr_methods, - sizeof(struct bktr_softc), -}; - -static devclass_t bktr_devclass; - -static d_open_t bktr_open; -static d_close_t bktr_close; -static d_read_t bktr_read; -static d_write_t bktr_write; -static d_ioctl_t bktr_ioctl; -static d_mmap_t bktr_mmap; -static d_poll_t bktr_poll; - -#define CDEV_MAJOR 92 -static struct cdevsw bktr_cdevsw = { - /* open */ bktr_open, - /* close */ bktr_close, - /* read */ bktr_read, - /* write */ bktr_write, - /* ioctl */ bktr_ioctl, - /* poll */ bktr_poll, - /* mmap */ bktr_mmap, - /* strategy */ nostrategy, - /* name */ "bktr", - /* maj */ CDEV_MAJOR, - /* dump */ nodump, - /* psize */ nopsize, - /* flags */ 0, - /* bmaj */ -1 -}; - -DEV_DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, bktr_cdevsw, 0, 0); - - -/* - * the boot time probe routine. - */ -static int -bktr_probe( device_t dev ) -{ - unsigned int type = pci_get_devid(dev); - unsigned int rev = pci_get_revid(dev); - static int once; - - if (!once++) - cdevsw_add(&bktr_cdevsw); - - switch (type) { - case BROOKTREE_848_PCI_ID: - if (rev == 0x12) device_set_desc(dev, "BrookTree 848A"); - else device_set_desc(dev, "BrookTree 848"); - return 0; - case BROOKTREE_849_PCI_ID: - device_set_desc(dev, "BrookTree 849A"); - return 0; - case BROOKTREE_878_PCI_ID: - device_set_desc(dev, "BrookTree 878"); - return 0; - case BROOKTREE_879_PCI_ID: - device_set_desc(dev, "BrookTree 879"); - return 0; - }; - - return ENXIO; -} - - -/* - * the attach routine. - */ -static int -bktr_attach( device_t dev ) -{ - bt848_ptr_t bt848; - u_long latency; - u_long fun; - u_long val; - unsigned int rev; - unsigned int unit; - int error = 0; - int rid; -#ifdef BROOKTREE_IRQ - u_long old_irq, new_irq; -#endif - - struct bktr_softc *bktr = device_get_softc(dev); - - unit = device_get_unit(dev); - - /* - * Enable bus mastering and Memory Mapped device - */ - val = pci_read_config(dev, PCIR_COMMAND, 4); - val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_write_config(dev, PCIR_COMMAND, val, 4); - - /* - * Map control/status registers. - */ - rid = PCI_MAP_REG_START; - bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0, ~0, 1, RF_ACTIVE); - - if (!bktr->res_mem) { - device_printf(dev, "could not map memory\n"); - error = ENXIO; - goto fail; - } - bktr->base = rman_get_virtual(bktr->res_mem); /* XXX use bus_space */ - - /* - * Disable the brooktree device - */ - bt848 = bktr->base; - bt848->int_mask = ALL_INTS_DISABLED; - bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; - - -#ifdef BROOKTREE_IRQ /* from the configuration file */ - old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); - pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); - new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); - printf("bktr%d: attach: irq changed from %d to %d\n", - unit, (old_irq & 0xff), (new_irq & 0xff)); -#endif - - /* - * Allocate our interrupt. - */ - rid = 0; - bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - if (bktr->res_irq == NULL) { - device_printf(dev, "could not map interrupt\n"); - error = ENXIO; - goto fail; - } - - error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_NET, - bktr_intr, bktr, &bktr->res_ih); - if (error) { - device_printf(dev, "could not setup irq\n"); - goto fail; - - } - - - /* Update the Device Control Register */ - /* on Bt878 and Bt879 cards */ - fun = pci_read_config( dev, 0x40, 2); - fun = fun | 1; /* Enable writes to the sub-system vendor ID */ - -#if defined( BKTR_430_FX_MODE ) - if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); - fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ -#endif - -#if defined( BKTR_SIS_VIA_MODE ) - if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); - fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for - OPTi chipset motherboards too */ -#endif - pci_write_config(dev, 0x40, fun, 2); - - - /* XXX call bt848_i2c dependent attach() routine */ -#if (NSMBUS > 0) - if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc)) - printf("bktr%d: i2c_attach: can't attach\n", unit); -#endif - - -/* - * PCI latency timer. 32 is a good value for 4 bus mastering slots, if - * you have more than four, then 16 would probably be a better value. - */ -#ifndef BROOKTREE_DEF_LATENCY_VALUE -#define BROOKTREE_DEF_LATENCY_VALUE 10 -#endif - latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); - latency = (latency >> 8) & 0xff; - if ( bootverbose ) { - if (latency) - printf("brooktree%d: PCI bus latency is", unit); - else - printf("brooktree%d: PCI bus latency was 0 changing to", - unit); - } - if ( !latency ) { - latency = BROOKTREE_DEF_LATENCY_VALUE; - pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); - } - if ( bootverbose ) { - printf(" %d.\n", (int) latency); - } - - /* read the pci device id and revision id */ - fun = pci_get_devid(dev); - rev = pci_get_revid(dev); - - /* call the common attach code */ - common_bktr_attach( bktr, unit, fun, rev ); - - make_dev(&bktr_cdevsw, unit, 0, 0, 0444, "bktr%d", unit); - make_dev(&bktr_cdevsw, unit+16, 0, 0, 0444, "tuner%d", unit); - make_dev(&bktr_cdevsw, unit+32, 0, 0, 0444, "vbi%d", unit); - - return 0; - -fail: - return error; - -} - -/* - * the detach routine. - */ -static int -bktr_detach( device_t dev ) -{ - struct bktr_softc *bktr = device_get_softc(dev); - bt848_ptr_t bt848; - - /* Disable the brooktree device */ - bt848 = bktr->base; - bt848->int_mask = ALL_INTS_DISABLED; - bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; - - /* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */ - - /* - * Deallocate resources. - */ - bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); - bus_release_resource(dev, SYS_RES_IRQ, 0, bktr->res_irq); - bus_release_resource(dev, SYS_RES_MEMORY, PCI_MAP_REG_START, bktr->res_mem); - - return 0; -} - -/* - * the shutdown routine. - */ -static int -bktr_shutdown( device_t dev ) -{ - struct bktr_softc *bktr = device_get_softc(dev); - bt848_ptr_t bt848; - - /* Disable the brooktree device */ - bt848 = bktr->base; - bt848->int_mask = ALL_INTS_DISABLED; - bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; - - return 0; -} - - -/* - * Special Memory Allocation - */ -static vm_offset_t -get_bktr_mem( int unit, unsigned size ) -{ - vm_offset_t addr = 0; - - addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); - if (addr == 0) - addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); - if (addr == 0) { - printf("bktr%d: Unable to allocate %d bytes of memory.\n", - unit, size); - } - - return( addr ); -} - - -/*--------------------------------------------------------- -** -** BrookTree 848 character device driver routines -** -**--------------------------------------------------------- -*/ - -#define VIDEO_DEV 0x00 -#define TUNER_DEV 0x01 -#define VBI_DEV 0x02 - -#define UNIT(x) ((x) & 0x0f) -#define FUNCTION(x) (x >> 4) - -/* - * - */ -int -bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) -{ - bktr_ptr_t bktr; - int unit; - int result; - - unit = UNIT( minor(dev) ); - - /* Get the device data */ - bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); - if (bktr == NULL) { - /* the device is no longer valid/functioning */ - return (ENXIO); - } - - if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ - return( ENXIO ); - - /* Record that the device is now busy */ - device_busy(devclass_get_device(bktr_devclass, unit)); - - - if (bt848_card != -1) { - if ((bt848_card >> 8 == unit ) && - ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { - if ( bktr->bt848_card != (bt848_card & 0xff) ) { - bktr->bt848_card = (bt848_card & 0xff); - probeCard(bktr, FALSE, unit); - } - } - } - - if (bt848_tuner != -1) { - if ((bt848_tuner >> 8 == unit ) && - ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { - if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { - bktr->bt848_tuner = (bt848_tuner & 0xff); - probeCard(bktr, FALSE, unit); - } - } - } - - if (bt848_reverse_mute != -1) { - if (((bt848_reverse_mute >> 8) == unit ) && - ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) { - bktr->reverse_mute = bt848_reverse_mute & 0xff; - bt848_reverse_mute = -1; - } - } - - switch ( FUNCTION( minor(dev) ) ) { - case VIDEO_DEV: - result = video_open( bktr ); - break; - case TUNER_DEV: - result = tuner_open( bktr ); - break; - case VBI_DEV: - result = vbi_open( bktr ); - break; - default: - result = ENXIO; - break; - } - - /* If there was an error opening the device, undo the busy status */ - if (result != 0) - device_unbusy(devclass_get_device(bktr_devclass, unit)); - return( result ); -} - - -/* - * - */ -int -bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) -{ - bktr_ptr_t bktr; - int unit; - int result; - - unit = UNIT( minor(dev) ); - - /* Get the device data */ - bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); - if (bktr == NULL) { - /* the device is no longer valid/functioning */ - return (ENXIO); - } - - switch ( FUNCTION( minor(dev) ) ) { - case VIDEO_DEV: - result = video_close( bktr ); - break; - case TUNER_DEV: - result = tuner_close( bktr ); - break; - case VBI_DEV: - result = vbi_close( bktr ); - break; - default: - return (ENXIO); - break; - } - - device_unbusy(devclass_get_device(bktr_devclass, unit)); - return( result ); -} - - -/* - * - */ -int -bktr_read( dev_t dev, struct uio *uio, int ioflag ) -{ - bktr_ptr_t bktr; - int unit; - - unit = UNIT(minor(dev)); - - /* Get the device data */ - bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); - if (bktr == NULL) { - /* the device is no longer valid/functioning */ - return (ENXIO); - } - - switch ( FUNCTION( minor(dev) ) ) { - case VIDEO_DEV: - return( video_read( bktr, unit, dev, uio ) ); - case VBI_DEV: - return( vbi_read( bktr, uio, ioflag ) ); - } - return( ENXIO ); -} - - -/* - * - */ -int -bktr_write( dev_t dev, struct uio *uio, int ioflag ) -{ - return( EINVAL ); /* XXX or ENXIO ? */ -} - - -/* - * - */ -int -bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) -{ - bktr_ptr_t bktr; - int unit; - - unit = UNIT(minor(dev)); - - /* Get the device data */ - bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); - if (bktr == NULL) { - /* the device is no longer valid/functioning */ - return (ENXIO); - } - - if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ - return( ENOMEM ); - - switch ( FUNCTION( minor(dev) ) ) { - case VIDEO_DEV: - return( video_ioctl( bktr, unit, cmd, arg, pr ) ); - case TUNER_DEV: - return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); - } - - return( ENXIO ); -} - - -/* - * - */ -int -bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) -{ - int unit; - bktr_ptr_t bktr; - - unit = UNIT(minor(dev)); - - if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ - return( -1 ); - - /* Get the device data */ - bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); - if (bktr == NULL) { - /* the device is no longer valid/functioning */ - return (ENXIO); - } - - if (nprot & PROT_EXEC) - return( -1 ); - - if (offset < 0) - return( -1 ); - - if (offset >= bktr->alloc_pages * PAGE_SIZE) - return( -1 ); - - return( i386_btop(vtophys(bktr->bigbuf) + offset) ); -} - -int bktr_poll( dev_t dev, int events, struct proc *p) -{ - int unit; - bktr_ptr_t bktr; - int revents = 0; - - unit = UNIT(minor(dev)); - - /* Get the device data */ - bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); - if (bktr == NULL) { - /* the device is no longer valid/functioning */ - return (ENXIO); - } - - disable_intr(); - - if (events & (POLLIN | POLLRDNORM)) { - - switch ( FUNCTION( minor(dev) ) ) { - case VBI_DEV: - if(bktr->vbisize == 0) - selrecord(p, &bktr->vbi_select); - else - revents |= events & (POLLIN | POLLRDNORM); - break; - } - } - - enable_intr(); - - return (revents); -} - -#endif /* FreeBSD 4.x specific kernel interface routines */ - - -/**********************************/ -/* *** FreeBSD 2.2.x and 3.x *** */ -/**********************************/ - -#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3)) -#endif /* FreeBSD 2.2.x and 3.x specific kernel interface routines */ - - -/*****************/ -/* *** BSDI *** */ -/*****************/ - -#if defined(__bsdi__) -#endif /* __bsdi__ BSDI specific kernel interface routines */ - - -/*****************************/ -/* *** OpenBSD / NetBSD *** */ -/*****************************/ -#if defined(__NetBSD__) || defined(__OpenBSD__) -#endif /* __NetBSD__ || __OpenBSD__ */ - - - #endif /* FreeBSD, BSDI, NetBSD, OpenBSD */ - -/* Local Variables: */ -/* mode: C */ -/* c-indent-level: 8 */ -/* c-brace-offset: -8 */ -/* c-argdecl-indent: 8 */ -/* c-label-offset: -8 */ -/* c-continued-statement-offset: 8 */ -/* c-tab-always-indent: nil */ -/* tab-width: 8 */ -/* End: */ diff --git a/sys/dev/bktr/bktr_core.h b/sys/dev/bktr/bktr_core.h new file mode 100644 index 00000000000..f6870936a0f --- /dev/null +++ b/sys/dev/bktr/bktr_core.h @@ -0,0 +1,93 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_core : This deals with the Bt848/849/878/879 PCI Frame Grabber, + * Handles all the open, close, ioctl and read userland calls. + * Sets the Bt848 registers and generates RISC pograms. + * Controls the i2c bus and GPIO interface. + * Contains the interface to the kernel. + * (eg probe/attach and open/close/ioctl) + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +int i2cWrite( bktr_ptr_t bktr, int addr, int byte1, int byte2 ); +int i2cRead( bktr_ptr_t bktr, int addr ); + +void msp_reset( bktr_ptr_t bktr ); +unsigned int msp_read(bktr_ptr_t bktr, unsigned char dev, unsigned int addr); +void msp_write( bktr_ptr_t bktr, unsigned char dev, + unsigned int addr, unsigned int data); + + +/* + * Defines for userland processes blocked in this driver + * For /dev/bktr[n] use memory address of bktr structure + * For /dev/vbi[n] use memory address of bktr structure + 1 + * this is ok as the bktr structure is > 1 byte + */ +#define BKTR_SLEEP ((caddr_t)bktr ) +#define VBI_SLEEP ((caddr_t)bktr + 1) + + +/* Prototypes for attatch and interrupt functions */ +void common_bktr_attach( bktr_ptr_t bktr, int unit, + u_long pci_id, u_int rev ); +int common_bktr_intr( void *arg ); + + +/* Prototypes for open, close, read, mmap and ioctl calls */ +int video_open( bktr_ptr_t bktr ); +int video_close( bktr_ptr_t bktr ); +int video_read( bktr_ptr_t bktr, int unit, dev_t dev, struct uio *uio ); +int video_ioctl( bktr_ptr_t bktr, int unit, + int cmd, caddr_t arg, struct proc* pr ); + + +int tuner_open( bktr_ptr_t bktr ); +int tuner_close( bktr_ptr_t bktr ); +int tuner_ioctl( bktr_ptr_t bktr, int unit, + int cmd, caddr_t arg, struct proc* pr ); + +int vbi_open( bktr_ptr_t bktr ); +int vbi_close( bktr_ptr_t bktr ); +int vbi_read( bktr_ptr_t bktr, struct uio *uio, int ioflag ); + diff --git a/sys/dev/bktr/bktr_os.c b/sys/dev/bktr/bktr_os.c new file mode 100644 index 00000000000..2384082b61b --- /dev/null +++ b/sys/dev/bktr/bktr_os.c @@ -0,0 +1,1200 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_os : This has all the Operating System dependant code, + * probe/attach and open/close/ioctl/read/mmap + * memory allocation + * PCI bus interfacing + * + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifdef __FreeBSD__ +#include "bktr.h" +#include "opt_bktr.h" +#include "opt_devfs.h" +#endif /* __FreeBSD__ */ + +#if defined(__NetBSD__) || defined(__OpenBSD__) +#include "bktr.h" +#include "pci.h" +#endif /* __NetBSD__ || __OpenBSD__ */ + +#define FIFO_RISC_DISABLED 0 +#define ALL_INTS_DISABLED 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/*******************/ +/* *** FreeBSD *** */ +/*******************/ +#ifdef __FreeBSD__ + +#if (__FreeBSD_version < 400000) +#ifdef DEVFS +#include +#endif /* DEVFS */ +#endif + +#if (__FreeBSD_version >=400000) || (NSMBUS > 0) +#include /* used by smbus and newbus */ +#endif + +#if (__FreeBSD_version >=400000) +#include /* used by newbus */ +#include /* used by newbus */ +#include /* used by newbus */ +#endif + +#include /* for DELAY */ +#include +#include + +#include +#include /* extensions to ioctl_meteor.h */ +#include +#include +#include +#include +#include +#include + +#if (NSMBUS > 0) +#include +#endif + +#include +int bt848_card = -1; +int bt848_tuner = -1; +int bt848_reverse_mute = -1; +int bt848_format = -1; + +SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); +SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); +SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); +SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); +SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); + +#if (__FreeBSD_version >= 300000) + typedef u_long ioctl_cmd_t; +#endif + +#if (__FreeBSD__ == 2) +typedef int ioctl_cmd_t; +#define PCIR_REVID PCI_CLASS_REG +#endif +#endif /* __FreeBSD__ */ + + +/****************/ +/* *** BSDI *** */ +/****************/ +#ifdef __bsdi__ +#endif /* __bsdi__ */ + + +/**************************/ +/* *** OpenBSD/NetBSD *** */ +/**************************/ +#if defined(__NetBSD__) || defined(__OpenBSD__) +#endif /* __NetBSD__ || __OpenBSD__ */ + + + +/****************************/ +/* *** FreeBSD 4.x code *** */ +/****************************/ +#if (__FreeBSD_version >= 400000) + +static int bktr_probe( device_t dev ); +static int bktr_attach( device_t dev ); +static int bktr_detach( device_t dev ); +static int bktr_shutdown( device_t dev ); +static void bktr_intr(void *arg) { common_bktr_intr(arg); } + +static device_method_t bktr_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bktr_probe), + DEVMETHOD(device_attach, bktr_attach), + DEVMETHOD(device_detach, bktr_detach), + DEVMETHOD(device_shutdown, bktr_shutdown), + + { 0, 0 } +}; + +static driver_t bktr_driver = { + "bktr", + bktr_methods, + sizeof(struct bktr_softc), +}; + +static devclass_t bktr_devclass; + +static d_open_t bktr_open; +static d_close_t bktr_close; +static d_read_t bktr_read; +static d_write_t bktr_write; +static d_ioctl_t bktr_ioctl; +static d_mmap_t bktr_mmap; +static d_poll_t bktr_poll; + +#define CDEV_MAJOR 92 +static struct cdevsw bktr_cdevsw = { + /* open */ bktr_open, + /* close */ bktr_close, + /* read */ bktr_read, + /* write */ bktr_write, + /* ioctl */ bktr_ioctl, + /* poll */ bktr_poll, + /* mmap */ bktr_mmap, + /* strategy */ nostrategy, + /* name */ "bktr", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, + /* bmaj */ -1 +}; + +DEV_DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, bktr_cdevsw, 0, 0); + + +/* + * the boot time probe routine. + */ +static int +bktr_probe( device_t dev ) +{ + unsigned int type = pci_get_devid(dev); + unsigned int rev = pci_get_revid(dev); + static int once; + + if (!once++) + cdevsw_add(&bktr_cdevsw); + + switch (type) { + case BROOKTREE_848_PCI_ID: + if (rev == 0x12) device_set_desc(dev, "BrookTree 848A"); + else device_set_desc(dev, "BrookTree 848"); + return 0; + case BROOKTREE_849_PCI_ID: + device_set_desc(dev, "BrookTree 849A"); + return 0; + case BROOKTREE_878_PCI_ID: + device_set_desc(dev, "BrookTree 878"); + return 0; + case BROOKTREE_879_PCI_ID: + device_set_desc(dev, "BrookTree 879"); + return 0; + }; + + return ENXIO; +} + + +/* + * the attach routine. + */ +static int +bktr_attach( device_t dev ) +{ + bt848_ptr_t bt848; + u_long latency; + u_long fun; + u_long val; + unsigned int rev; + unsigned int unit; + int error = 0; + int rid; +#ifdef BROOKTREE_IRQ + u_long old_irq, new_irq; +#endif + + struct bktr_softc *bktr = device_get_softc(dev); + + unit = device_get_unit(dev); + + /* + * Enable bus mastering and Memory Mapped device + */ + val = pci_read_config(dev, PCIR_COMMAND, 4); + val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); + pci_write_config(dev, PCIR_COMMAND, val, 4); + + /* + * Map control/status registers. + */ + rid = PCI_MAP_REG_START; + bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + + if (!bktr->res_mem) { + device_printf(dev, "could not map memory\n"); + error = ENXIO; + goto fail; + } + bktr->base = rman_get_virtual(bktr->res_mem); /* XXX use bus_space */ + + /* + * Disable the brooktree device + */ + bt848 = bktr->base; + bt848->int_mask = ALL_INTS_DISABLED; + bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; + + +#ifdef BROOKTREE_IRQ /* from the configuration file */ + old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); + pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); + new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); + printf("bktr%d: attach: irq changed from %d to %d\n", + unit, (old_irq & 0xff), (new_irq & 0xff)); +#endif + + /* + * Allocate our interrupt. + */ + rid = 0; + bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (bktr->res_irq == NULL) { + device_printf(dev, "could not map interrupt\n"); + error = ENXIO; + goto fail; + } + + error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_NET, + bktr_intr, bktr, &bktr->res_ih); + if (error) { + device_printf(dev, "could not setup irq\n"); + goto fail; + + } + + + /* Update the Device Control Register */ + /* on Bt878 and Bt879 cards */ + fun = pci_read_config( dev, 0x40, 2); + fun = fun | 1; /* Enable writes to the sub-system vendor ID */ + +#if defined( BKTR_430_FX_MODE ) + if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); + fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ +#endif + +#if defined( BKTR_SIS_VIA_MODE ) + if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); + fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for + OPTi chipset motherboards too */ +#endif + pci_write_config(dev, 0x40, fun, 2); + + + /* XXX call bt848_i2c dependent attach() routine */ +#if (NSMBUS > 0) + if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc)) + printf("bktr%d: i2c_attach: can't attach\n", unit); +#endif + + +/* + * PCI latency timer. 32 is a good value for 4 bus mastering slots, if + * you have more than four, then 16 would probably be a better value. + */ +#ifndef BROOKTREE_DEF_LATENCY_VALUE +#define BROOKTREE_DEF_LATENCY_VALUE 10 +#endif + latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); + latency = (latency >> 8) & 0xff; + if ( bootverbose ) { + if (latency) + printf("brooktree%d: PCI bus latency is", unit); + else + printf("brooktree%d: PCI bus latency was 0 changing to", + unit); + } + if ( !latency ) { + latency = BROOKTREE_DEF_LATENCY_VALUE; + pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); + } + if ( bootverbose ) { + printf(" %d.\n", (int) latency); + } + + /* read the pci device id and revision id */ + fun = pci_get_devid(dev); + rev = pci_get_revid(dev); + + /* call the common attach code */ + common_bktr_attach( bktr, unit, fun, rev ); + + make_dev(&bktr_cdevsw, unit, 0, 0, 0444, "bktr%d", unit); + make_dev(&bktr_cdevsw, unit+16, 0, 0, 0444, "tuner%d", unit); + make_dev(&bktr_cdevsw, unit+32, 0, 0, 0444, "vbi%d", unit); + + return 0; + +fail: + return error; + +} + +/* + * the detach routine. + */ +static int +bktr_detach( device_t dev ) +{ + struct bktr_softc *bktr = device_get_softc(dev); + bt848_ptr_t bt848; + + /* Disable the brooktree device */ + bt848 = bktr->base; + bt848->int_mask = ALL_INTS_DISABLED; + bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; + + /* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */ + + /* + * Deallocate resources. + */ + bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, bktr->res_irq); + bus_release_resource(dev, SYS_RES_MEMORY, PCI_MAP_REG_START, bktr->res_mem); + + return 0; +} + +/* + * the shutdown routine. + */ +static int +bktr_shutdown( device_t dev ) +{ + struct bktr_softc *bktr = device_get_softc(dev); + bt848_ptr_t bt848; + + /* Disable the brooktree device */ + bt848 = bktr->base; + bt848->int_mask = ALL_INTS_DISABLED; + bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; + + return 0; +} + + +/* + * Special Memory Allocation + */ +vm_offset_t +get_bktr_mem( int unit, unsigned size ) +{ + vm_offset_t addr = 0; + + addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); + if (addr == 0) + addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); + if (addr == 0) { + printf("bktr%d: Unable to allocate %d bytes of memory.\n", + unit, size); + } + + return( addr ); +} + + +/*--------------------------------------------------------- +** +** BrookTree 848 character device driver routines +** +**--------------------------------------------------------- +*/ + +#define VIDEO_DEV 0x00 +#define TUNER_DEV 0x01 +#define VBI_DEV 0x02 + +#define UNIT(x) ((x) & 0x0f) +#define FUNCTION(x) (x >> 4) + +/* + * + */ +int +bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) +{ + bktr_ptr_t bktr; + int unit; + int result; + + unit = UNIT( minor(dev) ); + + /* Get the device data */ + bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); + if (bktr == NULL) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ + return( ENXIO ); + + /* Record that the device is now busy */ + device_busy(devclass_get_device(bktr_devclass, unit)); + + + if (bt848_card != -1) { + if ((bt848_card >> 8 == unit ) && + ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { + if ( bktr->bt848_card != (bt848_card & 0xff) ) { + bktr->bt848_card = (bt848_card & 0xff); + probeCard(bktr, FALSE, unit); + } + } + } + + if (bt848_tuner != -1) { + if ((bt848_tuner >> 8 == unit ) && + ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { + if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { + bktr->bt848_tuner = (bt848_tuner & 0xff); + probeCard(bktr, FALSE, unit); + } + } + } + + if (bt848_reverse_mute != -1) { + if (((bt848_reverse_mute >> 8) == unit ) && + ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) { + bktr->reverse_mute = bt848_reverse_mute & 0xff; + bt848_reverse_mute = -1; + } + } + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + result = video_open( bktr ); + break; + case TUNER_DEV: + result = tuner_open( bktr ); + break; + case VBI_DEV: + result = vbi_open( bktr ); + break; + default: + result = ENXIO; + break; + } + + /* If there was an error opening the device, undo the busy status */ + if (result != 0) + device_unbusy(devclass_get_device(bktr_devclass, unit)); + return( result ); +} + + +/* + * + */ +int +bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) +{ + bktr_ptr_t bktr; + int unit; + int result; + + unit = UNIT( minor(dev) ); + + /* Get the device data */ + bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); + if (bktr == NULL) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + result = video_close( bktr ); + break; + case TUNER_DEV: + result = tuner_close( bktr ); + break; + case VBI_DEV: + result = vbi_close( bktr ); + break; + default: + return (ENXIO); + break; + } + + device_unbusy(devclass_get_device(bktr_devclass, unit)); + return( result ); +} + + +/* + * + */ +int +bktr_read( dev_t dev, struct uio *uio, int ioflag ) +{ + bktr_ptr_t bktr; + int unit; + + unit = UNIT(minor(dev)); + + /* Get the device data */ + bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); + if (bktr == NULL) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + return( video_read( bktr, unit, dev, uio ) ); + case VBI_DEV: + return( vbi_read( bktr, uio, ioflag ) ); + } + return( ENXIO ); +} + + +/* + * + */ +int +bktr_write( dev_t dev, struct uio *uio, int ioflag ) +{ + return( EINVAL ); /* XXX or ENXIO ? */ +} + + +/* + * + */ +int +bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) +{ + bktr_ptr_t bktr; + int unit; + + unit = UNIT(minor(dev)); + + /* Get the device data */ + bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); + if (bktr == NULL) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ + return( ENOMEM ); + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + return( video_ioctl( bktr, unit, cmd, arg, pr ) ); + case TUNER_DEV: + return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); + } + + return( ENXIO ); +} + + +/* + * + */ +int +bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) +{ + int unit; + bktr_ptr_t bktr; + + unit = UNIT(minor(dev)); + + if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ + return( -1 ); + + /* Get the device data */ + bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); + if (bktr == NULL) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + if (nprot & PROT_EXEC) + return( -1 ); + + if (offset < 0) + return( -1 ); + + if (offset >= bktr->alloc_pages * PAGE_SIZE) + return( -1 ); + + return( i386_btop(vtophys(bktr->bigbuf) + offset) ); +} + +int bktr_poll( dev_t dev, int events, struct proc *p) +{ + int unit; + bktr_ptr_t bktr; + int revents = 0; + + unit = UNIT(minor(dev)); + + /* Get the device data */ + bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); + if (bktr == NULL) { + /* the device is no longer valid/functioning */ + return (ENXIO); + } + + disable_intr(); + + if (events & (POLLIN | POLLRDNORM)) { + + switch ( FUNCTION( minor(dev) ) ) { + case VBI_DEV: + if(bktr->vbisize == 0) + selrecord(p, &bktr->vbi_select); + else + revents |= events & (POLLIN | POLLRDNORM); + break; + } + } + + enable_intr(); + + return (revents); +} + +#endif /* FreeBSD 4.x specific kernel interface routines */ + +/**********************************/ +/* *** FreeBSD 2.2.x and 3.x *** */ +/**********************************/ + +#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3)) + +static bktr_reg_t brooktree[ NBKTR ]; + +static const char* bktr_probe( pcici_t tag, pcidi_t type ); +static void bktr_attach( pcici_t tag, int unit ); +static void bktr_intr(void *arg) { common_bktr_intr(arg); } + +static u_long bktr_count; + +static struct pci_device bktr_device = { + "bktr", + bktr_probe, + bktr_attach, + &bktr_count +}; + +DATA_SET (pcidevice_set, bktr_device); + +static d_open_t bktr_open; +static d_close_t bktr_close; +static d_read_t bktr_read; +static d_write_t bktr_write; +static d_ioctl_t bktr_ioctl; +static d_mmap_t bktr_mmap; +static d_poll_t bktr_poll; + +#define CDEV_MAJOR 92 +static struct cdevsw bktr_cdevsw = +{ + bktr_open, bktr_close, bktr_read, bktr_write, + bktr_ioctl, nostop, nullreset, nodevtotty, + bktr_poll, bktr_mmap, NULL, "bktr", + NULL, -1 +}; + +static int bktr_devsw_installed; + +static void +bktr_drvinit( void *unused ) +{ + dev_t dev; + + if ( ! bktr_devsw_installed ) { + dev = makedev(CDEV_MAJOR, 0); + cdevsw_add(&dev,&bktr_cdevsw, NULL); + bktr_devsw_installed = 1; + } +} + +SYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL) + +/* + * the boot time probe routine. + */ +static const char* +bktr_probe( pcici_t tag, pcidi_t type ) +{ + unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff; + + switch (type) { + case BROOKTREE_848_PCI_ID: + if (rev == 0x12) return("BrookTree 848A"); + else return("BrookTree 848"); + case BROOKTREE_849_PCI_ID: + return("BrookTree 849A"); + case BROOKTREE_878_PCI_ID: + return("BrookTree 878"); + case BROOKTREE_879_PCI_ID: + return("BrookTree 879"); + }; + + return ((char *)0); +} + +/* + * the attach routine. + */ +static void +bktr_attach( pcici_t tag, int unit ) +{ + bktr_ptr_t bktr; + bt848_ptr_t bt848; + u_long latency; + u_long fun; + unsigned int rev; +#ifdef BROOKTREE_IRQ + u_long old_irq, new_irq; +#endif + + bktr = &brooktree[unit]; + + if (unit >= NBKTR) { + printf("brooktree%d: attach: only %d units configured.\n", + unit, NBKTR); + printf("brooktree%d: attach: invalid unit number.\n", unit); + return; + } + + /* Enable Memory Mapping */ + fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); + pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2); + + /* Enable Bus Mastering */ + fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); + pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4); + + bktr->tag = tag; + + + /* + * Map control/status registers + */ + pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &bktr->base, + &bktr->phys_base ); + + /* + * Disable the brooktree device + */ + bt848 = bktr->base; + bt848->int_mask = ALL_INTS_DISABLED; + bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; + +#ifdef BROOKTREE_IRQ /* from the configuration file */ + old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); + pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); + new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); + printf("bktr%d: attach: irq changed from %d to %d\n", + unit, (old_irq & 0xff), (new_irq & 0xff)); +#endif + + /* + * setup the interrupt handling routine + */ + pci_map_int(tag, bktr_intr, (void*) bktr, &net_imask); + + + /* Update the Device Control Register */ + /* on Bt878 and Bt879 cards */ + fun = pci_conf_read(tag, 0x40); + fun = fun | 1; /* Enable writes to the sub-system vendor ID */ + +#if defined( BKTR_430_FX_MODE ) + if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); + fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ +#endif + +#if defined( BKTR_SIS_VIA_MODE ) + if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); + fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for + OPTi chipset motherboards too */ +#endif + pci_conf_write(tag, 0x40, fun); + + + /* XXX call bt848_i2c dependent attach() routine */ +#if (NSMBUS > 0) + if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc)) + printf("bktr%d: i2c_attach: can't attach\n", unit); +#endif + + +/* + * PCI latency timer. 32 is a good value for 4 bus mastering slots, if + * you have more than four, then 16 would probably be a better value. + */ +#ifndef BROOKTREE_DEF_LATENCY_VALUE +#define BROOKTREE_DEF_LATENCY_VALUE 10 +#endif + latency = pci_conf_read(tag, PCI_LATENCY_TIMER); + latency = (latency >> 8) & 0xff; + if ( bootverbose ) { + if (latency) + printf("brooktree%d: PCI bus latency is", unit); + else + printf("brooktree%d: PCI bus latency was 0 changing to", + unit); + } + if ( !latency ) { + latency = BROOKTREE_DEF_LATENCY_VALUE; + pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); + } + if ( bootverbose ) { + printf(" %d.\n", (int) latency); + } + + + /* read the pci device id and revision id */ + fun = pci_conf_read(tag, PCI_ID_REG); + rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff; + + /* call the common attach code */ + common_bktr_attach( bktr, unit, fun, rev ); + +#ifdef DEVFS + /* XXX This just throw away the token, which should probably be fixed when + DEVFS is finally made really operational. */ + devfs_add_devswf(&bktr_cdevsw, unit, DV_CHR, 0, 0, 0444, "bktr%d", unit); + devfs_add_devswf(&bktr_cdevsw, unit+16, DV_CHR, 0, 0, 0444, "tuner%d", unit); + devfs_add_devswf(&bktr_cdevsw, unit+32, DV_CHR, 0, 0, 0444, "vbi%d", unit); +#endif /* DEVFS */ + +} + + +/* + * Special Memory Allocation + */ +vm_offset_t +get_bktr_mem( int unit, unsigned size ) +{ + vm_offset_t addr = 0; + + addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24); + if (addr == 0) + addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, + PAGE_SIZE); + if (addr == 0) { + printf("bktr%d: Unable to allocate %d bytes of memory.\n", + unit, size); + } + + return( addr ); +} + +/*--------------------------------------------------------- +** +** BrookTree 848 character device driver routines +** +**--------------------------------------------------------- +*/ + + +#define VIDEO_DEV 0x00 +#define TUNER_DEV 0x01 +#define VBI_DEV 0x02 + +#define UNIT(x) ((x) & 0x0f) +#define FUNCTION(x) ((x >> 4) & 0x0f) + + +/* + * + */ +int +bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) +{ + bktr_ptr_t bktr; + int unit; + + unit = UNIT( minor(dev) ); + if (unit >= NBKTR) /* unit out of range */ + return( ENXIO ); + + bktr = &(brooktree[ unit ]); + + if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ + return( ENXIO ); + + + if (bt848_card != -1) { + if ((bt848_card >> 8 == unit ) && + ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { + if ( bktr->bt848_card != (bt848_card & 0xff) ) { + bktr->bt848_card = (bt848_card & 0xff); + probeCard(bktr, FALSE, unit); + } + } + } + + if (bt848_tuner != -1) { + if ((bt848_tuner >> 8 == unit ) && + ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { + if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { + bktr->bt848_tuner = (bt848_tuner & 0xff); + probeCard(bktr, FALSE, unit); + } + } + } + + if (bt848_reverse_mute != -1) { + if (((bt848_reverse_mute >> 8) == unit ) && + ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) { + bktr->reverse_mute = bt848_reverse_mute & 0xff; + bt848_reverse_mute = -1; + } + } + + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + return( video_open( bktr ) ); + case TUNER_DEV: + return( tuner_open( bktr ) ); + case VBI_DEV: + return( vbi_open( bktr ) ); + } + return( ENXIO ); +} + + +/* + * + */ +int +bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) +{ + bktr_ptr_t bktr; + int unit; + + unit = UNIT( minor(dev) ); + if (unit >= NBKTR) /* unit out of range */ + return( ENXIO ); + + bktr = &(brooktree[ unit ]); + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + return( video_close( bktr ) ); + case TUNER_DEV: + return( tuner_close( bktr ) ); + case VBI_DEV: + return( vbi_close( bktr ) ); + } + + return( ENXIO ); +} + +/* + * + */ +int +bktr_read( dev_t dev, struct uio *uio, int ioflag ) +{ + bktr_ptr_t bktr; + int unit; + + unit = UNIT(minor(dev)); + if (unit >= NBKTR) /* unit out of range */ + return( ENXIO ); + + bktr = &(brooktree[unit]); + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + return( video_read( bktr, unit, dev, uio ) ); + case VBI_DEV: + return( vbi_read( bktr, uio, ioflag ) ); + } + return( ENXIO ); +} + + +/* + * + */ +int +bktr_write( dev_t dev, struct uio *uio, int ioflag ) +{ + return( EINVAL ); /* XXX or ENXIO ? */ +} + +/* + * + */ +int +bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) +{ + bktr_ptr_t bktr; + int unit; + + unit = UNIT(minor(dev)); + if (unit >= NBKTR) /* unit out of range */ + return( ENXIO ); + + bktr = &(brooktree[ unit ]); + + if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ + return( ENOMEM ); + + switch ( FUNCTION( minor(dev) ) ) { + case VIDEO_DEV: + return( video_ioctl( bktr, unit, cmd, arg, pr ) ); + case TUNER_DEV: + return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); + } + + return( ENXIO ); +} + +/* + * bktr_mmap. + * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually + * edit the following line and change "vm_offset_t" to "int"" + */ +int bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) + +{ + int unit; + bktr_ptr_t bktr; + + unit = UNIT(minor(dev)); + + if (unit >= NBKTR || FUNCTION(minor(dev)) > 0) + return( -1 ); + + bktr = &(brooktree[ unit ]); + + if (nprot & PROT_EXEC) + return( -1 ); + + if (offset < 0) + return( -1 ); + + if (offset >= bktr->alloc_pages * PAGE_SIZE) + return( -1 ); + + return( i386_btop(vtophys(bktr->bigbuf) + offset) ); +} + +int bktr_poll( dev_t dev, int events, struct proc *p) +{ + int unit; + bktr_ptr_t bktr; + int revents = 0; + + unit = UNIT(minor(dev)); + + if (unit >= NBKTR) + return( -1 ); + + bktr = &(brooktree[ unit ]); + + disable_intr(); + + if (events & (POLLIN | POLLRDNORM)) { + + switch ( FUNCTION( minor(dev) ) ) { + case VBI_DEV: + if(bktr->vbisize == 0) + selrecord(p, &bktr->vbi_select); + else + revents |= events & (POLLIN | POLLRDNORM); + break; + } + } + + enable_intr(); + + return (revents); +} + + +#endif /* FreeBSD 2.2.x and 3.x specific kernel interface routines */ + + +/*****************/ +/* *** BSDI *** */ +/*****************/ + +#if defined(__bsdi__) +#endif /* __bsdi__ BSDI specific kernel interface routines */ + + +/*****************************/ +/* *** OpenBSD / NetBSD *** */ +/*****************************/ +#if defined(__NetBSD__) || defined(__OpenBSD__) +#endif /* __NetBSD__ || __OpenBSD__ */ + diff --git a/sys/dev/bktr/bktr_os.h b/sys/dev/bktr/bktr_os.h new file mode 100644 index 00000000000..50334d096f6 --- /dev/null +++ b/sys/dev/bktr/bktr_os.h @@ -0,0 +1,58 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_os : This has all the Operating System dependant code. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/******************************/ +/* *** Memory Allocation *** */ +/******************************/ +#if (defined(__FreeBSD__) || defined(__bsdi__)) +vm_offset_t get_bktr_mem( int unit, unsigned size ); +#endif + +#if (defined(__NetBSD__) || defined(__OpenBSD__)) +vm_offset_t get_bktr_mem(bktr_ptr_t, bus_dmamap_t *, unsigned size); +void free_bktr_mem(bktr_ptr_t, bus_dmamap_t, vm_offset_t); +#endif + diff --git a/sys/dev/bktr/bktr_reg.h b/sys/dev/bktr/bktr_reg.h index 9bffd97b26a..0299221869e 100644 --- a/sys/dev/bktr/bktr_reg.h +++ b/sys/dev/bktr/bktr_reg.h @@ -1,4 +1,6 @@ /* + * $FreeBSD$ + * * Copyright (c) 1999 Roger Hardiman * Copyright (c) 1998 Amancio Hasty * Copyright (c) 1995 Mark Tinguely and Jim Lowe @@ -30,8 +32,17 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD$ */ + +#ifdef __FreeBSD__ +#if (__FreeBSD_version >= 310000) +#include +#include "smbus.h" +#else +#define NSMBUS 0 +#endif +#endif + #ifndef PCI_LATENCY_TIMER #define PCI_LATENCY_TIMER 0x0c /* pci timer register */ #endif @@ -582,6 +593,7 @@ struct bktr_softc { int xtal_pll_mode; /* Use XTAL or PLL mode for PAL/SECAM */ int remote_control; /* remote control detected */ int remote_control_addr; /* remote control i2c address */ char msp_version_string[9]; /* MSP version string 34xxx-xx */ + int msp_addr; /* MSP i2c address */ }; diff --git a/sys/dev/bktr/bktr_tuner.c b/sys/dev/bktr/bktr_tuner.c new file mode 100644 index 00000000000..a0aee9280f3 --- /dev/null +++ b/sys/dev/bktr/bktr_tuner.c @@ -0,0 +1,960 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_tuner : This deals with controlling the tuner fitted to TV cards. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include +#include +#include +#include + +#include /* for DELAY */ + +#include + +#include +#include /* extensions to ioctl_meteor.h */ +#include +#include +#include +#include + + + +#if defined( TUNER_AFC ) +#define AFC_DELAY 10000 /* 10 millisend delay */ +#define AFC_BITS 0x07 +#define AFC_FREQ_MINUS_125 0x00 +#define AFC_FREQ_MINUS_62 0x01 +#define AFC_FREQ_CENTERED 0x02 +#define AFC_FREQ_PLUS_62 0x03 +#define AFC_FREQ_PLUS_125 0x04 +#define AFC_MAX_STEP (5 * FREQFACTOR) /* no more than 5 MHz */ +#endif /* TUNER_AFC */ + + +#define TTYPE_XXX 0 +#define TTYPE_NTSC 1 +#define TTYPE_NTSC_J 2 +#define TTYPE_PAL 3 +#define TTYPE_PAL_M 4 +#define TTYPE_PAL_N 5 +#define TTYPE_SECAM 6 + +#define TSA552x_CB_MSB (0x80) +#define TSA552x_CB_CP (1<<6) /* set this for fast tuning */ +#define TSA552x_CB_T2 (1<<5) /* test mode - Normally set to 0 */ +#define TSA552x_CB_T1 (1<<4) /* test mode - Normally set to 0 */ +#define TSA552x_CB_T0 (1<<3) /* test mode - Normally set to 1 */ +#define TSA552x_CB_RSA (1<<2) /* 0 for 31.25 khz, 1 for 62.5 kHz */ +#define TSA552x_CB_RSB (1<<1) /* 0 for FM 50kHz steps, 1 = Use RSA*/ +#define TSA552x_CB_OS (1<<0) /* Set to 0 for normal operation */ + +#define TSA552x_RADIO (TSA552x_CB_MSB | \ + TSA552x_CB_T0) + +/* raise the charge pump voltage for fast tuning */ +#define TSA552x_FCONTROL (TSA552x_CB_MSB | \ + TSA552x_CB_CP | \ + TSA552x_CB_T0 | \ + TSA552x_CB_RSA | \ + TSA552x_CB_RSB) + +/* lower the charge pump voltage for better residual oscillator FM */ +#define TSA552x_SCONTROL (TSA552x_CB_MSB | \ + TSA552x_CB_T0 | \ + TSA552x_CB_RSA | \ + TSA552x_CB_RSB) + +/* The control value for the ALPS TSCH5 Tuner */ +#define TSCH5_FCONTROL 0x82 +#define TSCH5_RADIO 0x86 + +/* The control value for the ALPS TSBH1 Tuner */ +#define TSBH1_FCONTROL 0xce + + +static const struct TUNER tuners[] = { +/* XXX FIXME: fill in the band-switch crosspoints */ + /* NO_TUNER */ + { "", /* the 'name' */ + TTYPE_XXX, /* input type */ + { 0x00, /* control byte for Tuner PLL */ + 0x00, + 0x00, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0x00, 0x00, 0x00,0x00} }, /* the band-switch values */ + + /* TEMIC_NTSC */ + { "Temic NTSC", /* the 'name' */ + TTYPE_NTSC, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00}, /* band-switch crosspoints */ + { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ + + /* TEMIC_PAL */ + { "Temic PAL", /* the 'name' */ + TTYPE_PAL, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ + + /* TEMIC_SECAM */ + { "Temic SECAM", /* the 'name' */ + TTYPE_SECAM, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ + + /* PHILIPS_NTSC */ + { "Philips NTSC", /* the 'name' */ + TTYPE_NTSC, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ + + /* PHILIPS_PAL */ + { "Philips PAL", /* the 'name' */ + TTYPE_PAL, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ + + /* PHILIPS_SECAM */ + { "Philips SECAM", /* the 'name' */ + TTYPE_SECAM, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ + + /* TEMIC_PAL I */ + { "Temic PAL I", /* the 'name' */ + TTYPE_PAL, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ + + /* PHILIPS_PALI */ + { "Philips PAL I", /* the 'name' */ + TTYPE_PAL, /* input type */ + { TSA552x_SCONTROL, /* control byte for Tuner PLL */ + TSA552x_SCONTROL, + TSA552x_SCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30,0x00 } }, /* the band-switch values */ + + /* PHILIPS_FR1236_NTSC */ + { "Philips FR1236 NTSC FM", /* the 'name' */ + TTYPE_NTSC, /* input type */ + { TSA552x_FCONTROL, /* control byte for Tuner PLL */ + TSA552x_FCONTROL, + TSA552x_FCONTROL, + TSA552x_RADIO }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30,0xa4 } }, /* the band-switch values */ + + /* PHILIPS_FR1216_PAL */ + { "Philips FR1216 PAL FM" , /* the 'name' */ + TTYPE_PAL, /* input type */ + { TSA552x_FCONTROL, /* control byte for Tuner PLL */ + TSA552x_FCONTROL, + TSA552x_FCONTROL, + TSA552x_RADIO }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ + + /* PHILIPS_FR1236_SECAM */ + { "Philips FR1236 SECAM FM", /* the 'name' */ + TTYPE_SECAM, /* input type */ + { TSA552x_FCONTROL, /* control byte for Tuner PLL */ + TSA552x_FCONTROL, + TSA552x_FCONTROL, + TSA552x_RADIO }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ + + /* ALPS TSCH5 NTSC */ + { "ALPS TSCH5 NTSC FM", /* the 'name' */ + TTYPE_NTSC, /* input type */ + { TSCH5_FCONTROL, /* control byte for Tuner PLL */ + TSCH5_FCONTROL, + TSCH5_FCONTROL, + TSCH5_RADIO }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0x14, 0x12, 0x11, 0x04 } }, /* the band-switch values */ + + /* ALPS TSBH1 NTSC */ + { "ALPS TSBH1 NTSC", /* the 'name' */ + TTYPE_NTSC, /* input type */ + { TSBH1_FCONTROL, /* control byte for Tuner PLL */ + TSBH1_FCONTROL, + TSBH1_FCONTROL, + 0x00 }, + { 0x00, 0x00 }, /* band-switch crosspoints */ + { 0x01, 0x02, 0x08, 0x00 } } /* the band-switch values */ +}; + + +/* scaling factor for frequencies expressed as ints */ +#define FREQFACTOR 16 + +/* + * Format: + * entry 0: MAX legal channel + * entry 1: IF frequency + * expressed as fi{mHz} * 16, + * eg 45.75mHz == 45.75 * 16 = 732 + * entry 2: [place holder/future] + * entry 3: base of channel record 0 + * entry 3 + (x*3): base of channel record 'x' + * entry LAST: NULL channel entry marking end of records + * + * Record: + * int 0: base channel + * int 1: frequency of base channel, + * expressed as fb{mHz} * 16, + * int 2: offset frequency between channels, + * expressed as fo{mHz} * 16, + */ + +/* + * North American Broadcast Channels: + * + * 2: 55.25 mHz - 4: 67.25 mHz + * 5: 77.25 mHz - 6: 83.25 mHz + * 7: 175.25 mHz - 13: 211.25 mHz + * 14: 471.25 mHz - 83: 885.25 mHz + * + * IF freq: 45.75 mHz + */ +#define OFFSET 6.00 +static int nabcst[] = { + 83, (int)( 45.75 * FREQFACTOR), 0, + 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 0 +}; +#undef OFFSET + +/* + * North American Cable Channels, IRC: + * + * 2: 55.25 mHz - 4: 67.25 mHz + * 5: 77.25 mHz - 6: 83.25 mHz + * 7: 175.25 mHz - 13: 211.25 mHz + * 14: 121.25 mHz - 22: 169.25 mHz + * 23: 217.25 mHz - 94: 643.25 mHz + * 95: 91.25 mHz - 99: 115.25 mHz + * + * IF freq: 45.75 mHz + */ +#define OFFSET 6.00 +static int irccable[] = { + 99, (int)( 45.75 * FREQFACTOR), 0, + 95, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 23, (int)(217.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 14, (int)(121.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 0 +}; +#undef OFFSET + +/* + * North American Cable Channels, HRC: + * + * 2: 54 mHz - 4: 66 mHz + * 5: 78 mHz - 6: 84 mHz + * 7: 174 mHz - 13: 210 mHz + * 14: 120 mHz - 22: 168 mHz + * 23: 216 mHz - 94: 642 mHz + * 95: 90 mHz - 99: 114 mHz + * + * IF freq: 45.75 mHz + */ +#define OFFSET 6.00 +static int hrccable[] = { + 99, (int)( 45.75 * FREQFACTOR), 0, + 95, (int)( 90.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 23, (int)(216.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 14, (int)(120.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 5, (int)( 78.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 2, (int)( 54.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 0 +}; +#undef OFFSET + +/* + * Western European broadcast channels: + * + * (there are others that appear to vary between countries - rmt) + * + * here's the table Philips provides: + * caution, some of the offsets don't compute... + * + * 1 4525 700 N21 + * + * 2 4825 700 E2 + * 3 5525 700 E3 + * 4 6225 700 E4 + * + * 5 17525 700 E5 + * 6 18225 700 E6 + * 7 18925 700 E7 + * 8 19625 700 E8 + * 9 20325 700 E9 + * 10 21025 700 E10 + * 11 21725 700 E11 + * 12 22425 700 E12 + * + * 13 5375 700 ITA + * 14 6225 700 ITB + * + * 15 8225 700 ITC + * + * 16 17525 700 ITD + * 17 18325 700 ITE + * + * 18 19225 700 ITF + * 19 20125 700 ITG + * 20 21025 700 ITH + * + * 21 47125 800 E21 + * 22 47925 800 E22 + * 23 48725 800 E23 + * 24 49525 800 E24 + * 25 50325 800 E25 + * 26 51125 800 E26 + * 27 51925 800 E27 + * 28 52725 800 E28 + * 29 53525 800 E29 + * 30 54325 800 E30 + * 31 55125 800 E31 + * 32 55925 800 E32 + * 33 56725 800 E33 + * 34 57525 800 E34 + * 35 58325 800 E35 + * 36 59125 800 E36 + * 37 59925 800 E37 + * 38 60725 800 E38 + * 39 61525 800 E39 + * 40 62325 800 E40 + * 41 63125 800 E41 + * 42 63925 800 E42 + * 43 64725 800 E43 + * 44 65525 800 E44 + * 45 66325 800 E45 + * 46 67125 800 E46 + * 47 67925 800 E47 + * 48 68725 800 E48 + * 49 69525 800 E49 + * 50 70325 800 E50 + * 51 71125 800 E51 + * 52 71925 800 E52 + * 53 72725 800 E53 + * 54 73525 800 E54 + * 55 74325 800 E55 + * 56 75125 800 E56 + * 57 75925 800 E57 + * 58 76725 800 E58 + * 59 77525 800 E59 + * 60 78325 800 E60 + * 61 79125 800 E61 + * 62 79925 800 E62 + * 63 80725 800 E63 + * 64 81525 800 E64 + * 65 82325 800 E65 + * 66 83125 800 E66 + * 67 83925 800 E67 + * 68 84725 800 E68 + * 69 85525 800 E69 + * + * 70 4575 800 IA + * 71 5375 800 IB + * 72 6175 800 IC + * + * 74 6925 700 S01 + * 75 7625 700 S02 + * 76 8325 700 S03 + * + * 80 10525 700 S1 + * 81 11225 700 S2 + * 82 11925 700 S3 + * 83 12625 700 S4 + * 84 13325 700 S5 + * 85 14025 700 S6 + * 86 14725 700 S7 + * 87 15425 700 S8 + * 88 16125 700 S9 + * 89 16825 700 S10 + * 90 23125 700 S11 + * 91 23825 700 S12 + * 92 24525 700 S13 + * 93 25225 700 S14 + * 94 25925 700 S15 + * 95 26625 700 S16 + * 96 27325 700 S17 + * 97 28025 700 S18 + * 98 28725 700 S19 + * 99 29425 700 S20 + * + * + * Channels S21 - S41 are taken from + * http://gemma.apple.com:80/dev/technotes/tn/tn1012.html + * + * 100 30325 800 S21 + * 101 31125 800 S22 + * 102 31925 800 S23 + * 103 32725 800 S24 + * 104 33525 800 S25 + * 105 34325 800 S26 + * 106 35125 800 S27 + * 107 35925 800 S28 + * 108 36725 800 S29 + * 109 37525 800 S30 + * 110 38325 800 S31 + * 111 39125 800 S32 + * 112 39925 800 S33 + * 113 40725 800 S34 + * 114 41525 800 S35 + * 115 42325 800 S36 + * 116 43125 800 S37 + * 117 43925 800 S38 + * 118 44725 800 S39 + * 119 45525 800 S40 + * 120 46325 800 S41 + * + * 121 3890 000 IFFREQ + * + */ +static int weurope[] = { + 121, (int)( 38.90 * FREQFACTOR), 0, + 100, (int)(303.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 90, (int)(231.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), + 80, (int)(105.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), + 74, (int)( 69.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), + 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 17, (int)(183.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), + 16, (int)(175.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), + 15, (int)(82.25 * FREQFACTOR), (int)(8.50 * FREQFACTOR), + 13, (int)(53.75 * FREQFACTOR), (int)(8.50 * FREQFACTOR), + 5, (int)(175.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), + 2, (int)(48.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), + 0 +}; + +/* + * Japanese Broadcast Channels: + * + * 1: 91.25MHz - 3: 103.25MHz + * 4: 171.25MHz - 7: 189.25MHz + * 8: 193.25MHz - 12: 217.25MHz (VHF) + * 13: 471.25MHz - 62: 765.25MHz (UHF) + * + * IF freq: 45.75 mHz + * OR + * IF freq: 58.75 mHz + */ +#define OFFSET 6.00 +#define IF_FREQ 45.75 +static int jpnbcst[] = { + 62, (int)(IF_FREQ * FREQFACTOR), 0, + 13, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 0 +}; +#undef IF_FREQ +#undef OFFSET + +/* + * Japanese Cable Channels: + * + * 1: 91.25MHz - 3: 103.25MHz + * 4: 171.25MHz - 7: 189.25MHz + * 8: 193.25MHz - 12: 217.25MHz + * 13: 109.25MHz - 21: 157.25MHz + * 22: 165.25MHz + * 23: 223.25MHz - 63: 463.25MHz + * + * IF freq: 45.75 mHz + */ +#define OFFSET 6.00 +#define IF_FREQ 45.75 +static int jpncable[] = { + 63, (int)(IF_FREQ * FREQFACTOR), 0, + 23, (int)(223.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 22, (int)(165.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 13, (int)(109.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 0 +}; +#undef IF_FREQ +#undef OFFSET + +/* + * xUSSR Broadcast Channels: + * + * 1: 49.75MHz - 2: 59.25MHz + * 3: 77.25MHz - 5: 93.25MHz + * 6: 175.25MHz - 12: 223.25MHz + * 13-20 - not exist + * 21: 471.25MHz - 34: 575.25MHz + * 35: 583.25MHz - 69: 855.25MHz + * + * Cable channels + * + * 70: 111.25MHz - 77: 167.25MHz + * 78: 231.25MHz -107: 463.25MHz + * + * IF freq: 38.90 MHz + */ +#define IF_FREQ 38.90 +static int xussr[] = { + 107, (int)(IF_FREQ * FREQFACTOR), 0, + 78, (int)(231.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 70, (int)(111.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 35, (int)(583.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 6, (int)(175.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 3, (int)( 77.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), + 1, (int)( 49.75 * FREQFACTOR), (int)(9.50 * FREQFACTOR), + 0 +}; +#undef IF_FREQ + +/* + * Australian broadcast channels + */ +#define OFFSET 7.00 +static int australia[] = { + 83, (int)( 45.00 * FREQFACTOR), 0, + 28, (int)(520.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 11, (int)(214.50 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 10, (int)(201.50 * FREQFACTOR), (int)( 13.00 * FREQFACTOR), + 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 3, (int)( 85.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 2, (int)( 56.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), + 0 +}; +#undef OFFSET + +static struct { + int *ptr; + char name[BT848_MAX_CHNLSET_NAME_LEN]; +} freqTable[] = { + {NULL, ""}, + {nabcst, "nabcst"}, + {irccable, "cableirc"}, + {hrccable, "cablehrc"}, + {weurope, "weurope"}, + {jpnbcst, "jpnbcst"}, + {jpncable, "jpncable"}, + {xussr, "xussr"}, + {australia, "australia"}, + +}; + +#define TBL_CHNL freqTable[ bktr->tuner.chnlset ].ptr[ x ] +#define TBL_BASE_FREQ freqTable[ bktr->tuner.chnlset ].ptr[ x + 1 ] +#define TBL_OFFSET freqTable[ bktr->tuner.chnlset ].ptr[ x + 2 ] +static int +frequency_lookup( bktr_ptr_t bktr, int channel ) +{ + int x; + + /* check for "> MAX channel" */ + x = 0; + if ( channel > TBL_CHNL ) + return( -1 ); + + /* search the table for data */ + for ( x = 3; TBL_CHNL; x += 3 ) { + if ( channel >= TBL_CHNL ) { + return( TBL_BASE_FREQ + + ((channel - TBL_CHNL) * TBL_OFFSET) ); + } + } + + /* not found, must be below the MIN channel */ + return( -1 ); +} +#undef TBL_OFFSET +#undef TBL_BASE_FREQ +#undef TBL_CHNL + + +#define TBL_IF freqTable[ bktr->tuner.chnlset ].ptr[ 1 ] + + +/* Initialise the tuner structures in the bktr_softc */ +/* This is needed as the tuner details are no longer globally declared */ + +void select_tuner( bktr_ptr_t bktr, int tuner_type ) { + if (tuner_type < Bt848_MAX_TUNER) { + bktr->card.tuner = &tuners[ tuner_type ]; + } else { + bktr->card.tuner = NULL; + } +} + +/* + * Tuner Notes: + * Programming the tuner properly is quite complicated. + * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner. + * The tuner (front end) covers 45.75 Mhz - 855.25 Mhz and an FM band of + * 87.5 Mhz to 108.0 Mhz. + * + * RF and IF. RF = radio frequencies, it is the transmitted signal. + * IF is the Intermediate Frequency (the offset from the base + * signal where the video, color, audio and NICAM signals are. + * + * Eg, Picture at 38.9 Mhz, Colour at 34.47 MHz, sound at 32.9 MHz + * NICAM at 32.348 Mhz. + * Strangely enough, there is an IF (intermediate frequency) for + * FM Radio which is 10.7 Mhz. + * + * The tuner also works in Bands. Philips bands are + * FM radio band 87.50 to 108.00 MHz + * Low band 45.75 to 170.00 MHz + * Mid band 170.00 to 450.00 MHz + * High band 450.00 to 855.25 MHz + * + * + * Now we need to set the PLL on the tuner to the required freuqncy. + * It has a programmable divisor. + * For TV we want + * N = 16 (freq RF(pc) + freq IF(pc)) pc is picture carrier and RF and IF + * are in MHz. + + * For RADIO we want a different equation. + * freq IF is 10.70 MHz (so the data sheet tells me) + * N = (freq RF + freq IF) / step size + * The step size must be set to 50 khz (so the data sheet tells me) + * (note this is 50 kHz, the other things are in MHz) + * so we end up with N = 20x(freq RF + 10.7) + * + */ + +#define LOW_BAND 0 +#define MID_BAND 1 +#define HIGH_BAND 2 +#define FM_RADIO_BAND 3 + + +/* Check if these are correct for other than Philips PAL */ +#define STATUSBIT_COLD 0x80 +#define STATUSBIT_LOCK 0x40 +#define STATUSBIT_TV 0x20 +#define STATUSBIT_STEREO 0x10 /* valid if FM (aka not TV) */ +#define STATUSBIT_ADC 0x07 + +/* + * set the frequency of the tuner + * If 'type' is TV_FREQUENCY, the frequency is freq MHz*16 + * If 'type' is FM_RADIO_FREQUENCY, the frequency is freq MHz * 100 + * (note *16 gives is 4 bits of fraction, eg steps of nnn.0625) + * + */ +int +tv_freq( bktr_ptr_t bktr, int frequency, int type ) +{ + const struct TUNER* tuner; + u_char addr; + u_char control; + u_char band; + int N; + int band_select = 0; + + tuner = bktr->card.tuner; + if ( tuner == NULL ) + return( -1 ); + + if (type == TV_FREQUENCY) { + /* + * select the band based on frequency + * XXX FIXME: get the cross-over points from the tuner struct + */ + if ( frequency < (160 * FREQFACTOR ) ) + band_select = LOW_BAND; + else if ( frequency < (454 * FREQFACTOR ) ) + band_select = MID_BAND; + else + band_select = HIGH_BAND; + +#if defined( TEST_TUNER_AFC ) + if ( bktr->tuner.afc ) + frequency -= 4; +#endif + /* + * N = 16 * { fRF(pc) + fIF(pc) } + * or N = 16* fRF(pc) + 16*fIF(pc) } + * where: + * pc is picture carrier, fRF & fIF are in MHz + * + * fortunatly, frequency is passed in as MHz * 16 + * and the TBL_IF frequency is also stored in MHz * 16 + */ + N = frequency + TBL_IF; + + /* set the address of the PLL */ + addr = bktr->card.tuner_pllAddr; + control = tuner->pllControl[ band_select ]; + band = tuner->bandAddrs[ band_select ]; + + if(!(band && control)) /* Don't try to set un- */ + return(-1); /* supported modes. */ + + if ( frequency > bktr->tuner.frequency ) { + i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); + i2cWrite( bktr, addr, control, band ); + } + else { + i2cWrite( bktr, addr, control, band ); + i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); + } + +#if defined( TUNER_AFC ) + if ( bktr->tuner.afc == TRUE ) { + if ( (N = do_afc( bktr, addr, N )) < 0 ) { + /* AFC failed, restore requested frequency */ + N = frequency + TBL_IF; + i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); + } + else + frequency = N - TBL_IF; + } +#endif /* TUNER_AFC */ + + bktr->tuner.frequency = frequency; + } + + if ( type == FM_RADIO_FREQUENCY ) { + band_select = FM_RADIO_BAND; + + /* + * N = { fRF(pc) + fIF(pc) }/step_size + * The step size is 50kHz for FM radio. + * (eg after 102.35MHz comes 102.40 MHz) + * fIF is 10.7 MHz (as detailed in the specs) + * + * frequency is passed in as MHz * 100 + * + * So, we have N = (frequency/100 + 10.70) /(50/1000) + */ + N = (frequency + 1070)/5; + + /* set the address of the PLL */ + addr = bktr->card.tuner_pllAddr; + control = tuner->pllControl[ band_select ]; + band = tuner->bandAddrs[ band_select ]; + + if(!(band && control)) /* Don't try to set un- */ + return(-1); /* supported modes. */ + +/* band |= bktr->tuner.radio_mode;*/ + /* tuner.radio_mode is set in + * the ioctls RADIO_SETMODE + * and RADIO_GETMODE */ + + i2cWrite( bktr, addr, control, band ); + i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); + + bktr->tuner.frequency = (N * 5) - 1070; + + + } + + + return( 0 ); +} + + + +#if defined( TUNER_AFC ) +/* + * + */ +int +do_afc( bktr_ptr_t bktr, int addr, int frequency ) +{ + int step; + int status; + int origFrequency; + + origFrequency = frequency; + + /* wait for first setting to take effect */ + tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 ); + + if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) + return( -1 ); + +#if defined( TEST_TUNER_AFC ) + printf( "\nOriginal freq: %d, status: 0x%02x\n", frequency, status ); +#endif + for ( step = 0; step < AFC_MAX_STEP; ++step ) { + if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) + goto fubar; + if ( !(status & 0x40) ) { +#if defined( TEST_TUNER_AFC ) + printf( "no lock!\n" ); +#endif + goto fubar; + } + + switch( status & AFC_BITS ) { + case AFC_FREQ_CENTERED: +#if defined( TEST_TUNER_AFC ) + printf( "Centered, freq: %d, status: 0x%02x\n", frequency, status ); +#endif + return( frequency ); + + case AFC_FREQ_MINUS_125: + case AFC_FREQ_MINUS_62: +#if defined( TEST_TUNER_AFC ) + printf( "Low, freq: %d, status: 0x%02x\n", frequency, status ); +#endif + --frequency; + break; + + case AFC_FREQ_PLUS_62: + case AFC_FREQ_PLUS_125: +#if defined( TEST_TUNER_AFC ) + printf( "Hi, freq: %d, status: 0x%02x\n", frequency, status ); +#endif + ++frequency; + break; + } + + i2cWrite( bktr, addr, + (frequency>>8) & 0x7f, frequency & 0xff ); + DELAY( AFC_DELAY ); + } + + fubar: + i2cWrite( bktr, addr, + (origFrequency>>8) & 0x7f, origFrequency & 0xff ); + + return( -1 ); +} +#endif /* TUNER_AFC */ +#undef TBL_IF + + +/* + * Get the Tuner status and signal strength + */ +int get_tuner_status( bktr_ptr_t bktr ) { + return i2cRead( bktr, bktr->card.tuner_pllAddr + 1 ); +} + +/* + * set the channel of the tuner + */ +int +tv_channel( bktr_ptr_t bktr, int channel ) +{ + int frequency; + + /* calculate the frequency according to tuner type */ + if ( (frequency = frequency_lookup( bktr, channel )) < 0 ) + return( -1 ); + + /* set the new frequency */ + if ( tv_freq( bktr, frequency, TV_FREQUENCY ) < 0 ) + return( -1 ); + + /* OK to update records */ + return( (bktr->tuner.channel = channel) ); +} + +/* + * get channelset name + */ +int +tuner_getchnlset(struct bktr_chnlset *chnlset) +{ + if (( chnlset->index < CHNLSET_MIN ) || + ( chnlset->index > CHNLSET_MAX )) + return( EINVAL ); + + memcpy(&chnlset->name, &freqTable[chnlset->index].name, + BT848_MAX_CHNLSET_NAME_LEN); + + chnlset->max_channel=freqTable[chnlset->index].ptr[0]; + return( 0 ); +} diff --git a/sys/dev/bktr/bktr_tuner.h b/sys/dev/bktr/bktr_tuner.h new file mode 100644 index 00000000000..d7a67c0f834 --- /dev/null +++ b/sys/dev/bktr/bktr_tuner.h @@ -0,0 +1,103 @@ +/* $FreeBSD$ */ + +/* + * This is part of the Driver for Video Capture Cards (Frame grabbers) + * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 + * chipset. + * Copyright Roger Hardiman and Amancio Hasty. + * + * bktr_tuner : This deals with controlling the tuner fitted to TV cards. + * + */ + +/* + * 1. Redistributions of source code must retain the + * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Amancio Hasty and + * Roger Hardiman + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Definitions for Tuners */ + +#define NO_TUNER 0 +#define TEMIC_NTSC 1 +#define TEMIC_PAL 2 +#define TEMIC_SECAM 3 +#define PHILIPS_NTSC 4 +#define PHILIPS_PAL 5 +#define PHILIPS_SECAM 6 +#define TEMIC_PALI 7 +#define PHILIPS_PALI 8 +#define PHILIPS_FR1236_NTSC 9 /* These have FM radio support */ +#define PHILIPS_FR1216_PAL 10 /* These have FM radio support */ +#define PHILIPS_FR1236_SECAM 11 /* These have FM radio support */ +#define ALPS_TSCH5 12 +#define ALPS_TSBH1 13 +#define Bt848_MAX_TUNER 14 + +/* experimental code for Automatic Frequency Control */ +#define TUNER_AFC + +/* + * Fill in the tuner entries in the bktr_softc based on the selected tuner + * type (from the list of tuners above) + */ +void select_tuner( bktr_ptr_t bktr, int tuner_type ); + + +/* + * The Channel Set maps TV channels eg Ch 36, Ch 51, onto frequencies + * and is country specific. + */ +int tuner_getchnlset( struct bktr_chnlset *chnlset ); + +/* + * tv_channel sets the tuner to channel 'n' using the current Channel Set + * tv_freq sets the tuner to a specific frequency for TV or for FM Radio + * get_tuner_status can be used to get the signal strength. + */ +#define TV_FREQUENCY 0 +#define FM_RADIO_FREQUENCY 1 +int tv_channel( bktr_ptr_t bktr, int channel ); +int tv_freq( bktr_ptr_t bktr, int frequency, int type ); +int get_tuner_status( bktr_ptr_t bktr ); + +#if defined( TUNER_AFC ) +int do_afc( bktr_ptr_t bktr, int addr, int frequency ); +#endif /* TUNER_AFC */ + + +/* + * This is for start-up convenience only, NOT mandatory. + */ +#if !defined( DEFAULT_CHNLSET ) +#define DEFAULT_CHNLSET CHNLSET_WEUROPE +#endif + +