Merge from vendor branch FILE:
[dragonfly.git] / sys / dev / video / bktr / bktr_tuner.c
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 }