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