aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsys/dev/bktr/CHANGELOG.TXT404
-rw-r--r--sys/dev/bktr/bktr_audio.c432
-rw-r--r--sys/dev/bktr/bktr_audio.h76
-rw-r--r--sys/dev/bktr/bktr_card.c1069
-rw-r--r--sys/dev/bktr/bktr_card.h84
-rw-r--r--sys/dev/bktr/bktr_core.c3511
-rw-r--r--sys/dev/bktr/bktr_core.h93
-rw-r--r--sys/dev/bktr/bktr_os.c1200
-rw-r--r--sys/dev/bktr/bktr_os.h58
-rw-r--r--sys/dev/bktr/bktr_reg.h14
-rw-r--r--sys/dev/bktr/bktr_tuner.c960
-rw-r--r--sys/dev/bktr/bktr_tuner.h103
12 files changed, 4580 insertions, 3424 deletions
diff --git a/sys/dev/bktr/CHANGELOG.TXT b/sys/dev/bktr/CHANGELOG.TXT
new file mode 100755
index 000000000000..e61341cdc5f9
--- /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 <rhh@ct.picker.com>. 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 <petry@netwolf.NetMasters.com>
+
+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
+ <richard@cogsci.ed.ac.uk>.
+
+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 <gurney_j@resnet.uoregon.edu>
+ Added [SR]RGBMASKs ioctl for byte swapping.
+
+1.16 4/20/97 Randall Hopper <rhh@ct.picker.com>
+ 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 <sklower@CS.Berkeley.EDU> submitted
+ a patch to fix compilation of the BSDI's PCI
+ interface.
+ Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
+ 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 <rhh@ct.picker.com>
+ 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 <rhh@ct.picker.com>
+ Fixes for packed 24bpp - FIFO alignment
+1.23 11/17/97 Amancio <hasty@star-gate.com>
+ Added yuv support mpeg encoding
+1.24 12/27/97 Jonathan Hanna <pangolin@rogers.wave.ca>
+ Patch to support Philips FR1236MK2 tuner
+1.25 02/02/98 Takeshi Ohashi
+ <ohashi@atohasi.mickey.ai.kyutech.ac.jp> submitted
+ code to support bktr_read .
+ Flemming Jacobsen <fj@schizo.dk.tfs.com>
+ submitted code to support radio available with in
+ some bt848 based cards;additionally, wrote code to
+ correctly recognized his bt848 card.
+ Roger Hardiman <roger@cs.strath.ac.uk> 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 <fj@trw.nl>.
+ Added B849 PCI ID submitted by:
+ Tomi Vainio <tomppa@fidata.fi>
+1.28 Frank Nobis <fn@Radio-do.de> added tuner support
+ for the German Phillips PAL tuner and
+ additional channels for german cable tv.
+1.29 Roger Hardiman <roger@cs.strath.ac.uk>
+ 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 <fn@Radio-do.de>'s opt_bktr.h
+
+1.31 Randall Hopper <rhh@ct.picker.com>
+ 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 <roger@cs.strath.ac.uk>
+ 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 <sos@freebsd.org>
+
+1.39 08/05/98 Roger Hardiman <roger@cs.strath.ac.uk>
+ 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 <roger@cs.strath.ac.uk>
+ 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 <roger@cs.strath.ac.uk>
+ 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 <seva@alex-ua.com>.
+ In kernel configuration file add
+ options OVERRIDE_CARD=2
+ options OVERRIDE_TUNER=11
+ options BKTR_USE_PLL
+
+1.51 31 August 1998 Roger Hardiman <roger@cs.strath.ac.uk>
+ 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 <roger@cs.strath.ac.uk>
+ Submitted patch by Vsevolod Lobko <seva@alex-ua.com>
+ to correct SECAM B-Delay and add XUSSR channel set.
+
+1.53 9 Sep 1998 Roger Hardiman <roger@cs.strath.ac.uk>
+ Changed METEORSINPUT for Hauppauge cards with bt878.
+ Submitted by Fred Templin <templin@erg.sri.com>
+ Also fixed video_open defines and 878 support.
+
+1.54 18 Sep 1998 Roger Hardiman <roger@cs.strath.ac.uk>
+ Changed tuner code to autodetect tuner i2c address.
+ Addresses were incorrectly hardcoded.
+
+1.55 21 Sep 1998 Roger Hardiman <roger@cs.strath.ac.uk>
+ 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 <roger@cs.strath.ac.uk>
+ Added detection of Hauppauge IR remote control.
+ and MSP34xx Audio chip. Fixed i2c read error.
+ Hauppauge supplied details of new Tuner Types.
+ Danny Braniss <danny@cs.huji.ac.il> submitted Bt878
+ AverMedia detection with PCI subsystem vendor id.
+
+1.57 26 Jan 1999 Roger Hardiman <roger@cs.strath.ac.uk>
+ Support for MSP3410D / MSP3415D Stereo/Mono audio
+ using the audio format Auto Detection Mode.
+ Nicolas Souchu <nsouch@freebsd.org> 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<gozer@ludd.luth.se>
+ For true SVIDEO, use METEOR_INPUT_DEV_SVIDEO
+
+1.58 8 Feb 1999 Roger Hardiman <roger@cs.strath.ac.uk>
+ Added check to bktr_mmap from OpenBSD driver.
+ Improved MSP34xx reset for bt848 Hauppauge boards.
+ Added detection for Bt848a.
+ Vsevolod Lobko<seva@sevasoft.alex-ua.com> 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 <seva@alex-ua.com>
+
+1.60 23 Feb 1999 Roger Hardiman <roger@freebsd.org>
+ Corrected Mute on Hauppauge Radio cards.
+ Autodetect MMAC Osprey by looking for "MMAC" in the EEPROM.
+ Added for Jan Schmidt <mmedia@rz.uni-greifswald.de>
+ Added ALPS Tuner Type from Hiroki Mori <mori@infocity.co.jp>
+
+1.61 29 Apr 1999 Roger Hardiman <roger@freebsd.org>
+ Fix row=0/columns=0 bug. From Randal Hopper<aa8vb@ipass.net>
+ 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 <yuri@xpert.com>
+
+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 <mori@infocity.co.jp>
+
+1.63 29 Apr 1999 Roger Hardiman <roger@freebsd.org>
+ Added initial code for VBI capture based on work by
+ Hiroki Mori <mori@infocity.co.jp> and reworked by myself.
+ This allows software decoding of teletext, intercast and
+ subtitles via /dev/vbi.
+
+1.64 7 May 1999 Roger Hardiman <roger@freebsd.org>
+ Support LifeView FlyVideo 98 cards. Use EEPROM for card
+ autodetection. Use bttv's audio mux values.
+ Thanks to Paul Reece <paul@fastlane.net.au>,
+ Ivan Brawley <brawley@internode.com.au> and
+ Gilad Rom <rom_glsa@ein-hashofet.co.il>
+ 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 <roger@freebsd.org>
+ 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 <brawley@internode.com.au> added
+ the Australian channel frequencies.
+
+1.66 19 May 1999 Ivan Brawley <brawley@internode.com.au> added better
+ Australian channel frequencies.
+
+1.67 23 May 1999 Roger Hardiman <roger@freebsd.org>
+ 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 <roger@freebsd.org>
+ 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 <roger@freebsd.org>
+ Updates for FreeBSD 4.x device driver interface.
+ BSDI code removed. Will be restored later.
+
+1.70 12 July 1999 Roger Hardiman <roger@freebsd.org>
+ 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 <matt@dqc.org> added MSP3430G DBX initialisation.
+
+1.71 30 Aug 1999 Roger Hardiman <roger@freebsd.org>
+ 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 <Juha.Nurmela@quicknet.inet.fi>
+ Add support for Hauppauge 627 and Temic 4006 submitted
+ by Maurice Castro <maurice@atum.castro.aus.net>
+ Tom Jansen <tom@unhooked.net> added BSDi support again.
+
+1.72 31 Aug 1999 Juha Nurmela <Juha.Nurmela@quicknet.inet.fi>
+ Clear cap_ctl register when restarting the RISC program.
+ This fixes the freezes experienced when changing changes.
+
+1.73 10 Sep 1999 Roger Hardiman <roger@freebsd.org>
+ Add Hauppauge tuner #6 for Brian Somers <brian@freebsd.org>
+ Add card type for Aimslabs Video Highway Xtreme for
+ Ladislav Kostal <kostal@pefstud.uniag.sk>
+ Added select() code (for VBI) for the 2.2.x driver
+ tested by Steve Richards <steve@richsoft.demon.co.uk>
+
+1.74 17 Sep 1999 Roger Hardiman <roger@freebsd.org>
+ 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 <dlacroix@cowpie.acm.vt.edu>
+ Tidy up some tuner code and Hauppauge detection code.
+ New NetBSD code from Bernd Ernesti<bernd@arresum.inka.de>
+
+2.00 25 Sep 1999 Roger Hardiman <roger@freebsd.org>
+ 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 000000000000..9f27a668159d
--- /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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/vnode.h>
+
+#include <machine/clock.h> /* for DELAY */
+
+#include <pci/pcivar.h>
+
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
+#include <dev/bktr/bktr_reg.h>
+#include <dev/bktr/bktr_core.h>
+#include <dev/bktr/bktr_tuner.h>
+#include <dev/bktr/bktr_card.h>
+#include <dev/bktr/bktr_audio.h>
+
+
+/*
+ * 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 000000000000..79bb36614355
--- /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 000000000000..5975b4d1bc89
--- /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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+
+#include <machine/clock.h> /* for DELAY */
+
+#include <pci/pcivar.h>
+
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
+#include <dev/bktr/bktr_reg.h>
+#include <dev/bktr/bktr_core.h>
+#include <dev/bktr/bktr_tuner.h>
+#include <dev/bktr/bktr_card.h>
+#include <dev/bktr/bktr_audio.h>
+
+/* 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 000000000000..d6257430a844
--- /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 <card type>
+ * eg options OVERRIDE CARD=1
+ *
+ * or using the sysclt hw.bt848.card
+ * eg sysctl -w hw.bt848.card=1
+ *
+ * where <card type> 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 cffa17a284d4..538c0058911e 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 <rhh@ct.picker.com>. 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 <petry@netwolf.NetMasters.com>
-
-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
- <richard@cogsci.ed.ac.uk>.
-
-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 <gurney_j@resnet.uoregon.edu>
- Added [SR]RGBMASKs ioctl for byte swapping.
-
-1.16 4/20/97 Randall Hopper <rhh@ct.picker.com>
- 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 <sklower@CS.Berkeley.EDU> submitted
- a patch to fix compilation of the BSDI's PCI
- interface.
- Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
- 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 <rhh@ct.picker.com>
- 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 <rhh@ct.picker.com>
- Fixes for packed 24bpp - FIFO alignment
-1.23 11/17/97 Amancio <hasty@star-gate.com>
- Added yuv support mpeg encoding
-1.24 12/27/97 Jonathan Hanna <pangolin@rogers.wave.ca>
- Patch to support Philips FR1236MK2 tuner
-1.25 02/02/98 Takeshi Ohashi
- <ohashi@atohasi.mickey.ai.kyutech.ac.jp> submitted
- code to support bktr_read .
- Flemming Jacobsen <fj@schizo.dk.tfs.com>
- submitted code to support radio available with in
- some bt848 based cards;additionally, wrote code to
- correctly recognized his bt848 card.
- Roger Hardiman <roger@cs.strath.ac.uk> 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 <fj@trw.nl>.
- Added B849 PCI ID submitted by:
- Tomi Vainio <tomppa@fidata.fi>
-1.28 Frank Nobis <fn@Radio-do.de> added tuner support
- for the German Phillips PAL tuner and
- additional channels for german cable tv.
-1.29 Roger Hardiman <roger@cs.strath.ac.uk>
- 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 <fn@Radio-do.de>'s opt_bktr.h
-
-1.31 Randall Hopper <rhh@ct.picker.com>
- 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 <roger@cs.strath.ac.uk>
- 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 <sos@freebsd.org>
-
-1.39 08/05/98 Roger Hardiman <roger@cs.strath.ac.uk>
- 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 <roger@cs.strath.ac.uk>
- 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 <roger@cs.strath.ac.uk>
- 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 <seva@alex-ua.com>.
- In kernel configuration file add
- options OVERRIDE_CARD=2
- options OVERRIDE_TUNER=11
- options BKTR_USE_PLL
-
-1.51 31 August 1998 Roger Hardiman <roger@cs.strath.ac.uk>
- 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 <roger@cs.strath.ac.uk>
- Submitted patch by Vsevolod Lobko <seva@alex-ua.com>
- to correct SECAM B-Delay and add XUSSR channel set.
-
-1.53 9 Sep 1998 Roger Hardiman <roger@cs.strath.ac.uk>
- Changed METEORSINPUT for Hauppauge cards with bt878.
- Submitted by Fred Templin <templin@erg.sri.com>
- Also fixed video_open defines and 878 support.
-
-1.54 18 Sep 1998 Roger Hardiman <roger@cs.strath.ac.uk>
- Changed tuner code to autodetect tuner i2c address.
- Addresses were incorrectly hardcoded.
-
-1.55 21 Sep 1998 Roger Hardiman <roger@cs.strath.ac.uk>
- 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 <roger@cs.strath.ac.uk>
- Added detection of Hauppauge IR remote control.
- and MSP34xx Audio chip. Fixed i2c read error.
- Hauppauge supplied details of new Tuner Types.
- Danny Braniss <danny@cs.huji.ac.il> submitted Bt878
- AverMedia detection with PCI subsystem vendor id.
-
-1.57 26 Jan 1999 Roger Hardiman <roger@cs.strath.ac.uk>
- Support for MSP3410D / MSP3415D Stereo/Mono audio
- using the audio format Auto Detection Mode.
- Nicolas Souchu <nsouch@freebsd.org> 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<gozer@ludd.luth.se>
- For true SVIDEO, use METEOR_INPUT_DEV_SVIDEO
-
-1.58 8 Feb 1999 Roger Hardiman <roger@cs.strath.ac.uk>
- Added check to bktr_mmap from OpenBSD driver.
- Improved MSP34xx reset for bt848 Hauppauge boards.
- Added detection for Bt848a.
- Vsevolod Lobko<seva@sevasoft.alex-ua.com> 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 <seva@alex-ua.com>
-
-1.60 23 Feb 1999 Roger Hardiman <roger@freebsd.org>
- Corrected Mute on Hauppauge Radio cards.
- Autodetect MMAC Osprey by looking for "MMAC" in the EEPROM.
- Added for Jan Schmidt <mmedia@rz.uni-greifswald.de>
- Added ALPS Tuner Type from Hiroki Mori <mori@infocity.co.jp>
-
-1.61 29 Apr 1999 Roger Hardiman <roger@freebsd.org>
- Fix row=0/columns=0 bug. From Randal Hopper<aa8vb@ipass.net>
- 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 <yuri@xpert.com>
-
-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 <mori@infocity.co.jp>
-
-1.63 29 Apr 1999 Roger Hardiman <roger@freebsd.org>
- Added initial code for VBI capture based on work by
- Hiroki Mori <mori@infocity.co.jp> and reworked by myself.
- This allows software decoding of teletext, intercast and
- subtitles via /dev/vbi.
-
-1.64 7 May 1999 Roger Hardiman <roger@freebsd.org>
- Support LifeView FlyVideo 98 cards. Use EEPROM for card
- autodetection. Use bttv's audio mux values.
- Thanks to Paul Reece <paul@fastlane.net.au>,
- Ivan Brawley <brawley@internode.com.au> and
- Gilad Rom <rom_glsa@ein-hashofet.co.il>
- 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 <roger@freebsd.org>
- 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 <brawley@internode.com.au> added
- the Australian channel frequencies.
-
-1.66 19 May 1999 Ivan Brawley <brawley@internode.com.au> added better
- Australian channel frequencies.
-
-1.67 23 May 1999 Roger Hardiman <roger@freebsd.org>
- 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 <roger@freebsd.org>
- 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 <roger@freebsd.org>
- Updates for FreeBSD 4.x device driver interface.
- BSDI code removed. Will be restored later.
-
-1.70 12 July 1999 Roger Hardiman <roger@freebsd.org>
- 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 <matt@dqc.org> added MSP3430G DBX initialisation.
-
-1.71 30 Aug 1999 Roger Hardiman <roger@freebsd.org>
- 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 <Juha.Nurmela@quicknet.inet.fi>
- Add support for Hauppauge 627 and Temic 4006 submitted
- by Maurice Castro <maurice@atum.castro.aus.net>
- Tom Jansen <tom@unhooked.net> added BSDi support again.
-
-1.72 31 Aug 1999 Juha Nurmela <Juha.Nurmela@quicknet.inet.fi>
- Clear cap_ctl register when restarting the RISC program.
- This fixes the freezes experienced when changing changes.
-
-1.73 10 Sep 1999 Roger Hardiman <roger@freebsd.org>
- Add Hauppauge tuner #6 for Brian Somers <brian@freebsd.org>
- Add card type for Aimslabs Video Highway Xtreme for
- Ladislav Kostal <kostal@pefstud.uniag.sk>
- Added select() code (for VBI) for the 2.2.x driver
- tested by Steve Richards <steve@richsoft.demon.co.uk>
-
-1.74 17 Sep 1999 Roger Hardiman <roger@freebsd.org>
- 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 <dlacroix@cowpie.acm.vt.edu>
- Tidy up some tuner code and Hauppauge detection code.
- New NetBSD code from Bernd Ernesti<bernd@arresum.inka.de>
-*/
#ifdef __FreeBSD__
#include "bktr.h"
@@ -491,11 +116,8 @@ They are unrelated to Revision Control numbering of FreeBSD or any other system.
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
-#include <sys/uio.h>
#include <sys/kernel.h>
#include <sys/signalvar.h>
-#include <sys/mman.h>
-#include <sys/select.h>
#include <sys/vnode.h>
#include <vm/vm.h>
@@ -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 <sys/poll.h>
-#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 <sys/devfsext.h>
-#endif /* DEVFS */
-#endif
-
#if (__FreeBSD_version >=400000) || (NSMBUS > 0)
#include <sys/bus.h> /* used by smbus and newbus */
#endif
-#if (__FreeBSD_version >=400000)
-#include <machine/bus.h> /* used by newbus */
-#include <sys/rman.h> /* used by newbus */
-#include <machine/resource.h> /* used by newbus */
-#endif
-
#include <machine/clock.h> /* for DELAY */
#include <pci/pcivar.h>
-#include <pci/pcireg.h>
#include <machine/ioctl_meteor.h>
#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
#include <dev/bktr/bktr_reg.h>
+#include <dev/bktr/bktr_tuner.h>
+#include <dev/bktr/bktr_card.h>
+#include <dev/bktr/bktr_audio.h>
+#include <dev/bktr/bktr_core.h>
+#include <dev/bktr/bktr_os.h>
#if (NSMBUS > 0)
#include <dev/bktr/bktr_i2c.h>
@@ -556,26 +154,9 @@ They are unrelated to Revision Control numbering of FreeBSD or any other system.
#include "iicbus_if.h"
#endif
-#include <sys/sysctl.h>
-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 <tuner type>
- *
- * where <tuner type> 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 */
- { "<no>", /* 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 <card type>
- *
- * where <card type> 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 000000000000..f6870936a0f0
--- /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 000000000000..2384082b61b5
--- /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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/signalvar.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+
+/*******************/
+/* *** FreeBSD *** */
+/*******************/
+#ifdef __FreeBSD__
+
+#if (__FreeBSD_version < 400000)
+#ifdef DEVFS
+#include <sys/devfsext.h>
+#endif /* DEVFS */
+#endif
+
+#if (__FreeBSD_version >=400000) || (NSMBUS > 0)
+#include <sys/bus.h> /* used by smbus and newbus */
+#endif
+
+#if (__FreeBSD_version >=400000)
+#include <machine/bus.h> /* used by newbus */
+#include <sys/rman.h> /* used by newbus */
+#include <machine/resource.h> /* used by newbus */
+#endif
+
+#include <machine/clock.h> /* for DELAY */
+#include <pci/pcivar.h>
+#include <pci/pcireg.h>
+
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
+#include <dev/bktr/bktr_reg.h>
+#include <dev/bktr/bktr_tuner.h>
+#include <dev/bktr/bktr_card.h>
+#include <dev/bktr/bktr_audio.h>
+#include <dev/bktr/bktr_core.h>
+#include <dev/bktr/bktr_os.h>
+
+#if (NSMBUS > 0)
+#include <dev/bktr/bktr_i2c.h>
+#endif
+
+#include <sys/sysctl.h>
+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 000000000000..50334d096f68
--- /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 9bffd97b26a4..0299221869e4 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 <sys/bus.h>
+#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 000000000000..a0aee9280f39
--- /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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/vnode.h>
+
+#include <machine/clock.h> /* for DELAY */
+
+#include <pci/pcivar.h>
+
+#include <machine/ioctl_meteor.h>
+#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
+#include <dev/bktr/bktr_reg.h>
+#include <dev/bktr/bktr_tuner.h>
+#include <dev/bktr/bktr_card.h>
+#include <dev/bktr/bktr_core.h>
+
+
+
+#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 */
+ { "<no>", /* 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 000000000000..d7a67c0f834f
--- /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
+
+