1119418Sobrien/*- 251694Sroger * 1. Redistributions of source code must retain the 351694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 451694Sroger * All rights reserved. 551694Sroger * 651694Sroger * Redistribution and use in source and binary forms, with or without 751694Sroger * modification, are permitted provided that the following conditions 851694Sroger * are met: 951694Sroger * 1. Redistributions of source code must retain the above copyright 1051694Sroger * notice, this list of conditions and the following disclaimer. 1151694Sroger * 2. Redistributions in binary form must reproduce the above copyright 1251694Sroger * notice, this list of conditions and the following disclaimer in the 1351694Sroger * documentation and/or other materials provided with the distribution. 1451694Sroger * 3. All advertising materials mentioning features or use of this software 1551694Sroger * must display the following acknowledgement: 1651694Sroger * This product includes software developed by Amancio Hasty and 1751694Sroger * Roger Hardiman 1851694Sroger * 4. The name of the author may not be used to endorse or promote products 1951694Sroger * derived from this software without specific prior written permission. 2051694Sroger * 2151694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2251694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2351694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2451694Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2551694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2651694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2751694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2851694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2951694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3051694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3151694Sroger * POSSIBILITY OF SUCH DAMAGE. 3251694Sroger */ 3351694Sroger 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/dev/bktr/bktr_tuner.c 152375 2005-11-13 13:26:37Z netchild $"); 3651694Sroger 37119418Sobrien/* 38119418Sobrien * This is part of the Driver for Video Capture Cards (Frame grabbers) 39119418Sobrien * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 40119418Sobrien * chipset. 41119418Sobrien * Copyright Roger Hardiman and Amancio Hasty. 42119418Sobrien * 43119418Sobrien * bktr_tuner : This deals with controlling the tuner fitted to TV cards. 44119418Sobrien */ 4551694Sroger 4651694Sroger#include <sys/param.h> 4751694Sroger#include <sys/systm.h> 4851694Sroger#include <sys/kernel.h> 4959014Sroger#ifdef __NetBSD__ 5059014Sroger#include <sys/proc.h> 5159014Sroger#endif 5251694Sroger 5359014Sroger#ifdef __FreeBSD__ 5467306Sroger#if (__FreeBSD_version < 500000) 5567306Sroger#include <machine/clock.h> /* for DELAY */ 56119277Simp#include <pci/pcivar.h> 57119277Simp#else 58139917Simp#include <sys/lock.h> 59139917Simp#include <sys/mutex.h> 60139917Simp#include <sys/selinfo.h> 61119277Simp#include <dev/pci/pcivar.h> 6267306Sroger#endif 6367306Sroger 6459014Sroger#include <machine/bus.h> 6559014Sroger#include <sys/bus.h> 6659014Sroger#endif 6759014Sroger 6859014Sroger#ifdef __NetBSD__ 6962112Sroger#include <dev/ic/bt8xx.h> /* NetBSD .h file location */ 7062112Sroger#include <dev/pci/bktr/bktr_reg.h> 7162112Sroger#include <dev/pci/bktr/bktr_tuner.h> 7262112Sroger#include <dev/pci/bktr/bktr_card.h> 7362112Sroger#include <dev/pci/bktr/bktr_core.h> 7459014Sroger#else 75123291Sobrien#include <dev/bktr/ioctl_meteor.h> 76123291Sobrien#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 7751694Sroger#include <dev/bktr/bktr_reg.h> 7851694Sroger#include <dev/bktr/bktr_tuner.h> 7951694Sroger#include <dev/bktr/bktr_card.h> 8051694Sroger#include <dev/bktr/bktr_core.h> 8162112Sroger#endif 8251694Sroger 8351694Sroger 8451694Sroger 8551694Sroger#if defined( TUNER_AFC ) 8651694Sroger#define AFC_DELAY 10000 /* 10 millisend delay */ 8751694Sroger#define AFC_BITS 0x07 8851694Sroger#define AFC_FREQ_MINUS_125 0x00 8951694Sroger#define AFC_FREQ_MINUS_62 0x01 9051694Sroger#define AFC_FREQ_CENTERED 0x02 9151694Sroger#define AFC_FREQ_PLUS_62 0x03 9251694Sroger#define AFC_FREQ_PLUS_125 0x04 9351694Sroger#define AFC_MAX_STEP (5 * FREQFACTOR) /* no more than 5 MHz */ 9451694Sroger#endif /* TUNER_AFC */ 9551694Sroger 9651694Sroger 9751694Sroger#define TTYPE_XXX 0 9851694Sroger#define TTYPE_NTSC 1 9951694Sroger#define TTYPE_NTSC_J 2 10051694Sroger#define TTYPE_PAL 3 10151694Sroger#define TTYPE_PAL_M 4 10251694Sroger#define TTYPE_PAL_N 5 10351694Sroger#define TTYPE_SECAM 6 10451694Sroger 10551694Sroger#define TSA552x_CB_MSB (0x80) 10651694Sroger#define TSA552x_CB_CP (1<<6) /* set this for fast tuning */ 10751694Sroger#define TSA552x_CB_T2 (1<<5) /* test mode - Normally set to 0 */ 10851694Sroger#define TSA552x_CB_T1 (1<<4) /* test mode - Normally set to 0 */ 10951694Sroger#define TSA552x_CB_T0 (1<<3) /* test mode - Normally set to 1 */ 11051694Sroger#define TSA552x_CB_RSA (1<<2) /* 0 for 31.25 khz, 1 for 62.5 kHz */ 11151694Sroger#define TSA552x_CB_RSB (1<<1) /* 0 for FM 50kHz steps, 1 = Use RSA*/ 11251694Sroger#define TSA552x_CB_OS (1<<0) /* Set to 0 for normal operation */ 11351694Sroger 11451694Sroger#define TSA552x_RADIO (TSA552x_CB_MSB | \ 11551694Sroger TSA552x_CB_T0) 11651694Sroger 11751694Sroger/* raise the charge pump voltage for fast tuning */ 11851694Sroger#define TSA552x_FCONTROL (TSA552x_CB_MSB | \ 11951694Sroger TSA552x_CB_CP | \ 12051694Sroger TSA552x_CB_T0 | \ 12151694Sroger TSA552x_CB_RSA | \ 12251694Sroger TSA552x_CB_RSB) 12351694Sroger 12451694Sroger/* lower the charge pump voltage for better residual oscillator FM */ 12551694Sroger#define TSA552x_SCONTROL (TSA552x_CB_MSB | \ 12651694Sroger TSA552x_CB_T0 | \ 12751694Sroger TSA552x_CB_RSA | \ 12851694Sroger TSA552x_CB_RSB) 12951694Sroger 13051694Sroger/* The control value for the ALPS TSCH5 Tuner */ 13151694Sroger#define TSCH5_FCONTROL 0x82 13251694Sroger#define TSCH5_RADIO 0x86 13351694Sroger 13451694Sroger/* The control value for the ALPS TSBH1 Tuner */ 13551694Sroger#define TSBH1_FCONTROL 0xce 13651694Sroger 13751694Sroger 138138936Sjulianstatic void mt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq); 139138936Sjulian 140138936Sjulian 14151694Srogerstatic const struct TUNER tuners[] = { 14251694Sroger/* XXX FIXME: fill in the band-switch crosspoints */ 14351694Sroger /* NO_TUNER */ 14451694Sroger { "<no>", /* the 'name' */ 14551694Sroger TTYPE_XXX, /* input type */ 14651694Sroger { 0x00, /* control byte for Tuner PLL */ 14751694Sroger 0x00, 14851694Sroger 0x00, 14951694Sroger 0x00 }, 15051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 15151694Sroger { 0x00, 0x00, 0x00,0x00} }, /* the band-switch values */ 15251694Sroger 15351694Sroger /* TEMIC_NTSC */ 15451694Sroger { "Temic NTSC", /* the 'name' */ 15551694Sroger TTYPE_NTSC, /* input type */ 15651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 15751694Sroger TSA552x_SCONTROL, 15851694Sroger TSA552x_SCONTROL, 15951694Sroger 0x00 }, 16051694Sroger { 0x00, 0x00}, /* band-switch crosspoints */ 16151694Sroger { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ 16251694Sroger 16351694Sroger /* TEMIC_PAL */ 16451694Sroger { "Temic PAL", /* the 'name' */ 16551694Sroger TTYPE_PAL, /* input type */ 16651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 16751694Sroger TSA552x_SCONTROL, 16851694Sroger TSA552x_SCONTROL, 16951694Sroger 0x00 }, 17051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 17151694Sroger { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ 17251694Sroger 17351694Sroger /* TEMIC_SECAM */ 17451694Sroger { "Temic SECAM", /* the 'name' */ 17551694Sroger TTYPE_SECAM, /* input type */ 17651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 17751694Sroger TSA552x_SCONTROL, 17851694Sroger TSA552x_SCONTROL, 17951694Sroger 0x00 }, 18051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 18151694Sroger { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ 18251694Sroger 18351694Sroger /* PHILIPS_NTSC */ 18451694Sroger { "Philips NTSC", /* the 'name' */ 18551694Sroger TTYPE_NTSC, /* input type */ 18651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 18751694Sroger TSA552x_SCONTROL, 18851694Sroger TSA552x_SCONTROL, 18951694Sroger 0x00 }, 19051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 19151694Sroger { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ 19251694Sroger 19351694Sroger /* PHILIPS_PAL */ 19451694Sroger { "Philips PAL", /* the 'name' */ 19551694Sroger TTYPE_PAL, /* input type */ 19651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 19751694Sroger TSA552x_SCONTROL, 19851694Sroger TSA552x_SCONTROL, 19951694Sroger 0x00 }, 20051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 20151694Sroger { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ 20251694Sroger 20351694Sroger /* PHILIPS_SECAM */ 20451694Sroger { "Philips SECAM", /* the 'name' */ 20551694Sroger TTYPE_SECAM, /* input type */ 20651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 20751694Sroger TSA552x_SCONTROL, 20851694Sroger TSA552x_SCONTROL, 20951694Sroger 0x00 }, 21051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 21153123Sroger { 0xa7, 0x97, 0x37, 0x00 } }, /* the band-switch values */ 21251694Sroger 21351694Sroger /* TEMIC_PAL I */ 21451694Sroger { "Temic PAL I", /* the 'name' */ 21551694Sroger TTYPE_PAL, /* input type */ 21651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 21751694Sroger TSA552x_SCONTROL, 21851694Sroger TSA552x_SCONTROL, 21951694Sroger 0x00 }, 22051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 22151694Sroger { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ 22251694Sroger 22351694Sroger /* PHILIPS_PALI */ 22451694Sroger { "Philips PAL I", /* the 'name' */ 22551694Sroger TTYPE_PAL, /* input type */ 22651694Sroger { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 22751694Sroger TSA552x_SCONTROL, 22851694Sroger TSA552x_SCONTROL, 22951694Sroger 0x00 }, 23051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 23151694Sroger { 0xa0, 0x90, 0x30,0x00 } }, /* the band-switch values */ 23251694Sroger 23351694Sroger /* PHILIPS_FR1236_NTSC */ 23451694Sroger { "Philips FR1236 NTSC FM", /* the 'name' */ 23551694Sroger TTYPE_NTSC, /* input type */ 23651694Sroger { TSA552x_FCONTROL, /* control byte for Tuner PLL */ 23751694Sroger TSA552x_FCONTROL, 23851694Sroger TSA552x_FCONTROL, 23951694Sroger TSA552x_RADIO }, 24051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 24151694Sroger { 0xa0, 0x90, 0x30,0xa4 } }, /* the band-switch values */ 24251694Sroger 24351694Sroger /* PHILIPS_FR1216_PAL */ 24451694Sroger { "Philips FR1216 PAL FM" , /* the 'name' */ 24551694Sroger TTYPE_PAL, /* input type */ 24651694Sroger { TSA552x_FCONTROL, /* control byte for Tuner PLL */ 24751694Sroger TSA552x_FCONTROL, 24851694Sroger TSA552x_FCONTROL, 24951694Sroger TSA552x_RADIO }, 25051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 25151694Sroger { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ 25251694Sroger 25351694Sroger /* PHILIPS_FR1236_SECAM */ 25451694Sroger { "Philips FR1236 SECAM FM", /* the 'name' */ 25551694Sroger TTYPE_SECAM, /* input type */ 25651694Sroger { TSA552x_FCONTROL, /* control byte for Tuner PLL */ 25751694Sroger TSA552x_FCONTROL, 25851694Sroger TSA552x_FCONTROL, 25951694Sroger TSA552x_RADIO }, 26051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 26153123Sroger { 0xa7, 0x97, 0x37, 0xa4 } }, /* the band-switch values */ 26251694Sroger 26351694Sroger /* ALPS TSCH5 NTSC */ 26451694Sroger { "ALPS TSCH5 NTSC FM", /* the 'name' */ 26551694Sroger TTYPE_NTSC, /* input type */ 26651694Sroger { TSCH5_FCONTROL, /* control byte for Tuner PLL */ 26751694Sroger TSCH5_FCONTROL, 26851694Sroger TSCH5_FCONTROL, 26951694Sroger TSCH5_RADIO }, 27051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 27151694Sroger { 0x14, 0x12, 0x11, 0x04 } }, /* the band-switch values */ 27251694Sroger 27351694Sroger /* ALPS TSBH1 NTSC */ 27451694Sroger { "ALPS TSBH1 NTSC", /* the 'name' */ 27551694Sroger TTYPE_NTSC, /* input type */ 27651694Sroger { TSBH1_FCONTROL, /* control byte for Tuner PLL */ 27751694Sroger TSBH1_FCONTROL, 27851694Sroger TSBH1_FCONTROL, 27951694Sroger 0x00 }, 28051694Sroger { 0x00, 0x00 }, /* band-switch crosspoints */ 281152375Snetchild { 0x01, 0x02, 0x08, 0x00 } }, /* the band-switch values */ 282138936Sjulian 283138936Sjulian /* MT2032 Microtune */ 284138936Sjulian { "MT2032", /* the 'name' */ 285152375Snetchild TTYPE_PAL, /* input type */ 286138936Sjulian { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 287138936Sjulian TSA552x_SCONTROL, 288138936Sjulian TSA552x_SCONTROL, 289138936Sjulian 0x00 }, 290138936Sjulian { 0x00, 0x00 }, /* band-switch crosspoints */ 291138936Sjulian { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ 292152375Snetchild 293152375Snetchild /* LG TPI8PSB12P PAL */ 294152375Snetchild { "LG TPI8PSB12P PAL", /* the 'name' */ 295152375Snetchild TTYPE_PAL, /* input type */ 296152375Snetchild { TSA552x_SCONTROL, /* control byte for Tuner PLL */ 297152375Snetchild TSA552x_SCONTROL, 298152375Snetchild TSA552x_SCONTROL, 299152375Snetchild 0x00 }, 300152375Snetchild { 0x00, 0x00 }, /* band-switch crosspoints */ 301152375Snetchild { 0xa0, 0x90, 0x30, 0x8e } }, /* the band-switch values */ 30251694Sroger}; 30351694Sroger 30451694Sroger 30551694Sroger/* scaling factor for frequencies expressed as ints */ 30651694Sroger#define FREQFACTOR 16 30751694Sroger 30851694Sroger/* 30951694Sroger * Format: 31051694Sroger * entry 0: MAX legal channel 31151694Sroger * entry 1: IF frequency 31251694Sroger * expressed as fi{mHz} * 16, 31351694Sroger * eg 45.75mHz == 45.75 * 16 = 732 31451694Sroger * entry 2: [place holder/future] 31551694Sroger * entry 3: base of channel record 0 31651694Sroger * entry 3 + (x*3): base of channel record 'x' 31751694Sroger * entry LAST: NULL channel entry marking end of records 31851694Sroger * 31951694Sroger * Record: 32051694Sroger * int 0: base channel 32151694Sroger * int 1: frequency of base channel, 32251694Sroger * expressed as fb{mHz} * 16, 32351694Sroger * int 2: offset frequency between channels, 32451694Sroger * expressed as fo{mHz} * 16, 32551694Sroger */ 32651694Sroger 32751694Sroger/* 32851694Sroger * North American Broadcast Channels: 32951694Sroger * 33051694Sroger * 2: 55.25 mHz - 4: 67.25 mHz 33151694Sroger * 5: 77.25 mHz - 6: 83.25 mHz 33251694Sroger * 7: 175.25 mHz - 13: 211.25 mHz 33351694Sroger * 14: 471.25 mHz - 83: 885.25 mHz 33451694Sroger * 33551694Sroger * IF freq: 45.75 mHz 33651694Sroger */ 33751694Sroger#define OFFSET 6.00 33851694Srogerstatic int nabcst[] = { 33951694Sroger 83, (int)( 45.75 * FREQFACTOR), 0, 34051694Sroger 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 34151694Sroger 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 34251694Sroger 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 34351694Sroger 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 34451694Sroger 0 34551694Sroger}; 34651694Sroger#undef OFFSET 34751694Sroger 34851694Sroger/* 34951694Sroger * North American Cable Channels, IRC: 35051694Sroger * 35151694Sroger * 2: 55.25 mHz - 4: 67.25 mHz 35251694Sroger * 5: 77.25 mHz - 6: 83.25 mHz 35351694Sroger * 7: 175.25 mHz - 13: 211.25 mHz 35451694Sroger * 14: 121.25 mHz - 22: 169.25 mHz 35551694Sroger * 23: 217.25 mHz - 94: 643.25 mHz 35651694Sroger * 95: 91.25 mHz - 99: 115.25 mHz 35751694Sroger * 35851694Sroger * IF freq: 45.75 mHz 35951694Sroger */ 36051694Sroger#define OFFSET 6.00 36151694Srogerstatic int irccable[] = { 36259014Sroger 116, (int)( 45.75 * FREQFACTOR), 0, 36359014Sroger 100, (int)(649.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 36451694Sroger 95, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 36551694Sroger 23, (int)(217.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 36651694Sroger 14, (int)(121.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 36751694Sroger 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 36851694Sroger 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 36951694Sroger 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 37051694Sroger 0 37151694Sroger}; 37251694Sroger#undef OFFSET 37351694Sroger 37451694Sroger/* 37551694Sroger * North American Cable Channels, HRC: 37651694Sroger * 37751694Sroger * 2: 54 mHz - 4: 66 mHz 37851694Sroger * 5: 78 mHz - 6: 84 mHz 37951694Sroger * 7: 174 mHz - 13: 210 mHz 38051694Sroger * 14: 120 mHz - 22: 168 mHz 38151694Sroger * 23: 216 mHz - 94: 642 mHz 38251694Sroger * 95: 90 mHz - 99: 114 mHz 38351694Sroger * 38451694Sroger * IF freq: 45.75 mHz 38551694Sroger */ 38651694Sroger#define OFFSET 6.00 38751694Srogerstatic int hrccable[] = { 38859014Sroger 116, (int)( 45.75 * FREQFACTOR), 0, 38959014Sroger 100, (int)(648.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39051694Sroger 95, (int)( 90.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39151694Sroger 23, (int)(216.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39251694Sroger 14, (int)(120.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39351694Sroger 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39451694Sroger 5, (int)( 78.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39551694Sroger 2, (int)( 54.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 39651694Sroger 0 39751694Sroger}; 39851694Sroger#undef OFFSET 39951694Sroger 40051694Sroger/* 40151694Sroger * Western European broadcast channels: 40251694Sroger * 40351694Sroger * (there are others that appear to vary between countries - rmt) 40451694Sroger * 40551694Sroger * here's the table Philips provides: 40651694Sroger * caution, some of the offsets don't compute... 40751694Sroger * 40851694Sroger * 1 4525 700 N21 40951694Sroger * 41051694Sroger * 2 4825 700 E2 41151694Sroger * 3 5525 700 E3 41251694Sroger * 4 6225 700 E4 41351694Sroger * 41451694Sroger * 5 17525 700 E5 41551694Sroger * 6 18225 700 E6 41651694Sroger * 7 18925 700 E7 41751694Sroger * 8 19625 700 E8 41851694Sroger * 9 20325 700 E9 41951694Sroger * 10 21025 700 E10 42051694Sroger * 11 21725 700 E11 42151694Sroger * 12 22425 700 E12 42251694Sroger * 42351694Sroger * 13 5375 700 ITA 42451694Sroger * 14 6225 700 ITB 42551694Sroger * 42651694Sroger * 15 8225 700 ITC 42751694Sroger * 42851694Sroger * 16 17525 700 ITD 42951694Sroger * 17 18325 700 ITE 43051694Sroger * 43151694Sroger * 18 19225 700 ITF 43251694Sroger * 19 20125 700 ITG 43351694Sroger * 20 21025 700 ITH 43451694Sroger * 43551694Sroger * 21 47125 800 E21 43651694Sroger * 22 47925 800 E22 43751694Sroger * 23 48725 800 E23 43851694Sroger * 24 49525 800 E24 43951694Sroger * 25 50325 800 E25 44051694Sroger * 26 51125 800 E26 44151694Sroger * 27 51925 800 E27 44251694Sroger * 28 52725 800 E28 44351694Sroger * 29 53525 800 E29 44451694Sroger * 30 54325 800 E30 44551694Sroger * 31 55125 800 E31 44651694Sroger * 32 55925 800 E32 44751694Sroger * 33 56725 800 E33 44851694Sroger * 34 57525 800 E34 44951694Sroger * 35 58325 800 E35 45051694Sroger * 36 59125 800 E36 45151694Sroger * 37 59925 800 E37 45251694Sroger * 38 60725 800 E38 45351694Sroger * 39 61525 800 E39 45451694Sroger * 40 62325 800 E40 45551694Sroger * 41 63125 800 E41 45651694Sroger * 42 63925 800 E42 45751694Sroger * 43 64725 800 E43 45851694Sroger * 44 65525 800 E44 45951694Sroger * 45 66325 800 E45 46051694Sroger * 46 67125 800 E46 46151694Sroger * 47 67925 800 E47 46251694Sroger * 48 68725 800 E48 46351694Sroger * 49 69525 800 E49 46451694Sroger * 50 70325 800 E50 46551694Sroger * 51 71125 800 E51 46651694Sroger * 52 71925 800 E52 46751694Sroger * 53 72725 800 E53 46851694Sroger * 54 73525 800 E54 46951694Sroger * 55 74325 800 E55 47051694Sroger * 56 75125 800 E56 47151694Sroger * 57 75925 800 E57 47251694Sroger * 58 76725 800 E58 47351694Sroger * 59 77525 800 E59 47451694Sroger * 60 78325 800 E60 47551694Sroger * 61 79125 800 E61 47651694Sroger * 62 79925 800 E62 47751694Sroger * 63 80725 800 E63 47851694Sroger * 64 81525 800 E64 47951694Sroger * 65 82325 800 E65 48051694Sroger * 66 83125 800 E66 48151694Sroger * 67 83925 800 E67 48251694Sroger * 68 84725 800 E68 48351694Sroger * 69 85525 800 E69 48451694Sroger * 48551694Sroger * 70 4575 800 IA 48651694Sroger * 71 5375 800 IB 48751694Sroger * 72 6175 800 IC 48851694Sroger * 48951694Sroger * 74 6925 700 S01 49051694Sroger * 75 7625 700 S02 49151694Sroger * 76 8325 700 S03 49251694Sroger * 49351694Sroger * 80 10525 700 S1 49451694Sroger * 81 11225 700 S2 49551694Sroger * 82 11925 700 S3 49651694Sroger * 83 12625 700 S4 49751694Sroger * 84 13325 700 S5 49851694Sroger * 85 14025 700 S6 49951694Sroger * 86 14725 700 S7 50051694Sroger * 87 15425 700 S8 50151694Sroger * 88 16125 700 S9 50251694Sroger * 89 16825 700 S10 50351694Sroger * 90 23125 700 S11 50451694Sroger * 91 23825 700 S12 50551694Sroger * 92 24525 700 S13 50651694Sroger * 93 25225 700 S14 50751694Sroger * 94 25925 700 S15 50851694Sroger * 95 26625 700 S16 50951694Sroger * 96 27325 700 S17 51051694Sroger * 97 28025 700 S18 51151694Sroger * 98 28725 700 S19 51251694Sroger * 99 29425 700 S20 51351694Sroger * 51451694Sroger * 51551694Sroger * Channels S21 - S41 are taken from 51651694Sroger * http://gemma.apple.com:80/dev/technotes/tn/tn1012.html 51751694Sroger * 51851694Sroger * 100 30325 800 S21 51951694Sroger * 101 31125 800 S22 52051694Sroger * 102 31925 800 S23 52151694Sroger * 103 32725 800 S24 52251694Sroger * 104 33525 800 S25 52351694Sroger * 105 34325 800 S26 52451694Sroger * 106 35125 800 S27 52551694Sroger * 107 35925 800 S28 52651694Sroger * 108 36725 800 S29 52751694Sroger * 109 37525 800 S30 52851694Sroger * 110 38325 800 S31 52951694Sroger * 111 39125 800 S32 53051694Sroger * 112 39925 800 S33 53151694Sroger * 113 40725 800 S34 53251694Sroger * 114 41525 800 S35 53351694Sroger * 115 42325 800 S36 53451694Sroger * 116 43125 800 S37 53551694Sroger * 117 43925 800 S38 53651694Sroger * 118 44725 800 S39 53751694Sroger * 119 45525 800 S40 53851694Sroger * 120 46325 800 S41 53951694Sroger * 54051694Sroger * 121 3890 000 IFFREQ 54151694Sroger * 54251694Sroger */ 54351694Srogerstatic int weurope[] = { 54451694Sroger 121, (int)( 38.90 * FREQFACTOR), 0, 54551694Sroger 100, (int)(303.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 54651694Sroger 90, (int)(231.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), 54751694Sroger 80, (int)(105.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), 54851694Sroger 74, (int)( 69.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), 54951694Sroger 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 55051694Sroger 17, (int)(183.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), 55151694Sroger 16, (int)(175.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), 55251694Sroger 15, (int)(82.25 * FREQFACTOR), (int)(8.50 * FREQFACTOR), 55351694Sroger 13, (int)(53.75 * FREQFACTOR), (int)(8.50 * FREQFACTOR), 55451694Sroger 5, (int)(175.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), 55551694Sroger 2, (int)(48.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), 55651694Sroger 0 55751694Sroger}; 55851694Sroger 55951694Sroger/* 56051694Sroger * Japanese Broadcast Channels: 56151694Sroger * 56251694Sroger * 1: 91.25MHz - 3: 103.25MHz 56351694Sroger * 4: 171.25MHz - 7: 189.25MHz 56451694Sroger * 8: 193.25MHz - 12: 217.25MHz (VHF) 56551694Sroger * 13: 471.25MHz - 62: 765.25MHz (UHF) 56651694Sroger * 56751694Sroger * IF freq: 45.75 mHz 56851694Sroger * OR 56951694Sroger * IF freq: 58.75 mHz 57051694Sroger */ 57151694Sroger#define OFFSET 6.00 57251694Sroger#define IF_FREQ 45.75 57351694Srogerstatic int jpnbcst[] = { 57451694Sroger 62, (int)(IF_FREQ * FREQFACTOR), 0, 57551694Sroger 13, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 57651694Sroger 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 57751694Sroger 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 57851694Sroger 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 57951694Sroger 0 58051694Sroger}; 58151694Sroger#undef IF_FREQ 58251694Sroger#undef OFFSET 58351694Sroger 58451694Sroger/* 58551694Sroger * Japanese Cable Channels: 58651694Sroger * 58751694Sroger * 1: 91.25MHz - 3: 103.25MHz 58851694Sroger * 4: 171.25MHz - 7: 189.25MHz 58951694Sroger * 8: 193.25MHz - 12: 217.25MHz 59051694Sroger * 13: 109.25MHz - 21: 157.25MHz 59151694Sroger * 22: 165.25MHz 59251694Sroger * 23: 223.25MHz - 63: 463.25MHz 59351694Sroger * 59451694Sroger * IF freq: 45.75 mHz 59551694Sroger */ 59651694Sroger#define OFFSET 6.00 59751694Sroger#define IF_FREQ 45.75 59851694Srogerstatic int jpncable[] = { 59951694Sroger 63, (int)(IF_FREQ * FREQFACTOR), 0, 60051694Sroger 23, (int)(223.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 60151694Sroger 22, (int)(165.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 60251694Sroger 13, (int)(109.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 60351694Sroger 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 60451694Sroger 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 60551694Sroger 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 60651694Sroger 0 60751694Sroger}; 60851694Sroger#undef IF_FREQ 60951694Sroger#undef OFFSET 61051694Sroger 61151694Sroger/* 61251694Sroger * xUSSR Broadcast Channels: 61351694Sroger * 61451694Sroger * 1: 49.75MHz - 2: 59.25MHz 61551694Sroger * 3: 77.25MHz - 5: 93.25MHz 61651694Sroger * 6: 175.25MHz - 12: 223.25MHz 61751694Sroger * 13-20 - not exist 61851694Sroger * 21: 471.25MHz - 34: 575.25MHz 61951694Sroger * 35: 583.25MHz - 69: 855.25MHz 62051694Sroger * 62151694Sroger * Cable channels 62251694Sroger * 62351694Sroger * 70: 111.25MHz - 77: 167.25MHz 62451694Sroger * 78: 231.25MHz -107: 463.25MHz 62551694Sroger * 62651694Sroger * IF freq: 38.90 MHz 62751694Sroger */ 62851694Sroger#define IF_FREQ 38.90 62951694Srogerstatic int xussr[] = { 63051694Sroger 107, (int)(IF_FREQ * FREQFACTOR), 0, 63151694Sroger 78, (int)(231.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 63251694Sroger 70, (int)(111.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 63351694Sroger 35, (int)(583.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 63451694Sroger 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 63551694Sroger 6, (int)(175.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 63651694Sroger 3, (int)( 77.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), 63751694Sroger 1, (int)( 49.75 * FREQFACTOR), (int)(9.50 * FREQFACTOR), 63851694Sroger 0 63951694Sroger}; 64051694Sroger#undef IF_FREQ 64151694Sroger 64251694Sroger/* 64351694Sroger * Australian broadcast channels 64451694Sroger */ 64551694Sroger#define OFFSET 7.00 64656531Sroger#define IF_FREQ 38.90 64751694Srogerstatic int australia[] = { 64856531Sroger 83, (int)(IF_FREQ * FREQFACTOR), 0, 64956531Sroger 28, (int)(527.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 65056531Sroger 10, (int)(209.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 65156531Sroger 6, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 65256531Sroger 4, (int)( 95.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 65356531Sroger 3, (int)( 86.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 65456531Sroger 1, (int)( 57.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), 65556531Sroger 0 65651694Sroger}; 65751694Sroger#undef OFFSET 65856531Sroger#undef IF_FREQ 65951694Sroger 66056531Sroger/* 66156531Sroger * France broadcast channels 66256531Sroger */ 66356531Sroger#define OFFSET 8.00 66456531Sroger#define IF_FREQ 38.90 66556531Srogerstatic int france[] = { 66656531Sroger 69, (int)(IF_FREQ * FREQFACTOR), 0, 66756531Sroger 21, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 21 -> 69 */ 66856531Sroger 5, (int)(176.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 5 -> 10 */ 66956531Sroger 4, (int)( 63.75 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 4 */ 67056531Sroger 3, (int)( 60.50 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 3 */ 67156531Sroger 1, (int)( 47.75 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 1 2 */ 67256531Sroger 0 67356531Sroger}; 67456531Sroger#undef OFFSET 67556531Sroger#undef IF_FREQ 67656531Sroger 67751694Srogerstatic struct { 67851694Sroger int *ptr; 67951694Sroger char name[BT848_MAX_CHNLSET_NAME_LEN]; 68051694Sroger} freqTable[] = { 68151694Sroger {NULL, ""}, 68251694Sroger {nabcst, "nabcst"}, 68351694Sroger {irccable, "cableirc"}, 68451694Sroger {hrccable, "cablehrc"}, 68551694Sroger {weurope, "weurope"}, 68651694Sroger {jpnbcst, "jpnbcst"}, 68751694Sroger {jpncable, "jpncable"}, 68851694Sroger {xussr, "xussr"}, 68951694Sroger {australia, "australia"}, 69056531Sroger {france, "france"}, 69151694Sroger 69251694Sroger}; 69351694Sroger 69451694Sroger#define TBL_CHNL freqTable[ bktr->tuner.chnlset ].ptr[ x ] 69551694Sroger#define TBL_BASE_FREQ freqTable[ bktr->tuner.chnlset ].ptr[ x + 1 ] 69651694Sroger#define TBL_OFFSET freqTable[ bktr->tuner.chnlset ].ptr[ x + 2 ] 69751694Srogerstatic int 69851694Srogerfrequency_lookup( bktr_ptr_t bktr, int channel ) 69951694Sroger{ 70051694Sroger int x; 70151694Sroger 70251694Sroger /* check for "> MAX channel" */ 70351694Sroger x = 0; 70451694Sroger if ( channel > TBL_CHNL ) 70551694Sroger return( -1 ); 70651694Sroger 70751694Sroger /* search the table for data */ 70851694Sroger for ( x = 3; TBL_CHNL; x += 3 ) { 70951694Sroger if ( channel >= TBL_CHNL ) { 71051694Sroger return( TBL_BASE_FREQ + 71151694Sroger ((channel - TBL_CHNL) * TBL_OFFSET) ); 71251694Sroger } 71351694Sroger } 71451694Sroger 71551694Sroger /* not found, must be below the MIN channel */ 71651694Sroger return( -1 ); 71751694Sroger} 71851694Sroger#undef TBL_OFFSET 71951694Sroger#undef TBL_BASE_FREQ 72051694Sroger#undef TBL_CHNL 72151694Sroger 72251694Sroger 723131180Sschweikh#define TBL_IF (bktr->format_params == BT848_IFORM_F_NTSCJ || \ 724131180Sschweikh bktr->format_params == BT848_IFORM_F_NTSCM ? \ 725131180Sschweikh nabcst[1] : weurope[1]) 72651694Sroger 72751694Sroger 72851694Sroger/* Initialise the tuner structures in the bktr_softc */ 72951694Sroger/* This is needed as the tuner details are no longer globally declared */ 73051694Sroger 73151694Srogervoid select_tuner( bktr_ptr_t bktr, int tuner_type ) { 73251694Sroger if (tuner_type < Bt848_MAX_TUNER) { 73351694Sroger bktr->card.tuner = &tuners[ tuner_type ]; 73451694Sroger } else { 73551694Sroger bktr->card.tuner = NULL; 73651694Sroger } 73751694Sroger} 73851694Sroger 73951694Sroger/* 74051694Sroger * Tuner Notes: 74151694Sroger * Programming the tuner properly is quite complicated. 74251694Sroger * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner. 74351694Sroger * The tuner (front end) covers 45.75 Mhz - 855.25 Mhz and an FM band of 74451694Sroger * 87.5 Mhz to 108.0 Mhz. 74551694Sroger * 74651694Sroger * RF and IF. RF = radio frequencies, it is the transmitted signal. 74751694Sroger * IF is the Intermediate Frequency (the offset from the base 74851694Sroger * signal where the video, color, audio and NICAM signals are. 74951694Sroger * 75051694Sroger * Eg, Picture at 38.9 Mhz, Colour at 34.47 MHz, sound at 32.9 MHz 75151694Sroger * NICAM at 32.348 Mhz. 75251694Sroger * Strangely enough, there is an IF (intermediate frequency) for 75351694Sroger * FM Radio which is 10.7 Mhz. 75451694Sroger * 75551694Sroger * The tuner also works in Bands. Philips bands are 75651694Sroger * FM radio band 87.50 to 108.00 MHz 75751694Sroger * Low band 45.75 to 170.00 MHz 75851694Sroger * Mid band 170.00 to 450.00 MHz 75951694Sroger * High band 450.00 to 855.25 MHz 76051694Sroger * 76151694Sroger * 76251694Sroger * Now we need to set the PLL on the tuner to the required freuqncy. 76351694Sroger * It has a programmable divisor. 76451694Sroger * For TV we want 76551694Sroger * N = 16 (freq RF(pc) + freq IF(pc)) pc is picture carrier and RF and IF 76651694Sroger * are in MHz. 76751694Sroger 76851694Sroger * For RADIO we want a different equation. 76951694Sroger * freq IF is 10.70 MHz (so the data sheet tells me) 77051694Sroger * N = (freq RF + freq IF) / step size 77151694Sroger * The step size must be set to 50 khz (so the data sheet tells me) 77251694Sroger * (note this is 50 kHz, the other things are in MHz) 77351694Sroger * so we end up with N = 20x(freq RF + 10.7) 77451694Sroger * 77551694Sroger */ 77651694Sroger 77751694Sroger#define LOW_BAND 0 77851694Sroger#define MID_BAND 1 77951694Sroger#define HIGH_BAND 2 78051694Sroger#define FM_RADIO_BAND 3 78151694Sroger 78251694Sroger 78351694Sroger/* Check if these are correct for other than Philips PAL */ 78451694Sroger#define STATUSBIT_COLD 0x80 78551694Sroger#define STATUSBIT_LOCK 0x40 78651694Sroger#define STATUSBIT_TV 0x20 78751694Sroger#define STATUSBIT_STEREO 0x10 /* valid if FM (aka not TV) */ 78851694Sroger#define STATUSBIT_ADC 0x07 78951694Sroger 79051694Sroger/* 79151694Sroger * set the frequency of the tuner 79251694Sroger * If 'type' is TV_FREQUENCY, the frequency is freq MHz*16 79351694Sroger * If 'type' is FM_RADIO_FREQUENCY, the frequency is freq MHz * 100 79451694Sroger * (note *16 gives is 4 bits of fraction, eg steps of nnn.0625) 79551694Sroger * 79651694Sroger */ 79751694Srogerint 79851694Srogertv_freq( bktr_ptr_t bktr, int frequency, int type ) 79951694Sroger{ 80051694Sroger const struct TUNER* tuner; 80151694Sroger u_char addr; 80251694Sroger u_char control; 80351694Sroger u_char band; 80451694Sroger int N; 80551694Sroger int band_select = 0; 80651925Sroger#if defined( TEST_TUNER_AFC ) 80751925Sroger int oldFrequency, afcDelta; 80851925Sroger#endif 80951694Sroger 81051694Sroger tuner = bktr->card.tuner; 81151694Sroger if ( tuner == NULL ) 81251694Sroger return( -1 ); 81351694Sroger 814138936Sjulian if (tuner == &tuners[TUNER_MT2032]) { 815138936Sjulian mt2032_set_tv_freq(bktr, frequency); 816138936Sjulian return 0; 817138936Sjulian } 81851694Sroger if (type == TV_FREQUENCY) { 81951694Sroger /* 82051694Sroger * select the band based on frequency 82151694Sroger * XXX FIXME: get the cross-over points from the tuner struct 82251694Sroger */ 82351694Sroger if ( frequency < (160 * FREQFACTOR ) ) 82451694Sroger band_select = LOW_BAND; 82551694Sroger else if ( frequency < (454 * FREQFACTOR ) ) 82651694Sroger band_select = MID_BAND; 82751694Sroger else 82851694Sroger band_select = HIGH_BAND; 82951694Sroger 83051694Sroger#if defined( TEST_TUNER_AFC ) 83151694Sroger if ( bktr->tuner.afc ) 83251694Sroger frequency -= 4; 83351694Sroger#endif 83451694Sroger /* 83551694Sroger * N = 16 * { fRF(pc) + fIF(pc) } 83651694Sroger * or N = 16* fRF(pc) + 16*fIF(pc) } 83751694Sroger * where: 83851694Sroger * pc is picture carrier, fRF & fIF are in MHz 83951694Sroger * 84051694Sroger * fortunatly, frequency is passed in as MHz * 16 84151694Sroger * and the TBL_IF frequency is also stored in MHz * 16 84251694Sroger */ 84351694Sroger N = frequency + TBL_IF; 84451694Sroger 84551694Sroger /* set the address of the PLL */ 84651694Sroger addr = bktr->card.tuner_pllAddr; 84751694Sroger control = tuner->pllControl[ band_select ]; 84851694Sroger band = tuner->bandAddrs[ band_select ]; 84951694Sroger 85051694Sroger if(!(band && control)) /* Don't try to set un- */ 85151694Sroger return(-1); /* supported modes. */ 85251694Sroger 85351694Sroger if ( frequency > bktr->tuner.frequency ) { 85451694Sroger i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); 85551694Sroger i2cWrite( bktr, addr, control, band ); 85651694Sroger } 85751694Sroger else { 85851694Sroger i2cWrite( bktr, addr, control, band ); 85951694Sroger i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); 86051694Sroger } 86151694Sroger 86251694Sroger#if defined( TUNER_AFC ) 86351694Sroger if ( bktr->tuner.afc == TRUE ) { 86451925Sroger#if defined( TEST_TUNER_AFC ) 86551925Sroger oldFrequency = frequency; 86651925Sroger#endif 86751694Sroger if ( (N = do_afc( bktr, addr, N )) < 0 ) { 86851694Sroger /* AFC failed, restore requested frequency */ 86951694Sroger N = frequency + TBL_IF; 87051925Sroger#if defined( TEST_TUNER_AFC ) 87162112Sroger printf("%s: do_afc: failed to lock\n", 87262112Sroger bktr_name(bktr)); 87351925Sroger#endif 87451694Sroger i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); 87551694Sroger } 87651694Sroger else 87751694Sroger frequency = N - TBL_IF; 87851925Sroger#if defined( TEST_TUNER_AFC ) 87962112Sroger printf("%s: do_afc: returned freq %d (%d %% %d)\n", bktr_name(bktr), frequency, frequency / 16, frequency % 16); 88051925Sroger afcDelta = frequency - oldFrequency; 88162112Sroger printf("%s: changed by: %d clicks (%d mod %d)\n", bktr_name(bktr), afcDelta, afcDelta / 16, afcDelta % 16); 88251925Sroger#endif 88351694Sroger } 88451694Sroger#endif /* TUNER_AFC */ 88551694Sroger 88651694Sroger bktr->tuner.frequency = frequency; 88751694Sroger } 88851694Sroger 88951694Sroger if ( type == FM_RADIO_FREQUENCY ) { 89051694Sroger band_select = FM_RADIO_BAND; 89151694Sroger 89251694Sroger /* 89351694Sroger * N = { fRF(pc) + fIF(pc) }/step_size 89451694Sroger * The step size is 50kHz for FM radio. 89551694Sroger * (eg after 102.35MHz comes 102.40 MHz) 89651694Sroger * fIF is 10.7 MHz (as detailed in the specs) 89751694Sroger * 89851694Sroger * frequency is passed in as MHz * 100 89951694Sroger * 90051694Sroger * So, we have N = (frequency/100 + 10.70) /(50/1000) 90151694Sroger */ 90251694Sroger N = (frequency + 1070)/5; 90351694Sroger 90451694Sroger /* set the address of the PLL */ 90551694Sroger addr = bktr->card.tuner_pllAddr; 90651694Sroger control = tuner->pllControl[ band_select ]; 90751694Sroger band = tuner->bandAddrs[ band_select ]; 90851694Sroger 90951694Sroger if(!(band && control)) /* Don't try to set un- */ 91051694Sroger return(-1); /* supported modes. */ 91151694Sroger 91251943Sroger band |= bktr->tuner.radio_mode; /* tuner.radio_mode is set in 91351694Sroger * the ioctls RADIO_SETMODE 91451694Sroger * and RADIO_GETMODE */ 91551694Sroger 91651694Sroger i2cWrite( bktr, addr, control, band ); 91751694Sroger i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff ); 91851694Sroger 91951694Sroger bktr->tuner.frequency = (N * 5) - 1070; 92051694Sroger 92151694Sroger 92251694Sroger } 92351694Sroger 92451694Sroger 92551694Sroger return( 0 ); 92651694Sroger} 92751694Sroger 92851694Sroger 92951694Sroger 93051694Sroger#if defined( TUNER_AFC ) 93151694Sroger/* 93251694Sroger * 93351694Sroger */ 93451694Srogerint 93551694Srogerdo_afc( bktr_ptr_t bktr, int addr, int frequency ) 93651694Sroger{ 93751694Sroger int step; 93851694Sroger int status; 93951694Sroger int origFrequency; 94051694Sroger 94151694Sroger origFrequency = frequency; 94251694Sroger 94351694Sroger /* wait for first setting to take effect */ 94451694Sroger tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 ); 94551694Sroger 94651694Sroger if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) 94751694Sroger return( -1 ); 94851694Sroger 94951694Sroger#if defined( TEST_TUNER_AFC ) 95062112Sroger printf( "%s: Original freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); 95151694Sroger#endif 95251694Sroger for ( step = 0; step < AFC_MAX_STEP; ++step ) { 95351694Sroger if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) 95451694Sroger goto fubar; 95551694Sroger if ( !(status & 0x40) ) { 95651694Sroger#if defined( TEST_TUNER_AFC ) 95762112Sroger printf( "%s: no lock!\n", bktr_name(bktr) ); 95851694Sroger#endif 95951694Sroger goto fubar; 96051694Sroger } 96151694Sroger 96251694Sroger switch( status & AFC_BITS ) { 96351694Sroger case AFC_FREQ_CENTERED: 96451694Sroger#if defined( TEST_TUNER_AFC ) 96562112Sroger printf( "%s: Centered, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); 96651694Sroger#endif 96751694Sroger return( frequency ); 96851694Sroger 96951694Sroger case AFC_FREQ_MINUS_125: 97051694Sroger case AFC_FREQ_MINUS_62: 97151694Sroger#if defined( TEST_TUNER_AFC ) 97262112Sroger printf( "%s: Low, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); 97351694Sroger#endif 97451694Sroger --frequency; 97551694Sroger break; 97651694Sroger 97751694Sroger case AFC_FREQ_PLUS_62: 97851694Sroger case AFC_FREQ_PLUS_125: 97951694Sroger#if defined( TEST_TUNER_AFC ) 98062112Sroger printf( "%s: Hi, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); 98151694Sroger#endif 98251694Sroger ++frequency; 98351694Sroger break; 98451694Sroger } 98551694Sroger 98651694Sroger i2cWrite( bktr, addr, 98751694Sroger (frequency>>8) & 0x7f, frequency & 0xff ); 98851694Sroger DELAY( AFC_DELAY ); 98951694Sroger } 99051694Sroger 99151694Sroger fubar: 99251694Sroger i2cWrite( bktr, addr, 99351694Sroger (origFrequency>>8) & 0x7f, origFrequency & 0xff ); 99451694Sroger 99551694Sroger return( -1 ); 99651694Sroger} 99751694Sroger#endif /* TUNER_AFC */ 99851694Sroger#undef TBL_IF 99951694Sroger 100051694Sroger 100151694Sroger/* 100251694Sroger * Get the Tuner status and signal strength 100351694Sroger */ 100451694Srogerint get_tuner_status( bktr_ptr_t bktr ) { 1005138936Sjulian if (bktr->card.tuner == &tuners[TUNER_MT2032]) 1006138936Sjulian return 0; 100751694Sroger return i2cRead( bktr, bktr->card.tuner_pllAddr + 1 ); 100851694Sroger} 100951694Sroger 101051694Sroger/* 101151694Sroger * set the channel of the tuner 101251694Sroger */ 101351694Srogerint 101451694Srogertv_channel( bktr_ptr_t bktr, int channel ) 101551694Sroger{ 101651694Sroger int frequency; 101751694Sroger 101851694Sroger /* calculate the frequency according to tuner type */ 101951694Sroger if ( (frequency = frequency_lookup( bktr, channel )) < 0 ) 102051694Sroger return( -1 ); 102151694Sroger 102251694Sroger /* set the new frequency */ 102351694Sroger if ( tv_freq( bktr, frequency, TV_FREQUENCY ) < 0 ) 102451694Sroger return( -1 ); 102551694Sroger 102651694Sroger /* OK to update records */ 102751694Sroger return( (bktr->tuner.channel = channel) ); 102851694Sroger} 102951694Sroger 103051694Sroger/* 103151694Sroger * get channelset name 103251694Sroger */ 103351694Srogerint 103451694Srogertuner_getchnlset(struct bktr_chnlset *chnlset) 103551694Sroger{ 103651694Sroger if (( chnlset->index < CHNLSET_MIN ) || 103751694Sroger ( chnlset->index > CHNLSET_MAX )) 103851694Sroger return( EINVAL ); 103951694Sroger 104051694Sroger memcpy(&chnlset->name, &freqTable[chnlset->index].name, 104151694Sroger BT848_MAX_CHNLSET_NAME_LEN); 104251694Sroger 104351694Sroger chnlset->max_channel=freqTable[chnlset->index].ptr[0]; 104451694Sroger return( 0 ); 104551694Sroger} 1046138936Sjulian 1047138936Sjulian 1048138936Sjulian 1049138936Sjulian 1050138936Sjulian#define TDA9887_ADDR 0x86 1051138936Sjulian 1052140655Sjulianstatic int 1053138936SjulianTDA9887_init(bktr_ptr_t bktr, int output2_enable) 1054138936Sjulian{ 1055138936Sjulian u_char addr = TDA9887_ADDR; 1056138936Sjulian 1057140655Sjulian i2cWrite(bktr, addr, 0, output2_enable ? 0x50 : 0xd0); 1058140655Sjulian i2cWrite(bktr, addr, 1, 0x6e); /* takeover point / de-emphasis */ 1059138936Sjulian 1060140655Sjulian /* PAL BG: 0x09 PAL I: 0x0a NTSC: 0x04 */ 1061140655Sjulian#ifdef MT2032_NTSC 1062140655Sjulian i2cWrite(bktr, addr, 2, 0x04); 1063138936Sjulian#else 1064138936Sjulian i2cWrite(bktr, addr, 2, 0x09); 1065138936Sjulian#endif 1066138936Sjulian return 0; 1067138936Sjulian} 1068138936Sjulian 1069138936Sjulian 1070138936Sjulian 1071138936Sjulian#define MT2032_OPTIMIZE_VCO 1 1072138936Sjulian 1073138936Sjulian/* holds the value of XOGC register after init */ 1074138936Sjulianstatic int MT2032_XOGC = 4; 1075138936Sjulian 1076138936Sjulian/* card.tuner_pllAddr not set during init */ 1077138936Sjulian#define MT2032_ADDR 0xc0 1078138936Sjulian 1079138936Sjulian#ifndef MT2032_ADDR 1080138936Sjulian#define MT2032_ADDR (bktr->card.tuner_pllAddr) 1081138936Sjulian#endif 1082138936Sjulian 1083140655Sjulianstatic int 1084138936Sjulian_MT2032_GetRegister(bktr_ptr_t bktr, u_char regNum) 1085138936Sjulian{ 1086138936Sjulian int ch; 1087138936Sjulian 1088138936Sjulian if (i2cWrite(bktr, MT2032_ADDR, regNum, -1) == -1) { 1089140655Sjulian if (bootverbose) 1090140655Sjulian printf("%s: MT2032 write failed (i2c addr %#x)\n", 1091140655Sjulian bktr_name(bktr), MT2032_ADDR); 1092140655Sjulian return -1; 1093138936Sjulian } 1094138936Sjulian if ((ch = i2cRead(bktr, MT2032_ADDR + 1)) == -1) { 1095140655Sjulian if (bootverbose) 1096140655Sjulian printf("%s: MT2032 get register %d failed\n", 1097140655Sjulian bktr_name(bktr), regNum); 1098140655Sjulian return -1; 1099138936Sjulian } 1100138936Sjulian return ch; 1101138936Sjulian} 1102138936Sjulian 1103138936Sjulianstatic void 1104138936Sjulian_MT2032_SetRegister(bktr_ptr_t bktr, u_char regNum, u_char data) 1105138936Sjulian{ 1106138936Sjulian i2cWrite(bktr, MT2032_ADDR, regNum, data); 1107138936Sjulian} 1108138936Sjulian 1109138936Sjulian#define MT2032_GetRegister(r) _MT2032_GetRegister(bktr,r) 1110138936Sjulian#define MT2032_SetRegister(r,d) _MT2032_SetRegister(bktr,r,d) 1111138936Sjulian 1112138936Sjulian 1113140655Sjulianint 1114138936Sjulianmt2032_init(bktr_ptr_t bktr) 1115138936Sjulian{ 1116138936Sjulian u_char rdbuf[22]; 1117138936Sjulian int xogc, xok = 0; 1118138936Sjulian int i; 1119140655Sjulian int x; 1120138936Sjulian 1121138936Sjulian TDA9887_init(bktr, 0); 1122138936Sjulian 1123140655Sjulian for (i = 0; i < 21; i++) { 1124140655Sjulian if ((x = MT2032_GetRegister(i)) == -1) 1125140655Sjulian break; 1126140655Sjulian rdbuf[i] = x; 1127140655Sjulian } 1128140655Sjulian if (i < 21) 1129140655Sjulian return -1; 1130138936Sjulian 1131138936Sjulian printf("%s: MT2032: Companycode=%02x%02x Part=%02x Revision=%02x\n", 1132138936Sjulian bktr_name(bktr), 1133138936Sjulian rdbuf[0x11], rdbuf[0x12], rdbuf[0x13], rdbuf[0x14]); 1134140655Sjulian if (rdbuf[0x13] != 4) { 1135140655Sjulian printf("%s: MT2032 not found or unknown type\n", bktr_name(bktr)); 1136140655Sjulian return -1; 1137140655Sjulian } 1138138936Sjulian 1139138936Sjulian /* Initialize Registers per spec. */ 1140138936Sjulian MT2032_SetRegister(2, 0xff); 1141138936Sjulian MT2032_SetRegister(3, 0x0f); 1142138936Sjulian MT2032_SetRegister(4, 0x1f); 1143138936Sjulian MT2032_SetRegister(6, 0xe4); 1144138936Sjulian MT2032_SetRegister(7, 0x8f); 1145138936Sjulian MT2032_SetRegister(8, 0xc3); 1146138936Sjulian MT2032_SetRegister(9, 0x4e); 1147138936Sjulian MT2032_SetRegister(10, 0xec); 1148138936Sjulian MT2032_SetRegister(13, 0x32); 1149138936Sjulian 1150138936Sjulian /* Adjust XOGC (register 7), wait for XOK */ 1151138936Sjulian xogc = 7; 1152138936Sjulian do { 1153138936Sjulian DELAY(10000); 1154138936Sjulian xok = MT2032_GetRegister(0x0e) & 0x01; 1155138936Sjulian if (xok == 1) { 1156138936Sjulian break; 1157138936Sjulian } 1158138936Sjulian xogc--; 1159138936Sjulian if (xogc == 3) { 1160138936Sjulian xogc = 4; /* min. 4 per spec */ 1161138936Sjulian break; 1162138936Sjulian } 1163138936Sjulian MT2032_SetRegister(7, 0x88 + xogc); 1164138936Sjulian } while (xok != 1); 1165138936Sjulian 1166138936Sjulian TDA9887_init(bktr, 1); 1167138936Sjulian 1168138936Sjulian MT2032_XOGC = xogc; 1169138936Sjulian 1170138936Sjulian return 0; 1171138936Sjulian} 1172138936Sjulian 1173138936Sjulianstatic int 1174138936SjulianMT2032_SpurCheck(int f1, int f2, int spectrum_from, int spectrum_to) 1175138936Sjulian{ 1176138936Sjulian int n1 = 1, n2, f; 1177138936Sjulian 1178138936Sjulian f1 = f1 / 1000; /* scale to kHz to avoid 32bit overflows */ 1179138936Sjulian f2 = f2 / 1000; 1180138936Sjulian spectrum_from /= 1000; 1181138936Sjulian spectrum_to /= 1000; 1182138936Sjulian 1183138936Sjulian do { 1184138936Sjulian n2 = -n1; 1185138936Sjulian f = n1 * (f1 - f2); 1186138936Sjulian do { 1187138936Sjulian n2--; 1188138936Sjulian f = f - f2; 1189138936Sjulian if ((f > spectrum_from) && (f < spectrum_to)) { 1190138936Sjulian return 1; 1191138936Sjulian } 1192138936Sjulian } while ((f > (f2 - spectrum_to)) || (n2 > -5)); 1193138936Sjulian n1++; 1194138936Sjulian } while (n1 < 5); 1195138936Sjulian 1196138936Sjulian return 0; 1197138936Sjulian} 1198138936Sjulian 1199138936Sjulianstatic int 1200138936SjulianMT2032_ComputeFreq( 1201138936Sjulian int rfin, 1202138936Sjulian int if1, 1203138936Sjulian int if2, 1204138936Sjulian int spectrum_from, 1205138936Sjulian int spectrum_to, 1206138936Sjulian unsigned char *buf, 1207138936Sjulian int *ret_sel, 1208138936Sjulian int xogc 1209138936Sjulian) 1210138936Sjulian{ /* all in Hz */ 1211138936Sjulian int fref, lo1, lo1n, lo1a, s, sel; 1212138936Sjulian int lo1freq, desired_lo1, desired_lo2, lo2, lo2n, lo2a, 1213138936Sjulian lo2num, lo2freq; 1214138936Sjulian int nLO1adjust; 1215138936Sjulian 1216138936Sjulian fref = 5250 * 1000; /* 5.25MHz */ 1217138936Sjulian 1218138936Sjulian /* per spec 2.3.1 */ 1219138936Sjulian desired_lo1 = rfin + if1; 1220138936Sjulian lo1 = (2 * (desired_lo1 / 1000) + (fref / 1000)) / (2 * fref / 1000); 1221138936Sjulian lo1freq = lo1 * fref; 1222138936Sjulian desired_lo2 = lo1freq - rfin - if2; 1223138936Sjulian 1224138936Sjulian /* per spec 2.3.2 */ 1225138936Sjulian for (nLO1adjust = 1; nLO1adjust < 3; nLO1adjust++) { 1226138936Sjulian if (!MT2032_SpurCheck(lo1freq, desired_lo2, spectrum_from, spectrum_to)) { 1227138936Sjulian break; 1228138936Sjulian } 1229138936Sjulian if (lo1freq < desired_lo1) { 1230138936Sjulian lo1 += nLO1adjust; 1231138936Sjulian } else { 1232138936Sjulian lo1 -= nLO1adjust; 1233138936Sjulian } 1234138936Sjulian 1235138936Sjulian lo1freq = lo1 * fref; 1236138936Sjulian desired_lo2 = lo1freq - rfin - if2; 1237138936Sjulian } 1238138936Sjulian 1239138936Sjulian /* per spec 2.3.3 */ 1240138936Sjulian s = lo1freq / 1000 / 1000; 1241138936Sjulian 1242138936Sjulian if (MT2032_OPTIMIZE_VCO) { 1243138936Sjulian if (s > 1890) { 1244138936Sjulian sel = 0; 1245138936Sjulian } else if (s > 1720) { 1246138936Sjulian sel = 1; 1247138936Sjulian } else if (s > 1530) { 1248138936Sjulian sel = 2; 1249138936Sjulian } else if (s > 1370) { 1250138936Sjulian sel = 3; 1251138936Sjulian } else { 1252138936Sjulian sel = 4;/* >1090 */ 1253138936Sjulian } 1254138936Sjulian } else { 1255138936Sjulian if (s > 1790) { 1256138936Sjulian sel = 0;/* <1958 */ 1257138936Sjulian } else if (s > 1617) { 1258138936Sjulian sel = 1; 1259138936Sjulian } else if (s > 1449) { 1260138936Sjulian sel = 2; 1261138936Sjulian } else if (s > 1291) { 1262138936Sjulian sel = 3; 1263138936Sjulian } else { 1264138936Sjulian sel = 4;/* >1090 */ 1265138936Sjulian } 1266138936Sjulian } 1267138936Sjulian 1268138936Sjulian *ret_sel = sel; 1269138936Sjulian 1270138936Sjulian /* per spec 2.3.4 */ 1271138936Sjulian lo1n = lo1 / 8; 1272138936Sjulian lo1a = lo1 - (lo1n * 8); 1273138936Sjulian lo2 = desired_lo2 / fref; 1274138936Sjulian lo2n = lo2 / 8; 1275138936Sjulian lo2a = lo2 - (lo2n * 8); 1276138936Sjulian /* scale to fit in 32bit arith */ 1277138936Sjulian lo2num = ((desired_lo2 / 1000) % (fref / 1000)) * 3780 / (fref / 1000); 1278138936Sjulian lo2freq = (lo2a + 8 * lo2n) * fref + lo2num * (fref / 1000) / 3780 * 1000; 1279138936Sjulian 1280138936Sjulian if (lo1a < 0 || lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a < 0 || 1281138936Sjulian lo2a > 7 || lo2n < 17 || lo2n > 30) { 1282138936Sjulian printf("MT2032: parameter out of range\n"); 1283138936Sjulian return -1; 1284138936Sjulian } 1285138936Sjulian /* set up MT2032 register map for transfer over i2c */ 1286138936Sjulian buf[0] = lo1n - 1; 1287138936Sjulian buf[1] = lo1a | (sel << 4); 1288138936Sjulian buf[2] = 0x86; /* LOGC */ 1289138936Sjulian buf[3] = 0x0f; /* reserved */ 1290138936Sjulian buf[4] = 0x1f; 1291138936Sjulian buf[5] = (lo2n - 1) | (lo2a << 5); 1292138936Sjulian if (rfin < 400 * 1000 * 1000) { 1293138936Sjulian buf[6] = 0xe4; 1294138936Sjulian } else { 1295138936Sjulian buf[6] = 0xf4; /* set PKEN per rev 1.2 */ 1296138936Sjulian } 1297138936Sjulian 1298138936Sjulian buf[7] = 8 + xogc; 1299138936Sjulian buf[8] = 0xc3; /* reserved */ 1300138936Sjulian buf[9] = 0x4e; /* reserved */ 1301138936Sjulian buf[10] = 0xec; /* reserved */ 1302138936Sjulian buf[11] = (lo2num & 0xff); 1303138936Sjulian buf[12] = (lo2num >> 8) | 0x80; /* Lo2RST */ 1304138936Sjulian 1305138936Sjulian return 0; 1306138936Sjulian} 1307138936Sjulian 1308138936Sjulianstatic int 1309138936SjulianMT2032_CheckLOLock(bktr_ptr_t bktr) 1310138936Sjulian{ 1311138936Sjulian int t, lock = 0; 1312138936Sjulian for (t = 0; t < 10; t++) { 1313138936Sjulian lock = MT2032_GetRegister(0x0e) & 0x06; 1314138936Sjulian if (lock == 6) { 1315138936Sjulian break; 1316138936Sjulian } 1317138936Sjulian DELAY(1000); 1318138936Sjulian } 1319138936Sjulian return lock; 1320138936Sjulian} 1321138936Sjulian 1322138936Sjulianstatic int 1323138936SjulianMT2032_OptimizeVCO(bktr_ptr_t bktr, int sel, int lock) 1324138936Sjulian{ 1325138936Sjulian int tad1, lo1a; 1326138936Sjulian 1327138936Sjulian tad1 = MT2032_GetRegister(0x0f) & 0x07; 1328138936Sjulian 1329138936Sjulian if (tad1 == 0) { 1330138936Sjulian return lock; 1331138936Sjulian } 1332138936Sjulian if (tad1 == 1) { 1333138936Sjulian return lock; 1334138936Sjulian } 1335138936Sjulian if (tad1 == 2) { 1336138936Sjulian if (sel == 0) { 1337138936Sjulian return lock; 1338138936Sjulian } else { 1339138936Sjulian sel--; 1340138936Sjulian } 1341138936Sjulian } else { 1342138936Sjulian if (sel < 4) { 1343138936Sjulian sel++; 1344138936Sjulian } else { 1345138936Sjulian return lock; 1346138936Sjulian } 1347138936Sjulian } 1348138936Sjulian lo1a = MT2032_GetRegister(0x01) & 0x07; 1349138936Sjulian MT2032_SetRegister(0x01, lo1a | (sel << 4)); 1350138936Sjulian lock = MT2032_CheckLOLock(bktr); 1351138936Sjulian return lock; 1352138936Sjulian} 1353138936Sjulian 1354138936Sjulianstatic int 1355138936SjulianMT2032_SetIFFreq(bktr_ptr_t bktr, int rfin, int if1, int if2, int from, int to) 1356138936Sjulian{ 1357138936Sjulian u_char buf[21]; 1358138936Sjulian int lint_try, sel, lock = 0; 1359138936Sjulian 1360138936Sjulian if (MT2032_ComputeFreq(rfin, if1, if2, from, to, &buf[0], &sel, MT2032_XOGC) == -1) 1361138936Sjulian return -1; 1362138936Sjulian 1363138936Sjulian TDA9887_init(bktr, 0); 1364138936Sjulian 1365138936Sjulian /* send only the relevant registers per Rev. 1.2 */ 1366138936Sjulian MT2032_SetRegister(0, buf[0x00]); 1367138936Sjulian MT2032_SetRegister(1, buf[0x01]); 1368138936Sjulian MT2032_SetRegister(2, buf[0x02]); 1369138936Sjulian 1370138936Sjulian MT2032_SetRegister(5, buf[0x05]); 1371138936Sjulian MT2032_SetRegister(6, buf[0x06]); 1372138936Sjulian MT2032_SetRegister(7, buf[0x07]); 1373138936Sjulian 1374138936Sjulian MT2032_SetRegister(11, buf[0x0B]); 1375138936Sjulian MT2032_SetRegister(12, buf[0x0C]); 1376138936Sjulian 1377138936Sjulian /* wait for PLLs to lock (per manual), retry LINT if not. */ 1378138936Sjulian for (lint_try = 0; lint_try < 2; lint_try++) { 1379138936Sjulian lock = MT2032_CheckLOLock(bktr); 1380138936Sjulian 1381138936Sjulian if (MT2032_OPTIMIZE_VCO) { 1382138936Sjulian lock = MT2032_OptimizeVCO(bktr, sel, lock); 1383138936Sjulian } 1384138936Sjulian if (lock == 6) { 1385138936Sjulian break; 1386138936Sjulian } 1387138936Sjulian /* set LINT to re-init PLLs */ 1388138936Sjulian MT2032_SetRegister(7, 0x80 + 8 + MT2032_XOGC); 1389138936Sjulian DELAY(10000); 1390138936Sjulian MT2032_SetRegister(7, 8 + MT2032_XOGC); 1391138936Sjulian } 1392138936Sjulian if (lock != 6) 1393138936Sjulian printf("%s: PLL didn't lock\n", bktr_name(bktr)); 1394138936Sjulian 1395138936Sjulian MT2032_SetRegister(2, 0x20); 1396138936Sjulian 1397138936Sjulian TDA9887_init(bktr, 1); 1398138936Sjulian return 0; 1399138936Sjulian} 1400138936Sjulian 1401138936Sjulianstatic void 1402138936Sjulianmt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq) 1403138936Sjulian{ 1404138936Sjulian int if2,from,to; 1405140655Sjulian int stat, tad; 1406138936Sjulian 1407140655Sjulian#ifdef MT2032_NTSC 1408140655Sjulian from=40750*1000; 1409140655Sjulian to=46750*1000; 1410140655Sjulian if2=45750*1000; 1411140655Sjulian#else 1412138936Sjulian from=32900*1000; 1413138936Sjulian to=39900*1000; 1414138936Sjulian if2=38900*1000; 1415140655Sjulian#endif 1416138936Sjulian 1417140655Sjulian if (MT2032_SetIFFreq(bktr, freq*62500 /* freq*1000*1000/16 */, 1418140655Sjulian 1090*1000*1000, if2, from, to) == 0) { 1419140655Sjulian bktr->tuner.frequency = freq; 1420140655Sjulian stat = MT2032_GetRegister(0x0e); 1421140655Sjulian tad = MT2032_GetRegister(0x0f); 1422140655Sjulian if (bootverbose) 1423140655Sjulian printf("%s: frequency set to %d, st = %#x, tad = %#x\n", 1424140655Sjulian bktr_name(bktr), freq*62500, stat, tad); 1425140655Sjulian } 1426138936Sjulian} 1427