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