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