1 | /* $Sourceforge: bktr_tuner.c,v 1.5 2003/03/13 22:21:04 emsi Exp $ */ |
2 | |
3 | /* $NetBSD: bktr_tuner.c,v 1.12 2007/10/19 12:01:03 ad Exp $ */ |
4 | /* $FreeBSD: src/sys/dev/bktr/bktr_tuner.c,v 1.9 2000/10/19 07:33:28 roger Exp$ */ |
5 | |
6 | /* |
7 | * This is part of the Driver for Video Capture Cards (Frame grabbers) |
8 | * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 |
9 | * chipset. |
10 | * Copyright Roger Hardiman and Amancio Hasty. |
11 | * |
12 | * bktr_tuner : This deals with controlling the tuner fitted to TV cards. |
13 | * |
14 | */ |
15 | |
16 | /* |
17 | * 1. Redistributions of source code must retain the |
18 | * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman |
19 | * All rights reserved. |
20 | * |
21 | * Redistribution and use in source and binary forms, with or without |
22 | * modification, are permitted provided that the following conditions |
23 | * are met: |
24 | * 1. Redistributions of source code must retain the above copyright |
25 | * notice, this list of conditions and the following disclaimer. |
26 | * 2. Redistributions in binary form must reproduce the above copyright |
27 | * notice, this list of conditions and the following disclaimer in the |
28 | * documentation and/or other materials provided with the distribution. |
29 | * 3. All advertising materials mentioning features or use of this software |
30 | * must display the following acknowledgement: |
31 | * This product includes software developed by Amancio Hasty and |
32 | * Roger Hardiman |
33 | * 4. The name of the author may not be used to endorse or promote products |
34 | * derived from this software without specific prior written permission. |
35 | * |
36 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
37 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
38 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
39 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
40 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
41 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
42 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
44 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
45 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
46 | * POSSIBILITY OF SUCH DAMAGE. |
47 | */ |
48 | |
49 | #include <sys/cdefs.h> |
50 | __KERNEL_RCSID(0, "$NetBSD: bktr_tuner.c,v 1.12 2007/10/19 12:01:03 ad Exp $" ); |
51 | |
52 | #include <sys/param.h> |
53 | #include <sys/systm.h> |
54 | #include <sys/kernel.h> |
55 | #include <sys/vnode.h> |
56 | #ifdef __NetBSD__ |
57 | #include <sys/proc.h> |
58 | #endif |
59 | |
60 | #ifdef __FreeBSD__ |
61 | #include <pci/pcivar.h> |
62 | |
63 | #if (__FreeBSD_version < 500000) |
64 | #include <machine/clock.h> /* for DELAY */ |
65 | #endif |
66 | |
67 | #if (__FreeBSD_version >=300000) |
68 | #include <machine/bus_memio.h> /* for bus space */ |
69 | #include <sys/bus.h> |
70 | #include <sys/bus.h> |
71 | #endif |
72 | #endif |
73 | |
74 | #ifdef __NetBSD__ |
75 | #include <dev/ic/bt8xx.h> /* NetBSD .h file location */ |
76 | #include <dev/pci/bktr/bktr_reg.h> |
77 | #include <dev/pci/bktr/bktr_tuner.h> |
78 | #include <dev/pci/bktr/bktr_card.h> |
79 | #include <dev/pci/bktr/bktr_core.h> |
80 | #else |
81 | #include <machine/ioctl_meteor.h> /* Traditional .h file location */ |
82 | #include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ |
83 | #include <dev/bktr/bktr_reg.h> |
84 | #include <dev/bktr/bktr_tuner.h> |
85 | #include <dev/bktr/bktr_card.h> |
86 | #include <dev/bktr/bktr_core.h> |
87 | #endif |
88 | |
89 | |
90 | |
91 | #if defined(TUNER_AFC) |
92 | #define AFC_DELAY 10000 /* 10 millisend delay */ |
93 | #define AFC_BITS 0x07 |
94 | #define AFC_FREQ_MINUS_125 0x00 |
95 | #define AFC_FREQ_MINUS_62 0x01 |
96 | #define AFC_FREQ_CENTERED 0x02 |
97 | #define AFC_FREQ_PLUS_62 0x03 |
98 | #define AFC_FREQ_PLUS_125 0x04 |
99 | #define AFC_MAX_STEP (5 * FREQFACTOR) /* no more than 5 MHz */ |
100 | #endif /* TUNER_AFC */ |
101 | |
102 | |
103 | #define TTYPE_XXX 0 |
104 | #define TTYPE_NTSC 1 |
105 | #define TTYPE_NTSC_J 2 |
106 | #define TTYPE_PAL 3 |
107 | #define TTYPE_PAL_M 4 |
108 | #define TTYPE_PAL_N 5 |
109 | #define TTYPE_SECAM 6 |
110 | |
111 | #define TSA552x_CB_MSB (0x80) |
112 | #define TSA552x_CB_CP (1<<6) /* set this for fast tuning */ |
113 | #define TSA552x_CB_T2 (1<<5) /* test mode - Normally set to 0 */ |
114 | #define TSA552x_CB_T1 (1<<4) /* test mode - Normally set to 0 */ |
115 | #define TSA552x_CB_T0 (1<<3) /* test mode - Normally set to 1 */ |
116 | #define TSA552x_CB_RSA (1<<2) /* 0 for 31.25 kHz, 1 for 62.5 kHz */ |
117 | #define TSA552x_CB_RSB (1<<1) /* 0 for FM 50kHz steps, 1 = Use RSA*/ |
118 | #define TSA552x_CB_OS (1<<0) /* Set to 0 for normal operation */ |
119 | |
120 | #define TSA552x_RADIO (TSA552x_CB_MSB | \ |
121 | TSA552x_CB_T0) |
122 | |
123 | /* raise the charge pump voltage for fast tuning */ |
124 | #define TSA552x_FCONTROL (TSA552x_CB_MSB | \ |
125 | TSA552x_CB_CP | \ |
126 | TSA552x_CB_T0 | \ |
127 | TSA552x_CB_RSA | \ |
128 | TSA552x_CB_RSB) |
129 | |
130 | /* lower the charge pump voltage for better residual oscillator FM */ |
131 | #define TSA552x_SCONTROL (TSA552x_CB_MSB | \ |
132 | TSA552x_CB_T0 | \ |
133 | TSA552x_CB_RSA | \ |
134 | TSA552x_CB_RSB) |
135 | |
136 | /* The control value for the ALPS TSCH5 Tuner */ |
137 | #define TSCH5_FCONTROL 0x82 |
138 | #define TSCH5_RADIO 0x86 |
139 | |
140 | /* The control value for the ALPS TSBH1 Tuner */ |
141 | #define TSBH1_FCONTROL 0xce |
142 | |
143 | |
144 | static const struct TUNER tuners[] = { |
145 | /* XXX FIXME: fill in the band-switch crosspoints */ |
146 | /* NO_TUNER */ |
147 | { "<no>" , /* the 'name' */ |
148 | TTYPE_XXX, /* input type */ |
149 | { 0x00, /* control byte for Tuner PLL */ |
150 | 0x00, |
151 | 0x00, |
152 | 0x00 }, |
153 | { 160, 454 }, /* band-switch crosspoints */ |
154 | { 0x00, 0x00, 0x00,0x00} }, /* the band-switch values */ |
155 | |
156 | /* TEMIC_NTSC */ |
157 | { "Temic NTSC" , /* the 'name' */ |
158 | TTYPE_NTSC, /* input type */ |
159 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
160 | TSA552x_SCONTROL, |
161 | TSA552x_SCONTROL, |
162 | 0x00 }, |
163 | { 160, 454 }, /* band-switch crosspoints */ |
164 | { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ |
165 | |
166 | /* TEMIC_PAL */ |
167 | { "Temic PAL" , /* the 'name' */ |
168 | TTYPE_PAL, /* input type */ |
169 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
170 | TSA552x_SCONTROL, |
171 | TSA552x_SCONTROL, |
172 | 0x00 }, |
173 | { 160, 454 }, /* band-switch crosspoints */ |
174 | { 0x02, 0x04, 0x01, 0x00 } }, /* the band-switch values */ |
175 | |
176 | /* TEMIC_SECAM */ |
177 | { "Temic SECAM" , /* the 'name' */ |
178 | TTYPE_SECAM, /* input type */ |
179 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
180 | TSA552x_SCONTROL, |
181 | TSA552x_SCONTROL, |
182 | 0x00 }, |
183 | { 160, 454 }, /* band-switch crosspoints */ |
184 | { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ |
185 | |
186 | /* PHILIPS_NTSC */ |
187 | { "Philips NTSC" , /* the 'name' */ |
188 | TTYPE_NTSC, /* input type */ |
189 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
190 | TSA552x_SCONTROL, |
191 | TSA552x_SCONTROL, |
192 | 0x00 }, |
193 | { 160, 454 }, /* band-switch crosspoints */ |
194 | { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ |
195 | |
196 | /* PHILIPS_PAL */ |
197 | { "Philips PAL" , /* the 'name' */ |
198 | TTYPE_PAL, /* input type */ |
199 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
200 | TSA552x_SCONTROL, |
201 | TSA552x_SCONTROL, |
202 | 0x00 }, |
203 | { 160, 454 }, /* band-switch crosspoints */ |
204 | { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */ |
205 | |
206 | /* PHILIPS_SECAM */ |
207 | { "Philips SECAM" , /* the 'name' */ |
208 | TTYPE_SECAM, /* input type */ |
209 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
210 | TSA552x_SCONTROL, |
211 | TSA552x_SCONTROL, |
212 | 0x00 }, |
213 | { 160, 454 }, /* band-switch crosspoints */ |
214 | { 0xa7, 0x97, 0x37, 0x00 } }, /* the band-switch values */ |
215 | |
216 | /* TEMIC_PAL I */ |
217 | { "Temic PAL I" , /* the 'name' */ |
218 | TTYPE_PAL, /* input type */ |
219 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
220 | TSA552x_SCONTROL, |
221 | TSA552x_SCONTROL, |
222 | 0x00 }, |
223 | { 160, 454 }, /* band-switch crosspoints */ |
224 | { 0x02, 0x04, 0x01,0x00 } }, /* the band-switch values */ |
225 | |
226 | /* PHILIPS_PALI */ |
227 | { "Philips PAL I" , /* the 'name' */ |
228 | TTYPE_PAL, /* input type */ |
229 | { TSA552x_SCONTROL, /* control byte for Tuner PLL */ |
230 | TSA552x_SCONTROL, |
231 | TSA552x_SCONTROL, |
232 | 0x00 }, |
233 | { 160, 454 }, /* band-switch crosspoints */ |
234 | { 0xa0, 0x90, 0x30,0x00 } }, /* the band-switch values */ |
235 | |
236 | /* PHILIPS_FR1236_NTSC */ |
237 | { "Philips FR1236 NTSC FM" , /* the 'name' */ |
238 | TTYPE_NTSC, /* input type */ |
239 | { TSA552x_FCONTROL, /* control byte for Tuner PLL */ |
240 | TSA552x_FCONTROL, |
241 | TSA552x_FCONTROL, |
242 | TSA552x_RADIO }, |
243 | { 160, 454 }, /* band-switch crosspoints */ |
244 | { 0xa0, 0x90, 0x30,0xa4 } }, /* the band-switch values */ |
245 | |
246 | /* PHILIPS_FR1216_PAL */ |
247 | { "Philips FR1216 PAL FM" , /* the 'name' */ |
248 | TTYPE_PAL, /* input type */ |
249 | { TSA552x_FCONTROL, /* control byte for Tuner PLL */ |
250 | TSA552x_FCONTROL, |
251 | TSA552x_FCONTROL, |
252 | TSA552x_RADIO }, |
253 | { 160, 454 }, /* band-switch crosspoints */ |
254 | { 0xa0, 0x90, 0x30, 0xa4 } }, /* the band-switch values */ |
255 | |
256 | /* PHILIPS_FR1236_SECAM */ |
257 | { "Philips FR1236 SECAM FM" , /* the 'name' */ |
258 | TTYPE_SECAM, /* input type */ |
259 | { TSA552x_FCONTROL, /* control byte for Tuner PLL */ |
260 | TSA552x_FCONTROL, |
261 | TSA552x_FCONTROL, |
262 | TSA552x_RADIO }, |
263 | { 160, 454 }, /* band-switch crosspoints */ |
264 | { 0xa7, 0x97, 0x37, 0xa4 } }, /* the band-switch values */ |
265 | |
266 | /* ALPS TSCH5 NTSC */ |
267 | { "ALPS TSCH5 NTSC FM" , /* the 'name' */ |
268 | TTYPE_NTSC, /* input type */ |
269 | { TSCH5_FCONTROL, /* control byte for Tuner PLL */ |
270 | TSCH5_FCONTROL, |
271 | TSCH5_FCONTROL, |
272 | TSCH5_RADIO }, |
273 | { 160, 454 }, /* band-switch crosspoints */ |
274 | { 0x14, 0x12, 0x11, 0x04 } }, /* the band-switch values */ |
275 | |
276 | /* ALPS TSBH1 NTSC */ |
277 | { "ALPS TSBH1 NTSC" , /* the 'name' */ |
278 | TTYPE_NTSC, /* input type */ |
279 | { TSBH1_FCONTROL, /* control byte for Tuner PLL */ |
280 | TSBH1_FCONTROL, |
281 | TSBH1_FCONTROL, |
282 | 0x00 }, |
283 | { 160, 454 }, /* band-switch crosspoints */ |
284 | { 0x01, 0x02, 0x08, 0x00 } } /* the band-switch values */ |
285 | }; |
286 | |
287 | |
288 | /* scaling factor for frequencies expressed as ints */ |
289 | #define FREQFACTOR 16 |
290 | |
291 | /* |
292 | * Format: |
293 | * entry 0: MAX legal channel |
294 | * entry 1: IF frequency |
295 | * expressed as fi{MHz} * 16, |
296 | * eg 45.75MHz == 45.75 * 16 = 732 |
297 | * entry 2: [place holder/future] |
298 | * entry 3: base of channel record 0 |
299 | * entry 3 + (x*3): base of channel record 'x' |
300 | * entry LAST: NULL channel entry marking end of records |
301 | * |
302 | * Record: |
303 | * int 0: base channel |
304 | * int 1: frequency of base channel, |
305 | * expressed as fb{MHz} * 16, |
306 | * int 2: offset frequency between channels, |
307 | * expressed as fo{MHz} * 16, |
308 | */ |
309 | |
310 | /* |
311 | * North American Broadcast Channels: |
312 | * |
313 | * 2: 55.25 MHz - 4: 67.25 MHz |
314 | * 5: 77.25 MHz - 6: 83.25 MHz |
315 | * 7: 175.25 MHz - 13: 211.25 MHz |
316 | * 14: 471.25 MHz - 83: 885.25 MHz |
317 | * |
318 | * IF freq: 45.75 MHz |
319 | */ |
320 | #define OFFSET 6.00 |
321 | static const int nabcst[] = { |
322 | 83, (int)( 45.75 * FREQFACTOR), 0, |
323 | 14, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
324 | 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
325 | 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
326 | 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
327 | 0 |
328 | }; |
329 | #undef OFFSET |
330 | |
331 | /* |
332 | * North American Cable Channels, IRC: |
333 | * |
334 | * 2: 55.25 MHz - 4: 67.25 MHz |
335 | * 5: 77.25 MHz - 6: 83.25 MHz |
336 | * 7: 175.25 MHz - 13: 211.25 MHz |
337 | * 14: 121.25 MHz - 22: 169.25 MHz |
338 | * 23: 217.25 MHz - 94: 643.25 MHz |
339 | * 95: 91.25 MHz - 99: 115.25 MHz |
340 | * |
341 | * IF freq: 45.75 MHz |
342 | */ |
343 | #define OFFSET 6.00 |
344 | static const int irccable[] = { |
345 | 116, (int)( 45.75 * FREQFACTOR), 0, |
346 | 100, (int)(649.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
347 | 95, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
348 | 23, (int)(217.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
349 | 14, (int)(121.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
350 | 7, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
351 | 5, (int)( 77.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
352 | 2, (int)( 55.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
353 | 0 |
354 | }; |
355 | #undef OFFSET |
356 | |
357 | /* |
358 | * North American Cable Channels, HRC: |
359 | * |
360 | * 2: 54 MHz - 4: 66 MMz |
361 | * 5: 78 MHz - 6: 84 MHz |
362 | * 7: 174 MHz - 13: 210 MHz |
363 | * 14: 120 MHz - 22: 168 MHz |
364 | * 23: 216 MHz - 94: 642 MHz |
365 | * 95: 90 MHz - 99: 114 MHz |
366 | * |
367 | * IF freq: 45.75 MHz |
368 | */ |
369 | #define OFFSET 6.00 |
370 | static const int hrccable[] = { |
371 | 116, (int)( 45.75 * FREQFACTOR), 0, |
372 | 100, (int)(648.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
373 | 95, (int)( 90.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
374 | 23, (int)(216.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
375 | 14, (int)(120.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
376 | 7, (int)(174.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
377 | 5, (int)( 78.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
378 | 2, (int)( 54.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
379 | 0 |
380 | }; |
381 | #undef OFFSET |
382 | |
383 | /* |
384 | * Western European broadcast channels: |
385 | * |
386 | * (there are others that appear to vary between countries - rmt) |
387 | * |
388 | * here's the table Philips provides: |
389 | * caution, some of the offsets don't compute... |
390 | * |
391 | * 1 4525 700 N21 |
392 | * |
393 | * 2 4825 700 E2 |
394 | * 3 5525 700 E3 |
395 | * 4 6225 700 E4 |
396 | * |
397 | * 5 17525 700 E5 |
398 | * 6 18225 700 E6 |
399 | * 7 18925 700 E7 |
400 | * 8 19625 700 E8 |
401 | * 9 20325 700 E9 |
402 | * 10 21025 700 E10 |
403 | * 11 21725 700 E11 |
404 | * 12 22425 700 E12 |
405 | * |
406 | * 13 5375 700 ITA |
407 | * 14 6225 700 ITB |
408 | * |
409 | * 15 8225 700 ITC |
410 | * |
411 | * 16 17525 700 ITD |
412 | * 17 18325 700 ITE |
413 | * |
414 | * 18 19225 700 ITF |
415 | * 19 20125 700 ITG |
416 | * 20 21025 700 ITH |
417 | * |
418 | * 21 47125 800 E21 |
419 | * 22 47925 800 E22 |
420 | * 23 48725 800 E23 |
421 | * 24 49525 800 E24 |
422 | * 25 50325 800 E25 |
423 | * 26 51125 800 E26 |
424 | * 27 51925 800 E27 |
425 | * 28 52725 800 E28 |
426 | * 29 53525 800 E29 |
427 | * 30 54325 800 E30 |
428 | * 31 55125 800 E31 |
429 | * 32 55925 800 E32 |
430 | * 33 56725 800 E33 |
431 | * 34 57525 800 E34 |
432 | * 35 58325 800 E35 |
433 | * 36 59125 800 E36 |
434 | * 37 59925 800 E37 |
435 | * 38 60725 800 E38 |
436 | * 39 61525 800 E39 |
437 | * 40 62325 800 E40 |
438 | * 41 63125 800 E41 |
439 | * 42 63925 800 E42 |
440 | * 43 64725 800 E43 |
441 | * 44 65525 800 E44 |
442 | * 45 66325 800 E45 |
443 | * 46 67125 800 E46 |
444 | * 47 67925 800 E47 |
445 | * 48 68725 800 E48 |
446 | * 49 69525 800 E49 |
447 | * 50 70325 800 E50 |
448 | * 51 71125 800 E51 |
449 | * 52 71925 800 E52 |
450 | * 53 72725 800 E53 |
451 | * 54 73525 800 E54 |
452 | * 55 74325 800 E55 |
453 | * 56 75125 800 E56 |
454 | * 57 75925 800 E57 |
455 | * 58 76725 800 E58 |
456 | * 59 77525 800 E59 |
457 | * 60 78325 800 E60 |
458 | * 61 79125 800 E61 |
459 | * 62 79925 800 E62 |
460 | * 63 80725 800 E63 |
461 | * 64 81525 800 E64 |
462 | * 65 82325 800 E65 |
463 | * 66 83125 800 E66 |
464 | * 67 83925 800 E67 |
465 | * 68 84725 800 E68 |
466 | * 69 85525 800 E69 |
467 | * |
468 | * 70 4575 800 IA |
469 | * 71 5375 800 IB |
470 | * 72 6175 800 IC |
471 | * |
472 | * 74 6925 700 S01 |
473 | * 75 7625 700 S02 |
474 | * 76 8325 700 S03 |
475 | * |
476 | * 80 10525 700 S1 |
477 | * 81 11225 700 S2 |
478 | * 82 11925 700 S3 |
479 | * 83 12625 700 S4 |
480 | * 84 13325 700 S5 |
481 | * 85 14025 700 S6 |
482 | * 86 14725 700 S7 |
483 | * 87 15425 700 S8 |
484 | * 88 16125 700 S9 |
485 | * 89 16825 700 S10 |
486 | * 90 23125 700 S11 |
487 | * 91 23825 700 S12 |
488 | * 92 24525 700 S13 |
489 | * 93 25225 700 S14 |
490 | * 94 25925 700 S15 |
491 | * 95 26625 700 S16 |
492 | * 96 27325 700 S17 |
493 | * 97 28025 700 S18 |
494 | * 98 28725 700 S19 |
495 | * 99 29425 700 S20 |
496 | * |
497 | * |
498 | * Channels S21 - S41 are taken from |
499 | * http://gemma.apple.com:80/dev/technotes/tn/tn1012.html |
500 | * |
501 | * 100 30325 800 S21 |
502 | * 101 31125 800 S22 |
503 | * 102 31925 800 S23 |
504 | * 103 32725 800 S24 |
505 | * 104 33525 800 S25 |
506 | * 105 34325 800 S26 |
507 | * 106 35125 800 S27 |
508 | * 107 35925 800 S28 |
509 | * 108 36725 800 S29 |
510 | * 109 37525 800 S30 |
511 | * 110 38325 800 S31 |
512 | * 111 39125 800 S32 |
513 | * 112 39925 800 S33 |
514 | * 113 40725 800 S34 |
515 | * 114 41525 800 S35 |
516 | * 115 42325 800 S36 |
517 | * 116 43125 800 S37 |
518 | * 117 43925 800 S38 |
519 | * 118 44725 800 S39 |
520 | * 119 45525 800 S40 |
521 | * 120 46325 800 S41 |
522 | * |
523 | * 121 3890 000 IFFREQ |
524 | * |
525 | */ |
526 | static const int weurope[] = { |
527 | 121, (int)( 38.90 * FREQFACTOR), 0, |
528 | 100, (int)(303.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
529 | 90, (int)(231.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), |
530 | 80, (int)(105.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), |
531 | 74, (int)( 69.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), |
532 | 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
533 | 17, (int)(183.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), |
534 | 16, (int)(175.25 * FREQFACTOR), (int)(9.00 * FREQFACTOR), |
535 | 15, (int)( 82.25 * FREQFACTOR), (int)(8.50 * FREQFACTOR), |
536 | 13, (int)( 53.75 * FREQFACTOR), (int)(8.50 * FREQFACTOR), |
537 | 5, (int)(175.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), |
538 | 2, (int)( 48.25 * FREQFACTOR), (int)(7.00 * FREQFACTOR), |
539 | 0 |
540 | }; |
541 | |
542 | /* |
543 | * Japanese Broadcast Channels: |
544 | * |
545 | * 1: 91.25MHz - 3: 103.25MHz |
546 | * 4: 171.25MHz - 7: 189.25MHz |
547 | * 8: 193.25MHz - 12: 217.25MHz (VHF) |
548 | * 13: 471.25MHz - 62: 765.25MHz (UHF) |
549 | * |
550 | * IF freq: 45.75 MHz |
551 | * OR |
552 | * IF freq: 58.75 MHz |
553 | */ |
554 | #define OFFSET 6.00 |
555 | #define IF_FREQ 45.75 |
556 | static const int jpnbcst[] = { |
557 | 62, (int)(IF_FREQ * FREQFACTOR), 0, |
558 | 13, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
559 | 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
560 | 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
561 | 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
562 | 0 |
563 | }; |
564 | #undef IF_FREQ |
565 | #undef OFFSET |
566 | |
567 | /* |
568 | * Japanese Cable Channels: |
569 | * |
570 | * 1: 91.25MHz - 3: 103.25MHz |
571 | * 4: 171.25MHz - 7: 189.25MHz |
572 | * 8: 193.25MHz - 12: 217.25MHz |
573 | * 13: 109.25MHz - 21: 157.25MHz |
574 | * 22: 165.25MHz |
575 | * 23: 223.25MHz - 63: 463.25MHz |
576 | * |
577 | * IF freq: 45.75 MHz |
578 | */ |
579 | #define OFFSET 6.00 |
580 | #define IF_FREQ 45.75 |
581 | static const int jpncable[] = { |
582 | 63, (int)(IF_FREQ * FREQFACTOR), 0, |
583 | 23, (int)(223.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
584 | 22, (int)(165.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
585 | 13, (int)(109.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
586 | 8, (int)(193.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
587 | 4, (int)(171.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
588 | 1, (int)( 91.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
589 | 0 |
590 | }; |
591 | #undef IF_FREQ |
592 | #undef OFFSET |
593 | |
594 | /* |
595 | * xUSSR Broadcast Channels: |
596 | * |
597 | * 1: 49.75MHz - 2: 59.25MHz |
598 | * 3: 77.25MHz - 5: 93.25MHz |
599 | * 6: 175.25MHz - 12: 223.25MHz |
600 | * 13-20 - not exist |
601 | * 21: 471.25MHz - 34: 575.25MHz |
602 | * 35: 583.25MHz - 69: 855.25MHz |
603 | * |
604 | * Cable channels |
605 | * |
606 | * 70: 111.25MHz - 77: 167.25MHz |
607 | * 78: 231.25MHz -107: 463.25MHz |
608 | * |
609 | * IF freq: 38.90 MHz |
610 | */ |
611 | #define IF_FREQ 38.90 |
612 | static const int xussr[] = { |
613 | 107, (int)(IF_FREQ * FREQFACTOR), 0, |
614 | 78, (int)(231.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
615 | 70, (int)(111.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
616 | 35, (int)(583.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
617 | 21, (int)(471.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
618 | 6, (int)(175.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
619 | 3, (int)( 77.25 * FREQFACTOR), (int)(8.00 * FREQFACTOR), |
620 | 1, (int)( 49.75 * FREQFACTOR), (int)(9.50 * FREQFACTOR), |
621 | 0 |
622 | }; |
623 | #undef IF_FREQ |
624 | |
625 | /* |
626 | * Australian broadcast channels |
627 | */ |
628 | #define OFFSET 7.00 |
629 | #define IF_FREQ 38.90 |
630 | static const int australia[] = { |
631 | 83, (int)(IF_FREQ * FREQFACTOR), 0, |
632 | 28, (int)(527.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
633 | 10, (int)(209.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
634 | 6, (int)(175.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
635 | 4, (int)( 95.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
636 | 3, (int)( 86.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
637 | 1, (int)( 57.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), |
638 | 0 |
639 | }; |
640 | #undef OFFSET |
641 | #undef IF_FREQ |
642 | |
643 | /* |
644 | * France broadcast channels |
645 | */ |
646 | #define OFFSET 8.00 |
647 | #define IF_FREQ 38.90 |
648 | static const int france[] = { |
649 | 69, (int)(IF_FREQ * FREQFACTOR), 0, |
650 | 21, (int)(471.25 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 21 -> 69 */ |
651 | 5, (int)(176.00 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 5 -> 10 */ |
652 | 4, (int)( 63.75 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 4 */ |
653 | 3, (int)( 60.50 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 3 */ |
654 | 1, (int)( 47.75 * FREQFACTOR), (int)(OFFSET * FREQFACTOR), /* 1 2 */ |
655 | 0 |
656 | }; |
657 | #undef OFFSET |
658 | #undef IF_FREQ |
659 | |
660 | static const struct { |
661 | const int *ptr; |
662 | const char name[BT848_MAX_CHNLSET_NAME_LEN]; |
663 | } freqTable[] = { |
664 | {NULL, "" }, |
665 | {nabcst, "nabcst" }, |
666 | {irccable, "cableirc" }, |
667 | {hrccable, "cablehrc" }, |
668 | {weurope, "weurope" }, |
669 | {jpnbcst, "jpnbcst" }, |
670 | {jpncable, "jpncable" }, |
671 | {xussr, "xussr" }, |
672 | {australia, "australia" }, |
673 | {france, "france" }, |
674 | |
675 | }; |
676 | |
677 | #define TBL_CHNL freqTable[bktr->tuner.chnlset].ptr[x] |
678 | #define TBL_BASE_FREQ freqTable[bktr->tuner.chnlset].ptr[x + 1] |
679 | #define TBL_OFFSET freqTable[bktr->tuner.chnlset].ptr[x + 2] |
680 | static int |
681 | frequency_lookup(bktr_ptr_t bktr, int channel) |
682 | { |
683 | int x; |
684 | |
685 | /* check for "> MAX channel" */ |
686 | x = 0; |
687 | if (channel > TBL_CHNL) |
688 | return(-1); |
689 | |
690 | /* search the table for data */ |
691 | for (x = 3; TBL_CHNL; x += 3) { |
692 | if (channel >= TBL_CHNL) { |
693 | return(TBL_BASE_FREQ + |
694 | ((channel - TBL_CHNL) * TBL_OFFSET)); |
695 | } |
696 | } |
697 | |
698 | /* not found, must be below the MIN channel */ |
699 | return(-1); |
700 | } |
701 | #undef TBL_OFFSET |
702 | #undef TBL_BASE_FREQ |
703 | #undef TBL_CHNL |
704 | |
705 | |
706 | #define TBL_IF freqTable[bktr->tuner.chnlset].ptr[1] |
707 | |
708 | |
709 | /* Initialise the tuner structures in the bktr_softc */ |
710 | /* This is needed as the tuner details are no longer globally declared */ |
711 | |
712 | void select_tuner(bktr_ptr_t bktr, int tuner_type) { |
713 | if (tuner_type < Bt848_MAX_TUNER) { |
714 | bktr->card.tuner = &tuners[tuner_type]; |
715 | } else { |
716 | bktr->card.tuner = NULL; |
717 | } |
718 | } |
719 | |
720 | /* |
721 | * Tuner Notes: |
722 | * Programming the tuner properly is quite complicated. |
723 | * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner. |
724 | * The tuner (front end) covers 45.75 MHz - 855.25 MHz and an FM band of |
725 | * 87.5 MHz to 108.0 MHz. |
726 | * |
727 | * RF and IF. RF = radio frequencies, it is the transmitted signal. |
728 | * IF is the Intermediate Frequency (the offset from the base |
729 | * signal where the video, color, audio and NICAM signals are. |
730 | * |
731 | * Eg, Picture at 38.9 MHz, Colour at 34.47 MHz, sound at 32.9 MHz |
732 | * NICAM at 32.348 MHz. |
733 | * Strangely enough, there is an IF (intermediate frequency) for |
734 | * FM Radio which is 10.7 MHz. |
735 | * |
736 | * The tuner also works in Bands. Philips bands are |
737 | * FM radio band 87.50 to 108.00 MHz |
738 | * Low band 45.75 to 170.00 MHz |
739 | * Mid band 170.00 to 450.00 MHz |
740 | * High band 450.00 to 855.25 MHz |
741 | * |
742 | * |
743 | * Now we need to set the PLL on the tuner to the required freuqncy. |
744 | * It has a programmable divisor. |
745 | * For TV we want |
746 | * N = 16 (freq RF(pc) + freq IF(pc)) pc is picture carrier and RF and IF |
747 | * are in MHz. |
748 | |
749 | * For RADIO we want a different equation. |
750 | * freq IF is 10.70 MHz (so the data sheet tells me) |
751 | * N = (freq RF + freq IF) / step size |
752 | * The step size must be set to 50 kHz (so the data sheet tells me) |
753 | * (note this is 50 kHz, the other things are in MHz) |
754 | * so we end up with N = 20x(freq RF + 10.7) |
755 | * |
756 | */ |
757 | |
758 | #define LOW_BAND 0 |
759 | #define MID_BAND 1 |
760 | #define HIGH_BAND 2 |
761 | #define FM_RADIO_BAND 3 |
762 | |
763 | |
764 | /* Check if these are correct for other than Philips PAL */ |
765 | #define STATUSBIT_COLD 0x80 |
766 | #define STATUSBIT_LOCK 0x40 |
767 | #define STATUSBIT_TV 0x20 |
768 | #define STATUSBIT_STEREO 0x10 /* valid if FM (aka not TV) */ |
769 | #define STATUSBIT_ADC 0x07 |
770 | |
771 | /* |
772 | * set the frequency of the tuner |
773 | * If 'type' is TV_FREQUENCY, the frequency is freq MHz*16 |
774 | * If 'type' is FM_RADIO_FREQUENCY, the frequency is freq MHz * 100 |
775 | * (note *16 gives is 4 bits of fraction, eg steps of nnn.0625) |
776 | * |
777 | */ |
778 | int |
779 | tv_freq(bktr_ptr_t bktr, int frequency, int type) |
780 | { |
781 | const struct TUNER* tuner; |
782 | u_char addr; |
783 | u_char control; |
784 | u_char band; |
785 | int N; |
786 | int band_select = 0; |
787 | #if defined(TEST_TUNER_AFC) |
788 | int oldFrequency, afcDelta; |
789 | #endif |
790 | |
791 | tuner = bktr->card.tuner; |
792 | if (tuner == NULL) |
793 | return(-1); |
794 | |
795 | if (type == TV_FREQUENCY) { |
796 | /* |
797 | * select the band based on frequency |
798 | */ |
799 | if (frequency < (tuner->bandLimits[0] * FREQFACTOR)) |
800 | band_select = LOW_BAND; |
801 | else if (frequency < (tuner->bandLimits[1] * FREQFACTOR)) |
802 | band_select = MID_BAND; |
803 | else |
804 | band_select = HIGH_BAND; |
805 | |
806 | #if defined(TEST_TUNER_AFC) |
807 | if (bktr->tuner.afc) |
808 | frequency -= 4; |
809 | #endif |
810 | /* |
811 | * N = 16 * { fRF(pc) + fIF(pc) } |
812 | * or N = 16* fRF(pc) + 16*fIF(pc) } |
813 | * where: |
814 | * pc is picture carrier, fRF & fIF are in MHz |
815 | * |
816 | * fortunatly, frequency is passed in as MHz * 16 |
817 | * and the TBL_IF frequency is also stored in MHz * 16 |
818 | */ |
819 | N = frequency + TBL_IF; |
820 | |
821 | /* set the address of the PLL */ |
822 | addr = bktr->card.tuner_pllAddr; |
823 | control = tuner->pllControl[band_select]; |
824 | band = tuner->bandAddrs[band_select]; |
825 | |
826 | if(!(band && control)) /* Don't try to set un- */ |
827 | return(-1); /* supported modes. */ |
828 | |
829 | if (frequency > bktr->tuner.frequency) { |
830 | i2cWrite(bktr, addr, (N>>8) & 0x7f, N & 0xff); |
831 | i2cWrite(bktr, addr, control, band); |
832 | } |
833 | else { |
834 | i2cWrite(bktr, addr, control, band); |
835 | i2cWrite(bktr, addr, (N>>8) & 0x7f, N & 0xff); |
836 | } |
837 | |
838 | #if defined(TUNER_AFC) |
839 | if (bktr->tuner.afc == TRUE) { |
840 | #if defined(TEST_TUNER_AFC) |
841 | oldFrequency = frequency; |
842 | #endif |
843 | if ((N = do_afc(bktr, addr, N)) < 0) { |
844 | /* AFC failed, restore requested frequency */ |
845 | N = frequency + TBL_IF; |
846 | #if defined(TEST_TUNER_AFC) |
847 | printf("%s: do_afc: failed to lock\n" , |
848 | bktr_name(bktr)); |
849 | #endif |
850 | i2cWrite(bktr, addr, (N>>8) & 0x7f, N & 0xff); |
851 | } |
852 | else |
853 | frequency = N - TBL_IF; |
854 | #if defined(TEST_TUNER_AFC) |
855 | printf("%s: do_afc: returned freq %d (%d %% %d)\n" , bktr_name(bktr), frequency, frequency / 16, frequency % 16); |
856 | afcDelta = frequency - oldFrequency; |
857 | printf("%s: changed by: %d clicks (%d mod %d)\n" , bktr_name(bktr), afcDelta, afcDelta / 16, afcDelta % 16); |
858 | #endif |
859 | } |
860 | #endif /* TUNER_AFC */ |
861 | |
862 | bktr->tuner.frequency = frequency; |
863 | } |
864 | |
865 | if (type == FM_RADIO_FREQUENCY) { |
866 | band_select = FM_RADIO_BAND; |
867 | |
868 | /* |
869 | * N = { fRF(pc) + fIF(pc) }/step_size |
870 | * The step size is 50kHz for FM radio. |
871 | * (eg after 102.35MHz comes 102.40 MHz) |
872 | * fIF is 10.7 MHz (as detailed in the specs) |
873 | * |
874 | * frequency is passed in as MHz * 100 |
875 | * |
876 | * So, we have N = (frequency/100 + 10.70) /(50/1000) |
877 | */ |
878 | N = (frequency + 1070)/5; |
879 | |
880 | /* set the address of the PLL */ |
881 | addr = bktr->card.tuner_pllAddr; |
882 | control = tuner->pllControl[band_select]; |
883 | band = tuner->bandAddrs[band_select]; |
884 | |
885 | if(!(band && control)) /* Don't try to set un- */ |
886 | return(-1); /* supported modes. */ |
887 | |
888 | band |= bktr->tuner.radio_mode; /* tuner.radio_mode is set in |
889 | * the ioctls RADIO_SETMODE |
890 | * and RADIO_GETMODE */ |
891 | |
892 | i2cWrite(bktr, addr, control, band); |
893 | i2cWrite(bktr, addr, (N>>8) & 0x7f, N & 0xff); |
894 | |
895 | bktr->tuner.frequency = (N * 5) - 1070; |
896 | |
897 | |
898 | } |
899 | |
900 | |
901 | return(0); |
902 | } |
903 | |
904 | |
905 | |
906 | #if defined(TUNER_AFC) |
907 | /* |
908 | * |
909 | */ |
910 | int |
911 | do_afc(bktr_ptr_t bktr, int addr, int frequency) |
912 | { |
913 | int step; |
914 | int status; |
915 | int origFrequency; |
916 | |
917 | origFrequency = frequency; |
918 | |
919 | /* wait for first setting to take effect */ |
920 | tsleep(BKTR_SLEEP, PZERO, "tuning" , hz/8); |
921 | |
922 | if ((status = i2cRead(bktr, addr + 1)) < 0) |
923 | return(-1); |
924 | |
925 | #if defined(TEST_TUNER_AFC) |
926 | printf("%s: Original freq: %d, status: 0x%02x\n" , bktr_name(bktr), frequency, status); |
927 | #endif |
928 | for (step = 0; step < AFC_MAX_STEP; ++step) { |
929 | if ((status = i2cRead(bktr, addr + 1)) < 0) |
930 | goto fubar; |
931 | if (!(status & 0x40)) { |
932 | #if defined(TEST_TUNER_AFC) |
933 | printf("%s: no lock!\n" , bktr_name(bktr)); |
934 | #endif |
935 | goto fubar; |
936 | } |
937 | |
938 | switch(status & AFC_BITS) { |
939 | case AFC_FREQ_CENTERED: |
940 | #if defined(TEST_TUNER_AFC) |
941 | printf("%s: Centered, freq: %d, status: 0x%02x\n" , bktr_name(bktr), frequency, status); |
942 | #endif |
943 | return(frequency); |
944 | |
945 | case AFC_FREQ_MINUS_125: |
946 | case AFC_FREQ_MINUS_62: |
947 | #if defined(TEST_TUNER_AFC) |
948 | printf("%s: Low, freq: %d, status: 0x%02x\n" , bktr_name(bktr), frequency, status); |
949 | #endif |
950 | --frequency; |
951 | break; |
952 | |
953 | case AFC_FREQ_PLUS_62: |
954 | case AFC_FREQ_PLUS_125: |
955 | #if defined(TEST_TUNER_AFC) |
956 | printf("%s: Hi, freq: %d, status: 0x%02x\n" , bktr_name(bktr), frequency, status); |
957 | #endif |
958 | ++frequency; |
959 | break; |
960 | } |
961 | |
962 | i2cWrite(bktr, addr, |
963 | (frequency>>8) & 0x7f, frequency & 0xff); |
964 | DELAY(AFC_DELAY); |
965 | } |
966 | |
967 | fubar: |
968 | i2cWrite(bktr, addr, |
969 | (origFrequency>>8) & 0x7f, origFrequency & 0xff); |
970 | |
971 | return(-1); |
972 | } |
973 | #endif /* TUNER_AFC */ |
974 | #undef TBL_IF |
975 | |
976 | |
977 | /* |
978 | * Get the Tuner status and signal strength |
979 | */ |
980 | int get_tuner_status(bktr_ptr_t bktr) { |
981 | return i2cRead(bktr, bktr->card.tuner_pllAddr + 1); |
982 | } |
983 | |
984 | /* |
985 | * set the channel of the tuner |
986 | */ |
987 | int |
988 | tv_channel(bktr_ptr_t bktr, int channel) |
989 | { |
990 | int frequency; |
991 | |
992 | /* calculate the frequency according to tuner type */ |
993 | if ((frequency = frequency_lookup(bktr, channel)) < 0) |
994 | return(-1); |
995 | |
996 | /* set the new frequency */ |
997 | if (tv_freq(bktr, frequency, TV_FREQUENCY) < 0) |
998 | return(-1); |
999 | |
1000 | /* OK to update records */ |
1001 | return((bktr->tuner.channel = channel)); |
1002 | } |
1003 | |
1004 | /* |
1005 | * get channelset name |
1006 | */ |
1007 | int |
1008 | tuner_getchnlset(struct bktr_chnlset *chnlset) |
1009 | { |
1010 | if ((chnlset->index < CHNLSET_MIN) || |
1011 | (chnlset->index > CHNLSET_MAX)) |
1012 | return(EINVAL); |
1013 | |
1014 | memcpy(&chnlset->name, &freqTable[chnlset->index].name, |
1015 | BT848_MAX_CHNLSET_NAME_LEN); |
1016 | |
1017 | chnlset->max_channel=freqTable[chnlset->index].ptr[0]; |
1018 | return(0); |
1019 | } |
1020 | |