Commit | Line | Data |
---|---|---|
d3f3bfa9 | 1 | /*- |
984263bc MD |
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. | |
a35cc233 | 32 | * |
d3f3bfa9 | 33 | * $FreeBSD: src/sys/dev/bktr/bktr_tuner.c,v 1.20 2005/11/13 13:26:37 netchild Exp $ |
984263bc MD |
34 | */ |
35 | ||
36 | ||
a35cc233 JS |
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 | */ | |
984263bc MD |
45 | |
46 | #include <sys/param.h> | |
47 | #include <sys/systm.h> | |
48 | #include <sys/kernel.h> | |
1f7ab7c9 | 49 | #include <sys/bus.h> |
5b22f1a7 | 50 | #include <sys/event.h> |
984263bc | 51 | |
1f2de5d4 | 52 | #include <bus/pci/pcivar.h> |
984263bc | 53 | |
a35cc233 JS |
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> | |
984263bc MD |
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 | ||
7f5487a0 SS |
116 | static void mt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq); |
117 | ||
118 | ||
984263bc MD |
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 */ | |
d3f3bfa9 | 259 | { 0x01, 0x02, 0x08, 0x00 } }, /* the band-switch values */ |
7f5487a0 SS |
260 | |
261 | /* MT2032 Microtune */ | |
262 | { "MT2032", /* the 'name' */ | |
d3f3bfa9 | 263 | TTYPE_PAL, /* input type */ |
7f5487a0 SS |
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 */ | |
d3f3bfa9 SW |
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 */ | |
984263bc MD |
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 | ||
d3f3bfa9 SW |
701 | #define TBL_IF (bktr->format_params == BT848_IFORM_F_NTSCJ || \ |
702 | bktr->format_params == BT848_IFORM_F_NTSCM ? \ | |
703 | nabcst[1] : weurope[1]) | |
984263bc MD |
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 | ||
7f5487a0 SS |
792 | if (tuner == &tuners[TUNER_MT2032]) { |
793 | mt2032_set_tv_freq(bktr, frequency); | |
794 | return 0; | |
795 | } | |
984263bc MD |
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 ) | |
e3869ec7 | 849 | kprintf("%s: do_afc: failed to lock\n", |
984263bc MD |
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 ) | |
e3869ec7 | 857 | kprintf("%s: do_afc: returned freq %d (%d %% %d)\n", bktr_name(bktr), frequency, frequency / 16, frequency % 16); |
984263bc | 858 | afcDelta = frequency - oldFrequency; |
e3869ec7 | 859 | kprintf("%s: changed by: %d clicks (%d mod %d)\n", bktr_name(bktr), afcDelta, afcDelta / 16, afcDelta % 16); |
984263bc MD |
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 */ | |
377d4740 | 922 | tsleep( BKTR_SLEEP, 0, "tuning", hz/8 ); |
984263bc MD |
923 | |
924 | if ( (status = i2cRead( bktr, addr + 1 )) < 0 ) | |
925 | return( -1 ); | |
926 | ||
927 | #if defined( TEST_TUNER_AFC ) | |
e3869ec7 | 928 | kprintf( "%s: Original freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); |
984263bc MD |
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 ) | |
e3869ec7 | 935 | kprintf( "%s: no lock!\n", bktr_name(bktr) ); |
984263bc MD |
936 | #endif |
937 | goto fubar; | |
938 | } | |
939 | ||
940 | switch( status & AFC_BITS ) { | |
941 | case AFC_FREQ_CENTERED: | |
942 | #if defined( TEST_TUNER_AFC ) | |
e3869ec7 | 943 | kprintf( "%s: Centered, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); |
984263bc MD |
944 | #endif |
945 | return( frequency ); | |
946 | ||
947 | case AFC_FREQ_MINUS_125: | |
948 | case AFC_FREQ_MINUS_62: | |
949 | #if defined( TEST_TUNER_AFC ) | |
e3869ec7 | 950 | kprintf( "%s: Low, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); |
984263bc MD |
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 ) | |
e3869ec7 | 958 | kprintf( "%s: Hi, freq: %d, status: 0x%02x\n", bktr_name(bktr), frequency, status ); |
984263bc MD |
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 ) { | |
7f5487a0 SS |
983 | if (bktr->card.tuner == &tuners[TUNER_MT2032]) |
984 | return 0; | |
984263bc MD |
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 | } | |
7f5487a0 SS |
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) | |
e3869ec7 | 1068 | kprintf("%s: MT2032 write failed (i2c addr %#x)\n", |
7f5487a0 SS |
1069 | bktr_name(bktr), MT2032_ADDR); |
1070 | return -1; | |
1071 | } | |
1072 | if ((ch = i2cRead(bktr, MT2032_ADDR + 1)) == -1) { | |
1073 | if (bootverbose) | |
e3869ec7 | 1074 | kprintf("%s: MT2032 get register %d failed\n", |
7f5487a0 SS |
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 | ||
e3869ec7 | 1109 | kprintf("%s: MT2032: Companycode=%02x%02x Part=%02x Revision=%02x\n", |
7f5487a0 SS |
1110 | bktr_name(bktr), |
1111 | rdbuf[0x11], rdbuf[0x12], rdbuf[0x13], rdbuf[0x14]); | |
1112 | if (rdbuf[0x13] != 4) { | |
e3869ec7 | 1113 | kprintf("%s: MT2032 not found or unknown type\n", bktr_name(bktr)); |
7f5487a0 SS |
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, | |
77f47c61 | 1191 | lo2num; |
7f5487a0 SS |
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); | |
7f5487a0 SS |
1256 | |
1257 | if (lo1a < 0 || lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a < 0 || | |
1258 | lo2a > 7 || lo2n < 17 || lo2n > 30) { | |
e3869ec7 | 1259 | kprintf("MT2032: parameter out of range\n"); |
7f5487a0 SS |
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) | |
e3869ec7 | 1370 | kprintf("%s: PLL didn't lock\n", bktr_name(bktr)); |
7f5487a0 SS |
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) | |
e3869ec7 | 1400 | kprintf("%s: frequency set to %d, st = %#x, tad = %#x\n", |
7f5487a0 SS |
1401 | bktr_name(bktr), freq*62500, stat, tad); |
1402 | } | |
1403 | } |