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