| 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 | |