bktr_tuner.c revision 330897
1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * 1. Redistributions of source code must retain the
5 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *      This product includes software developed by Amancio Hasty and
19 *      Roger Hardiman
20 * 4. The name of the author may not be used to endorse or promote products
21 *    derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: stable/11/sys/dev/bktr/bktr_tuner.c 330897 2018-03-14 03:19:51Z eadler $");
38
39/*
40 * This is part of the Driver for Video Capture Cards (Frame grabbers)
41 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
42 * chipset.
43 * Copyright Roger Hardiman and Amancio Hasty.
44 *
45 * bktr_tuner : This deals with controlling the tuner fitted to TV cards.
46 */
47
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/kernel.h>
51#ifdef __NetBSD__
52#include <sys/proc.h>
53#endif
54
55#ifdef __FreeBSD__
56#if (__FreeBSD_version < 500000)
57#include <machine/clock.h>              /* for DELAY */
58#include <pci/pcivar.h>
59#else
60#include <sys/lock.h>
61#include <sys/mutex.h>
62#include <sys/selinfo.h>
63#include <dev/pci/pcivar.h>
64#endif
65
66#include <machine/bus.h>
67#include <sys/bus.h>
68#endif
69
70#ifdef __NetBSD__
71#include <dev/ic/bt8xx.h>	/* NetBSD .h file location */
72#include <dev/pci/bktr/bktr_reg.h>
73#include <dev/pci/bktr/bktr_tuner.h>
74#include <dev/pci/bktr/bktr_card.h>
75#include <dev/pci/bktr/bktr_core.h>
76#else
77#include <dev/bktr/ioctl_meteor.h>
78#include <dev/bktr/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
79#include <dev/bktr/bktr_reg.h>
80#include <dev/bktr/bktr_tuner.h>
81#include <dev/bktr/bktr_card.h>
82#include <dev/bktr/bktr_core.h>
83#endif
84
85
86
87#if defined( TUNER_AFC )
88#define AFC_DELAY               10000   /* 10 millisend delay */
89#define AFC_BITS                0x07
90#define AFC_FREQ_MINUS_125      0x00
91#define AFC_FREQ_MINUS_62       0x01
92#define AFC_FREQ_CENTERED       0x02
93#define AFC_FREQ_PLUS_62        0x03
94#define AFC_FREQ_PLUS_125       0x04
95#define AFC_MAX_STEP            (5 * FREQFACTOR) /* no more than 5 MHz */
96#endif /* TUNER_AFC */
97
98
99#define TTYPE_XXX               0
100#define TTYPE_NTSC              1
101#define TTYPE_NTSC_J            2
102#define TTYPE_PAL               3
103#define TTYPE_PAL_M             4
104#define TTYPE_PAL_N             5
105#define TTYPE_SECAM             6
106
107#define TSA552x_CB_MSB          (0x80)
108#define TSA552x_CB_CP           (1<<6)	/* set this for fast tuning */
109#define TSA552x_CB_T2           (1<<5)	/* test mode - Normally set to 0 */
110#define TSA552x_CB_T1           (1<<4)	/* test mode - Normally set to 0 */
111#define TSA552x_CB_T0           (1<<3)	/* test mode - Normally set to 1 */
112#define TSA552x_CB_RSA          (1<<2)	/* 0 for 31.25 khz, 1 for 62.5 kHz */
113#define TSA552x_CB_RSB          (1<<1)	/* 0 for FM 50kHz steps, 1 = Use RSA*/
114#define TSA552x_CB_OS           (1<<0)	/* Set to 0 for normal operation */
115
116#define TSA552x_RADIO           (TSA552x_CB_MSB |       \
117                                 TSA552x_CB_T0)
118
119/* raise the charge pump voltage for fast tuning */
120#define TSA552x_FCONTROL        (TSA552x_CB_MSB |       \
121                                 TSA552x_CB_CP  |       \
122                                 TSA552x_CB_T0  |       \
123                                 TSA552x_CB_RSA |       \
124                                 TSA552x_CB_RSB)
125
126/* lower the charge pump voltage for better residual oscillator FM */
127#define TSA552x_SCONTROL        (TSA552x_CB_MSB |       \
128                                 TSA552x_CB_T0  |       \
129                                 TSA552x_CB_RSA |       \
130                                 TSA552x_CB_RSB)
131
132/* The control value for the ALPS TSCH5 Tuner */
133#define TSCH5_FCONTROL          0x82
134#define TSCH5_RADIO             0x86
135
136/* The control value for the ALPS TSBH1 Tuner */
137#define TSBH1_FCONTROL		0xce
138
139
140static void mt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq);
141
142
143static const struct TUNER tuners[] = {
144/* XXX FIXME: fill in the band-switch crosspoints */
145	/* NO_TUNER */
146	{ "<no>",				/* the 'name' */
147	   TTYPE_XXX,				/* input type */
148 	   { 0x00,				/* control byte for Tuner PLL */
149 	     0x00,
150 	     0x00,
151 	     0x00 },
152	   { 0x00, 0x00 },			/* band-switch crosspoints */
153	   { 0x00, 0x00, 0x00,0x00} },		/* the band-switch values */
154
155	/* TEMIC_NTSC */
156	{ "Temic NTSC",				/* the 'name' */
157	   TTYPE_NTSC,				/* input type */
158	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
159	     TSA552x_SCONTROL,
160	     TSA552x_SCONTROL,
161	     0x00 },
162	   { 0x00, 0x00},			/* band-switch crosspoints */
163	   { 0x02, 0x04, 0x01, 0x00 } },	/* the band-switch values */
164
165	/* TEMIC_PAL */
166	{ "Temic PAL",				/* the 'name' */
167	   TTYPE_PAL,				/* input type */
168	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
169	     TSA552x_SCONTROL,
170	     TSA552x_SCONTROL,
171	     0x00 },
172	   { 0x00, 0x00 },			/* band-switch crosspoints */
173	   { 0x02, 0x04, 0x01, 0x00 } },	/* the band-switch values */
174
175	/* TEMIC_SECAM */
176	{ "Temic SECAM",			/* the 'name' */
177	   TTYPE_SECAM,				/* input type */
178	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
179	     TSA552x_SCONTROL,
180	     TSA552x_SCONTROL,
181	     0x00 },
182	   { 0x00, 0x00 },			/* band-switch crosspoints */
183	   { 0x02, 0x04, 0x01,0x00 } },		/* the band-switch values */
184
185	/* PHILIPS_NTSC */
186	{ "Philips NTSC",			/* the 'name' */
187	   TTYPE_NTSC,				/* input type */
188	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
189	     TSA552x_SCONTROL,
190	     TSA552x_SCONTROL,
191	     0x00 },
192	   { 0x00, 0x00 },			/* band-switch crosspoints */
193	   { 0xa0, 0x90, 0x30, 0x00 } },	/* the band-switch values */
194
195	/* PHILIPS_PAL */
196	{ "Philips PAL",			/* the 'name' */
197	   TTYPE_PAL,				/* input type */
198	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
199	     TSA552x_SCONTROL,
200	     TSA552x_SCONTROL,
201	     0x00 },
202	   { 0x00, 0x00 },			/* band-switch crosspoints */
203	   { 0xa0, 0x90, 0x30, 0x00 } },	/* the band-switch values */
204
205	/* PHILIPS_SECAM */
206	{ "Philips SECAM",			/* the 'name' */
207	   TTYPE_SECAM,				/* input type */
208	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
209	     TSA552x_SCONTROL,
210	     TSA552x_SCONTROL,
211	     0x00 },
212	   { 0x00, 0x00 },			/* band-switch crosspoints */
213	   { 0xa7, 0x97, 0x37, 0x00 } },	/* the band-switch values */
214
215	/* TEMIC_PAL I */
216	{ "Temic PAL I",			/* the 'name' */
217	   TTYPE_PAL,				/* input type */
218	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
219	     TSA552x_SCONTROL,
220	     TSA552x_SCONTROL,
221	     0x00 },
222	   { 0x00, 0x00 },			/* band-switch crosspoints */
223	   { 0x02, 0x04, 0x01,0x00 } },		/* the band-switch values */
224
225	/* PHILIPS_PALI */
226	{ "Philips PAL I",			/* the 'name' */
227	   TTYPE_PAL,				/* input type */
228	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
229	     TSA552x_SCONTROL,
230	     TSA552x_SCONTROL,
231	     0x00 },
232          { 0x00, 0x00 },                      /* band-switch crosspoints */
233          { 0xa0, 0x90, 0x30,0x00 } },         /* the band-switch values */
234
235       /* PHILIPS_FR1236_NTSC */
236       { "Philips FR1236 NTSC FM",             /* the 'name' */
237          TTYPE_NTSC,                          /* input type */
238	  { TSA552x_FCONTROL,			/* control byte for Tuner PLL */
239	    TSA552x_FCONTROL,
240	    TSA552x_FCONTROL,
241	    TSA552x_RADIO  },
242          { 0x00, 0x00 },			/* band-switch crosspoints */
243	  { 0xa0, 0x90, 0x30,0xa4 } },		/* the band-switch values */
244
245	/* PHILIPS_FR1216_PAL */
246	{ "Philips FR1216 PAL FM" ,		/* the 'name' */
247	   TTYPE_PAL,				/* input type */
248	   { TSA552x_FCONTROL,			/* control byte for Tuner PLL */
249	     TSA552x_FCONTROL,
250	     TSA552x_FCONTROL,
251	     TSA552x_RADIO },
252	   { 0x00, 0x00 },			/* band-switch crosspoints */
253	   { 0xa0, 0x90, 0x30, 0xa4 } },	/* the band-switch values */
254
255	/* PHILIPS_FR1236_SECAM */
256	{ "Philips FR1236 SECAM FM",		/* the 'name' */
257	   TTYPE_SECAM,				/* input type */
258	   { TSA552x_FCONTROL,			/* control byte for Tuner PLL */
259	     TSA552x_FCONTROL,
260	     TSA552x_FCONTROL,
261	     TSA552x_RADIO },
262	   { 0x00, 0x00 },			/* band-switch crosspoints */
263	   { 0xa7, 0x97, 0x37, 0xa4 } },	/* the band-switch values */
264
265        /* ALPS TSCH5 NTSC */
266        { "ALPS TSCH5 NTSC FM",                 /* the 'name' */
267           TTYPE_NTSC,                          /* input type */
268           { TSCH5_FCONTROL,                    /* control byte for Tuner PLL */
269             TSCH5_FCONTROL,
270             TSCH5_FCONTROL,
271             TSCH5_RADIO },
272           { 0x00, 0x00 },                      /* band-switch crosspoints */
273           { 0x14, 0x12, 0x11, 0x04 } },        /* the band-switch values */
274
275        /* ALPS TSBH1 NTSC */
276        { "ALPS TSBH1 NTSC",                    /* the 'name' */
277           TTYPE_NTSC,                          /* input type */
278           { TSBH1_FCONTROL,                    /* control byte for Tuner PLL */
279             TSBH1_FCONTROL,
280             TSBH1_FCONTROL,
281             0x00 },
282           { 0x00, 0x00 },                      /* band-switch crosspoints */
283           { 0x01, 0x02, 0x08, 0x00 } },        /* the band-switch values */
284
285	/* MT2032 Microtune */
286	{ "MT2032",				/* the 'name' */
287	   TTYPE_PAL,				/* input type */
288	   { TSA552x_SCONTROL,			/* control byte for Tuner PLL */
289	     TSA552x_SCONTROL,
290	     TSA552x_SCONTROL,
291	     0x00 },
292	   { 0x00, 0x00 },			/* band-switch crosspoints */
293	   { 0xa0, 0x90, 0x30, 0x00 } },	/* the band-switch values */
294
295	 /* LG TPI8PSB12P PAL */
296	 { "LG TPI8PSB12P PAL",                 /* the 'name' */
297	   TTYPE_PAL,                           /* input type */
298	   { TSA552x_SCONTROL,                  /* control byte for Tuner PLL */
299	     TSA552x_SCONTROL,
300	     TSA552x_SCONTROL,
301	     0x00 },
302	   { 0x00, 0x00 },                      /* band-switch crosspoints */
303	   { 0xa0, 0x90, 0x30, 0x8e } },        /* the band-switch values */
304};
305
306
307/* scaling factor for frequencies expressed as ints */
308#define FREQFACTOR		16
309
310/*
311 * Format:
312 *	entry 0:         MAX legal channel
313 *	entry 1:         IF frequency
314 *			 expressed as fi{mHz} * 16,
315 *			 eg 45.75mHz == 45.75 * 16 = 732
316 *	entry 2:         [place holder/future]
317 *	entry 3:         base of channel record 0
318 *	entry 3 + (x*3): base of channel record 'x'
319 *	entry LAST:      NULL channel entry marking end of records
320 *
321 * Record:
322 *	int 0:		base channel
323 *	int 1:		frequency of base channel,
324 *			 expressed as fb{mHz} * 16,
325 *	int 2:		offset frequency between channels,
326 *			 expressed as fo{mHz} * 16,
327 */
328
329/*
330 * North American Broadcast Channels:
331 *
332 *  2:  55.25 mHz -  4:  67.25 mHz
333 *  5:  77.25 mHz -  6:	 83.25 mHz
334 *  7: 175.25 mHz - 13:	211.25 mHz
335 * 14: 471.25 mHz - 83:	885.25 mHz
336 *
337 * IF freq: 45.75 mHz
338 */
339#define OFFSET	6.00
340static int nabcst[] = {
341	83,	(int)( 45.75 * FREQFACTOR),	0,
342	14,	(int)(471.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
343	 7,	(int)(175.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
344	 5,	(int)( 77.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
345	 2,	(int)( 55.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
346	 0
347};
348#undef OFFSET
349
350/*
351 * North American Cable Channels, IRC:
352 *
353 *  2:  55.25 mHz -  4:  67.25 mHz
354 *  5:  77.25 mHz -  6:  83.25 mHz
355 *  7: 175.25 mHz - 13: 211.25 mHz
356 * 14: 121.25 mHz - 22: 169.25 mHz
357 * 23: 217.25 mHz - 94: 643.25 mHz
358 * 95:  91.25 mHz - 99: 115.25 mHz
359 *
360 * IF freq: 45.75 mHz
361 */
362#define OFFSET	6.00
363static int irccable[] = {
364	116,    (int)( 45.75 * FREQFACTOR),     0,
365	100,    (int)(649.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
366	95,	(int)( 91.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
367	23,	(int)(217.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
368	14,	(int)(121.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
369	 7,	(int)(175.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
370	 5,	(int)( 77.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
371	 2,	(int)( 55.25 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
372	 0
373};
374#undef OFFSET
375
376/*
377 * North American Cable Channels, HRC:
378 *
379 * 2:   54 mHz  - 4:    66 mHz
380 * 5:   78 mHz  - 6:    84 mHz
381 * 7:  174 mHz  - 13:  210 mHz
382 * 14: 120 mHz  - 22:  168 mHz
383 * 23: 216 mHz  - 94:  642 mHz
384 * 95:  90 mHz  - 99:  114 mHz
385 *
386 * IF freq: 45.75 mHz
387 */
388#define OFFSET  6.00
389static int hrccable[] = {
390	116,    (int)( 45.75 * FREQFACTOR),     0,
391	100,    (int)(648.00 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
392	95,	(int)( 90.00 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
393	23,	(int)(216.00 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
394	14,	(int)(120.00 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
395	7,	(int)(174.00 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
396	5,	(int)( 78.00 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
397	2,	(int)( 54.00 * FREQFACTOR),	(int)(OFFSET * FREQFACTOR),
398	0
399};
400#undef OFFSET
401
402/*
403 * Western European broadcast channels:
404 *
405 * (there are others that appear to vary between countries - rmt)
406 *
407 * here's the table Philips provides:
408 * caution, some of the offsets don't compute...
409 *
410 *  1	 4525	700	N21
411 *
412 *  2	 4825	700	E2
413 *  3	 5525	700	E3
414 *  4	 6225	700	E4
415 *
416 *  5	17525	700	E5
417 *  6	18225	700	E6
418 *  7	18925	700	E7
419 *  8	19625	700	E8
420 *  9	20325	700	E9
421 * 10	21025	700	E10
422 * 11	21725	700	E11
423 * 12	22425	700	E12
424 *
425 * 13	 5375	700	ITA
426 * 14	 6225	700	ITB
427 *
428 * 15	 8225	700	ITC
429 *
430 * 16	17525	700	ITD
431 * 17	18325	700	ITE
432 *
433 * 18	19225	700	ITF
434 * 19	20125	700	ITG
435 * 20	21025	700	ITH
436 *
437 * 21	47125	800	E21
438 * 22	47925	800	E22
439 * 23	48725	800	E23
440 * 24	49525	800	E24
441 * 25	50325	800	E25
442 * 26	51125	800	E26
443 * 27	51925	800	E27
444 * 28	52725	800	E28
445 * 29	53525	800	E29
446 * 30	54325	800	E30
447 * 31	55125	800	E31
448 * 32	55925	800	E32
449 * 33	56725	800	E33
450 * 34	57525	800	E34
451 * 35	58325	800	E35
452 * 36	59125	800	E36
453 * 37	59925	800	E37
454 * 38	60725	800	E38
455 * 39	61525	800	E39
456 * 40	62325	800	E40
457 * 41	63125	800	E41
458 * 42	63925	800	E42
459 * 43	64725	800	E43
460 * 44	65525	800	E44
461 * 45	66325	800	E45
462 * 46	67125	800	E46
463 * 47	67925	800	E47
464 * 48	68725	800	E48
465 * 49	69525	800	E49
466 * 50	70325	800	E50
467 * 51	71125	800	E51
468 * 52	71925	800	E52
469 * 53	72725	800	E53
470 * 54	73525	800	E54
471 * 55	74325	800	E55
472 * 56	75125	800	E56
473 * 57	75925	800	E57
474 * 58	76725	800	E58
475 * 59	77525	800	E59
476 * 60	78325	800	E60
477 * 61	79125	800	E61
478 * 62	79925	800	E62
479 * 63	80725	800	E63
480 * 64	81525	800	E64
481 * 65	82325	800	E65
482 * 66	83125	800	E66
483 * 67	83925	800	E67
484 * 68	84725	800	E68
485 * 69	85525	800	E69
486 *
487 * 70	 4575	800	IA
488 * 71	 5375	800	IB
489 * 72	 6175	800	IC
490 *
491 * 74	 6925	700	S01
492 * 75	 7625	700	S02
493 * 76	 8325	700	S03
494 *
495 * 80	10525	700	S1
496 * 81	11225	700	S2
497 * 82	11925	700	S3
498 * 83	12625	700	S4
499 * 84	13325	700	S5
500 * 85	14025	700	S6
501 * 86	14725	700	S7
502 * 87	15425	700	S8
503 * 88	16125	700	S9
504 * 89	16825	700	S10
505 * 90	23125	700	S11
506 * 91	23825	700	S12
507 * 92	24525	700	S13
508 * 93	25225	700	S14
509 * 94	25925	700	S15
510 * 95	26625	700	S16
511 * 96	27325	700	S17
512 * 97	28025	700	S18
513 * 98	28725	700	S19
514 * 99	29425	700	S20
515 *
516 *
517 * Channels S21 - S41 are taken from
518 * http://gemma.apple.com:80/dev/technotes/tn/tn1012.html
519 *
520 * 100	30325	800	S21
521 * 101	31125	800	S22
522 * 102	31925	800	S23
523 * 103	32725	800	S24
524 * 104	33525	800	S25
525 * 105	34325	800	S26
526 * 106	35125	800	S27
527 * 107	35925	800	S28
528 * 108	36725	800	S29
529 * 109	37525	800	S30
530 * 110	38325	800	S31
531 * 111	39125	800	S32
532 * 112	39925	800	S33
533 * 113	40725	800	S34
534 * 114	41525	800	S35
535 * 115	42325	800	S36
536 * 116	43125	800	S37
537 * 117	43925	800	S38
538 * 118	44725	800	S39
539 * 119	45525	800	S40
540 * 120	46325	800	S41
541 *
542 * 121	 3890	000	IFFREQ
543 *
544 */
545static int weurope[] = {
546       121,     (int)( 38.90 * FREQFACTOR),     0,
547       100,     (int)(303.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
548        90,     (int)(231.25 * FREQFACTOR),     (int)(7.00 * FREQFACTOR),
549        80,     (int)(105.25 * FREQFACTOR),     (int)(7.00 * FREQFACTOR),
550        74,     (int)( 69.25 * FREQFACTOR),     (int)(7.00 * FREQFACTOR),
551        21,     (int)(471.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
552        17,     (int)(183.25 * FREQFACTOR),     (int)(9.00 * FREQFACTOR),
553        16,     (int)(175.25 * FREQFACTOR),     (int)(9.00 * FREQFACTOR),
554        15,     (int)(82.25 * FREQFACTOR),      (int)(8.50 * FREQFACTOR),
555        13,     (int)(53.75 * FREQFACTOR),      (int)(8.50 * FREQFACTOR),
556         5,     (int)(175.25 * FREQFACTOR),     (int)(7.00 * FREQFACTOR),
557         2,     (int)(48.25 * FREQFACTOR),      (int)(7.00 * FREQFACTOR),
558	 0
559};
560
561/*
562 * Japanese Broadcast Channels:
563 *
564 *  1:  91.25MHz -  3: 103.25MHz
565 *  4: 171.25MHz -  7: 189.25MHz
566 *  8: 193.25MHz - 12: 217.25MHz  (VHF)
567 * 13: 471.25MHz - 62: 765.25MHz  (UHF)
568 *
569 * IF freq: 45.75 mHz
570 *  OR
571 * IF freq: 58.75 mHz
572 */
573#define OFFSET  6.00
574#define IF_FREQ 45.75
575static int jpnbcst[] = {
576	62,     (int)(IF_FREQ * FREQFACTOR),    0,
577	13,     (int)(471.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
578	 8,     (int)(193.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
579	 4,     (int)(171.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
580	 1,     (int)( 91.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
581	 0
582};
583#undef IF_FREQ
584#undef OFFSET
585
586/*
587 * Japanese Cable Channels:
588 *
589 *  1:  91.25MHz -  3: 103.25MHz
590 *  4: 171.25MHz -  7: 189.25MHz
591 *  8: 193.25MHz - 12: 217.25MHz
592 * 13: 109.25MHz - 21: 157.25MHz
593 * 22: 165.25MHz
594 * 23: 223.25MHz - 63: 463.25MHz
595 *
596 * IF freq: 45.75 mHz
597 */
598#define OFFSET  6.00
599#define IF_FREQ 45.75
600static int jpncable[] = {
601	63,     (int)(IF_FREQ * FREQFACTOR),    0,
602	23,     (int)(223.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
603	22,     (int)(165.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
604	13,     (int)(109.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
605	 8,     (int)(193.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
606	 4,     (int)(171.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
607	 1,     (int)( 91.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
608	 0
609};
610#undef IF_FREQ
611#undef OFFSET
612
613/*
614 * xUSSR Broadcast Channels:
615 *
616 *  1:  49.75MHz -  2:  59.25MHz
617 *  3:  77.25MHz -  5:  93.25MHz
618 *  6: 175.25MHz - 12: 223.25MHz
619 * 13-20 - not exist
620 * 21: 471.25MHz - 34: 575.25MHz
621 * 35: 583.25MHz - 69: 855.25MHz
622 *
623 * Cable channels
624 *
625 * 70: 111.25MHz - 77: 167.25MHz
626 * 78: 231.25MHz -107: 463.25MHz
627 *
628 * IF freq: 38.90 MHz
629 */
630#define IF_FREQ 38.90
631static int xussr[] = {
632      107,     (int)(IF_FREQ * FREQFACTOR),    0,
633       78,     (int)(231.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
634       70,     (int)(111.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
635       35,     (int)(583.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
636       21,     (int)(471.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
637        6,     (int)(175.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
638        3,     (int)( 77.25 * FREQFACTOR),     (int)(8.00 * FREQFACTOR),
639        1,     (int)( 49.75 * FREQFACTOR),     (int)(9.50 * FREQFACTOR),
640        0
641};
642#undef IF_FREQ
643
644/*
645 * Australian broadcast channels
646 */
647#define OFFSET	7.00
648#define IF_FREQ 38.90
649static int australia[] = {
650       83,     (int)(IF_FREQ * FREQFACTOR),    0,
651       28,     (int)(527.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
652       10,     (int)(209.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
653        6,     (int)(175.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
654        4,     (int)( 95.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
655        3,     (int)( 86.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
656        1,     (int)( 57.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR),
657        0
658};
659#undef OFFSET
660#undef IF_FREQ
661
662/*
663 * France broadcast channels
664 */
665#define OFFSET 8.00
666#define IF_FREQ 38.90
667static int france[] = {
668        69,     (int)(IF_FREQ * FREQFACTOR),     0,
669        21,     (int)(471.25 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR), /* 21 -> 69 */
670         5,     (int)(176.00 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR), /* 5 -> 10 */
671         4,     (int)( 63.75 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR), /* 4    */
672         3,     (int)( 60.50 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR), /* 3    */
673         1,     (int)( 47.75 * FREQFACTOR),     (int)(OFFSET * FREQFACTOR), /* 1  2 */
674         0
675};
676#undef OFFSET
677#undef IF_FREQ
678
679static struct {
680        int     *ptr;
681        char    name[BT848_MAX_CHNLSET_NAME_LEN];
682} freqTable[] = {
683        {NULL,          ""},
684        {nabcst,        "nabcst"},
685        {irccable,      "cableirc"},
686        {hrccable,      "cablehrc"},
687        {weurope,       "weurope"},
688        {jpnbcst,       "jpnbcst"},
689        {jpncable,      "jpncable"},
690        {xussr,         "xussr"},
691        {australia,     "australia"},
692        {france,        "france"},
693
694};
695
696#define TBL_CHNL	freqTable[ bktr->tuner.chnlset ].ptr[ x ]
697#define TBL_BASE_FREQ	freqTable[ bktr->tuner.chnlset ].ptr[ x + 1 ]
698#define TBL_OFFSET	freqTable[ bktr->tuner.chnlset ].ptr[ x + 2 ]
699static int
700frequency_lookup( bktr_ptr_t bktr, int channel )
701{
702	int	x;
703
704	/* check for "> MAX channel" */
705	x = 0;
706	if ( channel > TBL_CHNL )
707		return( -1 );
708
709	/* search the table for data */
710	for ( x = 3; TBL_CHNL; x += 3 ) {
711		if ( channel >= TBL_CHNL ) {
712			return( TBL_BASE_FREQ +
713				 ((channel - TBL_CHNL) * TBL_OFFSET) );
714		}
715	}
716
717	/* not found, must be below the MIN channel */
718	return( -1 );
719}
720#undef TBL_OFFSET
721#undef TBL_BASE_FREQ
722#undef TBL_CHNL
723
724
725#define	TBL_IF	(bktr->format_params == BT848_IFORM_F_NTSCJ || \
726                 bktr->format_params == BT848_IFORM_F_NTSCM ? \
727                 nabcst[1] : weurope[1])
728
729
730/* Initialise the tuner structures in the bktr_softc */
731/* This is needed as the tuner details are no longer globally declared */
732
733void    select_tuner( bktr_ptr_t bktr, int tuner_type ) {
734	if (tuner_type < Bt848_MAX_TUNER) {
735		bktr->card.tuner = &tuners[ tuner_type ];
736	} else {
737		bktr->card.tuner = NULL;
738	}
739}
740
741/*
742 * Tuner Notes:
743 * Programming the tuner properly is quite complicated.
744 * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner.
745 * The tuner (front end) covers 45.75 Mhz - 855.25 Mhz and an FM band of
746 * 87.5 Mhz to 108.0 Mhz.
747 *
748 * RF and IF.  RF = radio frequencies, it is the transmitted signal.
749 *             IF is the Intermediate Frequency (the offset from the base
750 *             signal where the video, color,  audio and NICAM signals are.
751 *
752 * Eg, Picture at 38.9 Mhz, Colour at 34.47 MHz, sound at 32.9 MHz
753 * NICAM at 32.348 Mhz.
754 * Strangely enough, there is an IF (intermediate frequency) for
755 * FM Radio which is 10.7 Mhz.
756 *
757 * The tuner also works in Bands. Philips bands are
758 * FM radio band 87.50 to 108.00 MHz
759 * Low band 45.75 to 170.00 MHz
760 * Mid band 170.00 to 450.00 MHz
761 * High band 450.00 to 855.25 MHz
762 *
763 *
764 * Now we need to set the PLL on the tuner to the required freuqncy.
765 * It has a programmable divisor.
766 * For TV we want
767 *  N = 16 (freq RF(pc) + freq IF(pc))  pc is picture carrier and RF and IF
768 *  are in MHz.
769
770 * For RADIO we want a different equation.
771 *  freq IF is 10.70 MHz (so the data sheet tells me)
772 * N = (freq RF + freq IF) / step size
773 * The step size must be set to 50 khz (so the data sheet tells me)
774 * (note this is 50 kHz, the other things are in MHz)
775 * so we end up with N = 20x(freq RF + 10.7)
776 *
777 */
778
779#define LOW_BAND 0
780#define MID_BAND 1
781#define HIGH_BAND 2
782#define FM_RADIO_BAND 3
783
784
785/* Check if these are correct for other than Philips PAL */
786#define STATUSBIT_COLD   0x80
787#define STATUSBIT_LOCK   0x40
788#define STATUSBIT_TV     0x20
789#define STATUSBIT_STEREO 0x10 /* valid if FM (aka not TV) */
790#define STATUSBIT_ADC    0x07
791
792/*
793 * set the frequency of the tuner
794 * If 'type' is TV_FREQUENCY, the frequency is freq MHz*16
795 * If 'type' is FM_RADIO_FREQUENCY, the frequency is freq MHz * 100
796 * (note *16 gives is 4 bits of fraction, eg steps of nnn.0625)
797 *
798 */
799int
800tv_freq( bktr_ptr_t bktr, int frequency, int type )
801{
802	const struct TUNER*	tuner;
803	u_char			addr;
804	u_char			control;
805	u_char			band;
806	int			N;
807	int			band_select = 0;
808#if defined( TEST_TUNER_AFC )
809	int			oldFrequency, afcDelta;
810#endif
811
812	tuner = bktr->card.tuner;
813	if ( tuner == NULL )
814		return( -1 );
815
816	if (tuner == &tuners[TUNER_MT2032]) {
817		mt2032_set_tv_freq(bktr, frequency);
818		return 0;
819	}
820	if (type == TV_FREQUENCY) {
821		/*
822		 * select the band based on frequency
823		 * XXX FIXME: get the cross-over points from the tuner struct
824		 */
825		if ( frequency < (160 * FREQFACTOR  ) )
826		    band_select = LOW_BAND;
827		else if ( frequency < (454 * FREQFACTOR ) )
828		    band_select = MID_BAND;
829		else
830		    band_select = HIGH_BAND;
831
832#if defined( TEST_TUNER_AFC )
833		if ( bktr->tuner.afc )
834			frequency -= 4;
835#endif
836		/*
837		 * N = 16 * { fRF(pc) + fIF(pc) }
838		 * or N = 16* fRF(pc) + 16*fIF(pc) }
839		 * where:
840		 *  pc is picture carrier, fRF & fIF are in MHz
841		 *
842		 * fortunatly, frequency is passed in as MHz * 16
843		 * and the TBL_IF frequency is also stored in MHz * 16
844		 */
845		N = frequency + TBL_IF;
846
847		/* set the address of the PLL */
848		addr    = bktr->card.tuner_pllAddr;
849		control = tuner->pllControl[ band_select ];
850		band    = tuner->bandAddrs[ band_select ];
851
852		if(!(band && control))		/* Don't try to set un-	*/
853		  return(-1);			/* supported modes.	*/
854
855		if ( frequency > bktr->tuner.frequency ) {
856			i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
857			i2cWrite( bktr, addr, control, band );
858	        }
859	        else {
860			i2cWrite( bktr, addr, control, band );
861			i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
862       		}
863
864#if defined( TUNER_AFC )
865		if ( bktr->tuner.afc == TRUE ) {
866#if defined( TEST_TUNER_AFC )
867			oldFrequency = frequency;
868#endif
869			if ( (N = do_afc( bktr, addr, N )) < 0 ) {
870			    /* AFC failed, restore requested frequency */
871			    N = frequency + TBL_IF;
872#if defined( TEST_TUNER_AFC )
873			    printf("%s: do_afc: failed to lock\n",
874				   bktr_name(bktr));
875#endif
876			    i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
877			}
878			else
879			    frequency = N - TBL_IF;
880#if defined( TEST_TUNER_AFC )
881 printf("%s: do_afc: returned freq %d (%d %% %d)\n", bktr_name(bktr), frequency, frequency / 16, frequency % 16);
882			    afcDelta = frequency - oldFrequency;
883 printf("%s: changed by: %d clicks (%d mod %d)\n", bktr_name(bktr), afcDelta, afcDelta / 16, afcDelta % 16);
884#endif
885			}
886#endif /* TUNER_AFC */
887
888		bktr->tuner.frequency = frequency;
889	}
890
891	if ( type == FM_RADIO_FREQUENCY ) {
892		band_select = FM_RADIO_BAND;
893
894		/*
895		 * N = { fRF(pc) + fIF(pc) }/step_size
896                 * The step size is 50kHz for FM radio.
897		 * (eg after 102.35MHz comes 102.40 MHz)
898		 * fIF is 10.7 MHz (as detailed in the specs)
899		 *
900		 * frequency is passed in as MHz * 100
901		 *
902		 * So, we have N = (frequency/100 + 10.70)  /(50/1000)
903		 */
904		N = (frequency + 1070)/5;
905
906		/* set the address of the PLL */
907		addr    = bktr->card.tuner_pllAddr;
908		control = tuner->pllControl[ band_select ];
909		band    = tuner->bandAddrs[ band_select ];
910
911		if(!(band && control))		/* Don't try to set un-	*/
912		  return(-1);			/* supported modes.	*/
913
914		band |= bktr->tuner.radio_mode; /* tuner.radio_mode is set in
915						 * the ioctls RADIO_SETMODE
916						 * and RADIO_GETMODE */
917
918		i2cWrite( bktr, addr, control, band );
919		i2cWrite( bktr, addr, (N>>8) & 0x7f, N & 0xff );
920
921		bktr->tuner.frequency = (N * 5) - 1070;
922
923
924	}
925
926
927	return( 0 );
928}
929
930
931
932#if defined( TUNER_AFC )
933/*
934 *
935 */
936int
937do_afc( bktr_ptr_t bktr, int addr, int frequency )
938{
939	int step;
940	int status;
941	int origFrequency;
942
943	origFrequency = frequency;
944
945	/* wait for first setting to take effect */
946	tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 );
947
948	if ( (status = i2cRead( bktr, addr + 1 )) < 0 )
949		return( -1 );
950
951#if defined( TEST_TUNER_AFC )
952 printf( "%s: Original freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status );
953#endif
954	for ( step = 0; step < AFC_MAX_STEP; ++step ) {
955		if ( (status = i2cRead( bktr, addr + 1 )) < 0 )
956			goto fubar;
957		if ( !(status & 0x40) ) {
958#if defined( TEST_TUNER_AFC )
959 printf( "%s: no lock!\n", bktr_name(bktr) );
960#endif
961			goto fubar;
962		}
963
964		switch( status & AFC_BITS ) {
965		case AFC_FREQ_CENTERED:
966#if defined( TEST_TUNER_AFC )
967 printf( "%s: Centered, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status );
968#endif
969			return( frequency );
970
971		case AFC_FREQ_MINUS_125:
972		case AFC_FREQ_MINUS_62:
973#if defined( TEST_TUNER_AFC )
974 printf( "%s: Low, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status );
975#endif
976			--frequency;
977			break;
978
979		case AFC_FREQ_PLUS_62:
980		case AFC_FREQ_PLUS_125:
981#if defined( TEST_TUNER_AFC )
982 printf( "%s: Hi, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status );
983#endif
984			++frequency;
985			break;
986		}
987
988		i2cWrite( bktr, addr,
989			  (frequency>>8) & 0x7f, frequency & 0xff );
990		DELAY( AFC_DELAY );
991	}
992
993 fubar:
994	i2cWrite( bktr, addr,
995		  (origFrequency>>8) & 0x7f, origFrequency & 0xff );
996
997	return( -1 );
998}
999#endif /* TUNER_AFC */
1000#undef TBL_IF
1001
1002
1003/*
1004 * Get the Tuner status and signal strength
1005 */
1006int     get_tuner_status( bktr_ptr_t bktr ) {
1007	if (bktr->card.tuner == &tuners[TUNER_MT2032])
1008		return 0;
1009	return i2cRead( bktr, bktr->card.tuner_pllAddr + 1 );
1010}
1011
1012/*
1013 * set the channel of the tuner
1014 */
1015int
1016tv_channel( bktr_ptr_t bktr, int channel )
1017{
1018	int frequency;
1019
1020	/* calculate the frequency according to tuner type */
1021	if ( (frequency = frequency_lookup( bktr, channel )) < 0 )
1022		return( -1 );
1023
1024	/* set the new frequency */
1025	if ( tv_freq( bktr, frequency, TV_FREQUENCY ) < 0 )
1026		return( -1 );
1027
1028	/* OK to update records */
1029	return( (bktr->tuner.channel = channel) );
1030}
1031
1032/*
1033 * get channelset name
1034 */
1035int
1036tuner_getchnlset(struct bktr_chnlset *chnlset)
1037{
1038       if (( chnlset->index < CHNLSET_MIN ) ||
1039               ( chnlset->index > CHNLSET_MAX ))
1040                       return( EINVAL );
1041
1042       memcpy(&chnlset->name, &freqTable[chnlset->index].name,
1043               BT848_MAX_CHNLSET_NAME_LEN);
1044
1045       chnlset->max_channel=freqTable[chnlset->index].ptr[0];
1046       return( 0 );
1047}
1048
1049
1050
1051
1052#define	TDA9887_ADDR	0x86
1053
1054static int
1055TDA9887_init(bktr_ptr_t bktr, int output2_enable)
1056{
1057	u_char addr = TDA9887_ADDR;
1058
1059	i2cWrite(bktr, addr, 0, output2_enable ? 0x50 : 0xd0);
1060	i2cWrite(bktr, addr, 1, 0x6e); /* takeover point / de-emphasis */
1061
1062	/* PAL BG: 0x09  PAL I: 0x0a  NTSC: 0x04 */
1063#ifdef MT2032_NTSC
1064	i2cWrite(bktr, addr, 2, 0x04);
1065#else
1066	i2cWrite(bktr, addr, 2, 0x09);
1067#endif
1068	return 0;
1069}
1070
1071
1072
1073#define MT2032_OPTIMIZE_VCO	 1
1074
1075/* holds the value of XOGC register after init */
1076static int      MT2032_XOGC = 4;
1077
1078/* card.tuner_pllAddr not set during init */
1079#define	MT2032_ADDR		0xc0
1080
1081#ifndef MT2032_ADDR
1082#define	MT2032_ADDR		(bktr->card.tuner_pllAddr)
1083#endif
1084
1085static int
1086_MT2032_GetRegister(bktr_ptr_t bktr, u_char regNum)
1087{
1088	int		ch;
1089
1090	if (i2cWrite(bktr, MT2032_ADDR, regNum, -1) == -1) {
1091		if (bootverbose)
1092			printf("%s: MT2032 write failed (i2c addr %#x)\n",
1093				bktr_name(bktr), MT2032_ADDR);
1094		return -1;
1095	}
1096	if ((ch = i2cRead(bktr, MT2032_ADDR + 1)) == -1) {
1097		if (bootverbose)
1098			printf("%s: MT2032 get register %d failed\n",
1099				bktr_name(bktr), regNum);
1100		return -1;
1101	}
1102	return ch;
1103}
1104
1105static void
1106_MT2032_SetRegister(bktr_ptr_t bktr, u_char regNum, u_char data)
1107{
1108	i2cWrite(bktr, MT2032_ADDR, regNum, data);
1109}
1110
1111#define	MT2032_GetRegister(r)		_MT2032_GetRegister(bktr,r)
1112#define	MT2032_SetRegister(r,d)		_MT2032_SetRegister(bktr,r,d)
1113
1114
1115int
1116mt2032_init(bktr_ptr_t bktr)
1117{
1118	u_char            rdbuf[22];
1119	int             xogc, xok = 0;
1120	int             i;
1121	int		x;
1122
1123	TDA9887_init(bktr, 0);
1124
1125	for (i = 0; i < 21; i++) {
1126		if ((x = MT2032_GetRegister(i)) == -1)
1127			break;
1128		rdbuf[i] = x;
1129	}
1130	if (i < 21)
1131		return -1;
1132
1133	printf("%s: MT2032: Companycode=%02x%02x Part=%02x Revision=%02x\n",
1134		bktr_name(bktr),
1135		rdbuf[0x11], rdbuf[0x12], rdbuf[0x13], rdbuf[0x14]);
1136	if (rdbuf[0x13] != 4) {
1137		printf("%s: MT2032 not found or unknown type\n", bktr_name(bktr));
1138		return -1;
1139	}
1140
1141	/* Initialize Registers per spec. */
1142	MT2032_SetRegister(2, 0xff);
1143	MT2032_SetRegister(3, 0x0f);
1144	MT2032_SetRegister(4, 0x1f);
1145	MT2032_SetRegister(6, 0xe4);
1146	MT2032_SetRegister(7, 0x8f);
1147	MT2032_SetRegister(8, 0xc3);
1148	MT2032_SetRegister(9, 0x4e);
1149	MT2032_SetRegister(10, 0xec);
1150	MT2032_SetRegister(13, 0x32);
1151
1152	/* Adjust XOGC (register 7), wait for XOK */
1153	xogc = 7;
1154	do {
1155		DELAY(10000);
1156		xok = MT2032_GetRegister(0x0e) & 0x01;
1157		if (xok == 1) {
1158			break;
1159		}
1160		xogc--;
1161		if (xogc == 3) {
1162			xogc = 4;	/* min. 4 per spec */
1163			break;
1164		}
1165		MT2032_SetRegister(7, 0x88 + xogc);
1166	} while (xok != 1);
1167
1168	TDA9887_init(bktr, 1);
1169
1170	MT2032_XOGC = xogc;
1171
1172	return 0;
1173}
1174
1175static int
1176MT2032_SpurCheck(int f1, int f2, int spectrum_from, int spectrum_to)
1177{
1178	int             n1 = 1, n2, f;
1179
1180	f1 = f1 / 1000;		/* scale to kHz to avoid 32bit overflows */
1181	f2 = f2 / 1000;
1182	spectrum_from /= 1000;
1183	spectrum_to /= 1000;
1184
1185	do {
1186		n2 = -n1;
1187		f = n1 * (f1 - f2);
1188		do {
1189			n2--;
1190			f = f - f2;
1191			if ((f > spectrum_from) && (f < spectrum_to)) {
1192				return 1;
1193			}
1194		} while ((f > (f2 - spectrum_to)) || (n2 > -5));
1195		n1++;
1196	} while (n1 < 5);
1197
1198	return 0;
1199}
1200
1201static int
1202MT2032_ComputeFreq(
1203		   int rfin,
1204		   int if1,
1205		   int if2,
1206		   int spectrum_from,
1207		   int spectrum_to,
1208		   unsigned char *buf,
1209		   int *ret_sel,
1210		   int xogc
1211)
1212{				/* all in Hz */
1213	int             fref, lo1, lo1n, lo1a, s, sel;
1214	int             lo1freq, desired_lo1, desired_lo2, lo2, lo2n, lo2a,
1215	                lo2num, lo2freq;
1216	int             nLO1adjust;
1217
1218	fref = 5250 * 1000;	/* 5.25MHz */
1219
1220	/* per spec 2.3.1 */
1221	desired_lo1 = rfin + if1;
1222	lo1 = (2 * (desired_lo1 / 1000) + (fref / 1000)) / (2 * fref / 1000);
1223	lo1freq = lo1 * fref;
1224	desired_lo2 = lo1freq - rfin - if2;
1225
1226	/* per spec 2.3.2 */
1227	for (nLO1adjust = 1; nLO1adjust < 3; nLO1adjust++) {
1228		if (!MT2032_SpurCheck(lo1freq, desired_lo2, spectrum_from, spectrum_to)) {
1229			break;
1230		}
1231		if (lo1freq < desired_lo1) {
1232			lo1 += nLO1adjust;
1233		} else {
1234			lo1 -= nLO1adjust;
1235		}
1236
1237		lo1freq = lo1 * fref;
1238		desired_lo2 = lo1freq - rfin - if2;
1239	}
1240
1241	/* per spec 2.3.3 */
1242	s = lo1freq / 1000 / 1000;
1243
1244	if (MT2032_OPTIMIZE_VCO) {
1245		if (s > 1890) {
1246			sel = 0;
1247		} else if (s > 1720) {
1248			sel = 1;
1249		} else if (s > 1530) {
1250			sel = 2;
1251		} else if (s > 1370) {
1252			sel = 3;
1253		} else {
1254			sel = 4;/* >1090 */
1255		}
1256	} else {
1257		if (s > 1790) {
1258			sel = 0;/* <1958 */
1259		} else if (s > 1617) {
1260			sel = 1;
1261		} else if (s > 1449) {
1262			sel = 2;
1263		} else if (s > 1291) {
1264			sel = 3;
1265		} else {
1266			sel = 4;/* >1090 */
1267		}
1268	}
1269
1270	*ret_sel = sel;
1271
1272	/* per spec 2.3.4 */
1273	lo1n = lo1 / 8;
1274	lo1a = lo1 - (lo1n * 8);
1275	lo2 = desired_lo2 / fref;
1276	lo2n = lo2 / 8;
1277	lo2a = lo2 - (lo2n * 8);
1278	/* scale to fit in 32bit arith */
1279	lo2num = ((desired_lo2 / 1000) % (fref / 1000)) * 3780 / (fref / 1000);
1280	lo2freq = (lo2a + 8 * lo2n) * fref + lo2num * (fref / 1000) / 3780 * 1000;
1281
1282	if (lo1a < 0 || lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a < 0 ||
1283	    lo2a > 7 || lo2n < 17 || lo2n > 30) {
1284		printf("MT2032: parameter out of range\n");
1285		return -1;
1286	}
1287	/* set up MT2032 register map for transfer over i2c */
1288	buf[0] = lo1n - 1;
1289	buf[1] = lo1a | (sel << 4);
1290	buf[2] = 0x86;		/* LOGC */
1291	buf[3] = 0x0f;		/* reserved */
1292	buf[4] = 0x1f;
1293	buf[5] = (lo2n - 1) | (lo2a << 5);
1294	if (rfin < 400 * 1000 * 1000) {
1295		buf[6] = 0xe4;
1296	} else {
1297		buf[6] = 0xf4;	/* set PKEN per rev 1.2 */
1298	}
1299
1300	buf[7] = 8 + xogc;
1301	buf[8] = 0xc3;		/* reserved */
1302	buf[9] = 0x4e;		/* reserved */
1303	buf[10] = 0xec;		/* reserved */
1304	buf[11] = (lo2num & 0xff);
1305	buf[12] = (lo2num >> 8) | 0x80;	/* Lo2RST */
1306
1307	return 0;
1308}
1309
1310static int
1311MT2032_CheckLOLock(bktr_ptr_t bktr)
1312{
1313	int             t, lock = 0;
1314	for (t = 0; t < 10; t++) {
1315		lock = MT2032_GetRegister(0x0e) & 0x06;
1316		if (lock == 6) {
1317			break;
1318		}
1319		DELAY(1000);
1320	}
1321	return lock;
1322}
1323
1324static int
1325MT2032_OptimizeVCO(bktr_ptr_t bktr, int sel, int lock)
1326{
1327	int             tad1, lo1a;
1328
1329	tad1 = MT2032_GetRegister(0x0f) & 0x07;
1330
1331	if (tad1 == 0) {
1332		return lock;
1333	}
1334	if (tad1 == 1) {
1335		return lock;
1336	}
1337	if (tad1 == 2) {
1338		if (sel == 0) {
1339			return lock;
1340		} else {
1341			sel--;
1342		}
1343	} else {
1344		if (sel < 4) {
1345			sel++;
1346		} else {
1347			return lock;
1348		}
1349	}
1350	lo1a = MT2032_GetRegister(0x01) & 0x07;
1351	MT2032_SetRegister(0x01, lo1a | (sel << 4));
1352	lock = MT2032_CheckLOLock(bktr);
1353	return lock;
1354}
1355
1356static int
1357MT2032_SetIFFreq(bktr_ptr_t bktr, int rfin, int if1, int if2, int from, int to)
1358{
1359	u_char          buf[21];
1360	int             lint_try, sel, lock = 0;
1361
1362	if (MT2032_ComputeFreq(rfin, if1, if2, from, to, &buf[0], &sel, MT2032_XOGC) == -1)
1363		return -1;
1364
1365	TDA9887_init(bktr, 0);
1366
1367	/* send only the relevant registers per Rev. 1.2 */
1368	MT2032_SetRegister(0, buf[0x00]);
1369	MT2032_SetRegister(1, buf[0x01]);
1370	MT2032_SetRegister(2, buf[0x02]);
1371
1372	MT2032_SetRegister(5, buf[0x05]);
1373	MT2032_SetRegister(6, buf[0x06]);
1374	MT2032_SetRegister(7, buf[0x07]);
1375
1376	MT2032_SetRegister(11, buf[0x0B]);
1377	MT2032_SetRegister(12, buf[0x0C]);
1378
1379	/* wait for PLLs to lock (per manual), retry LINT if not. */
1380	for (lint_try = 0; lint_try < 2; lint_try++) {
1381		lock = MT2032_CheckLOLock(bktr);
1382
1383		if (MT2032_OPTIMIZE_VCO) {
1384			lock = MT2032_OptimizeVCO(bktr, sel, lock);
1385		}
1386		if (lock == 6) {
1387			break;
1388		}
1389		/* set LINT to re-init PLLs */
1390		MT2032_SetRegister(7, 0x80 + 8 + MT2032_XOGC);
1391		DELAY(10000);
1392		MT2032_SetRegister(7, 8 + MT2032_XOGC);
1393	}
1394	if (lock != 6)
1395		printf("%s: PLL didn't lock\n", bktr_name(bktr));
1396
1397	MT2032_SetRegister(2, 0x20);
1398
1399	TDA9887_init(bktr, 1);
1400	return 0;
1401}
1402
1403static void
1404mt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq)
1405{
1406	int if2,from,to;
1407	int stat, tad;
1408
1409#ifdef MT2032_NTSC
1410	from=40750*1000;
1411	to=46750*1000;
1412	if2=45750*1000;
1413#else
1414	from=32900*1000;
1415	to=39900*1000;
1416	if2=38900*1000;
1417#endif
1418
1419	if (MT2032_SetIFFreq(bktr, freq*62500 /* freq*1000*1000/16 */,
1420			1090*1000*1000, if2, from, to) == 0) {
1421		bktr->tuner.frequency = freq;
1422		stat = MT2032_GetRegister(0x0e);
1423		tad = MT2032_GetRegister(0x0f);
1424		if (bootverbose)
1425			printf("%s: frequency set to %d, st = %#x, tad = %#x\n",
1426				bktr_name(bktr), freq*62500, stat, tad);
1427	}
1428}
1429