Deleted Added
full compact
bktr_tuner.c (131180) bktr_tuner.c (138936)
1/*-
2 * 1. Redistributions of source code must retain the
3 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 18 unchanged lines hidden (view full) ---

27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
1/*-
2 * 1. Redistributions of source code must retain the
3 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 18 unchanged lines hidden (view full) ---

27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_tuner.c 131180 2004-06-27 09:59:02Z schweikh $");
35__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_tuner.c 138936 2004-12-16 23:37:41Z julian $");
36
37/*
38 * This is part of the Driver for Video Capture Cards (Frame grabbers)
39 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
40 * chipset.
41 * Copyright Roger Hardiman and Amancio Hasty.
42 *
43 * bktr_tuner : This deals with controlling the tuner fitted to TV cards.

--- 87 unchanged lines hidden (view full) ---

131/* The control value for the ALPS TSCH5 Tuner */
132#define TSCH5_FCONTROL 0x82
133#define TSCH5_RADIO 0x86
134
135/* The control value for the ALPS TSBH1 Tuner */
136#define TSBH1_FCONTROL 0xce
137
138
36
37/*
38 * This is part of the Driver for Video Capture Cards (Frame grabbers)
39 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
40 * chipset.
41 * Copyright Roger Hardiman and Amancio Hasty.
42 *
43 * bktr_tuner : This deals with controlling the tuner fitted to TV cards.

--- 87 unchanged lines hidden (view full) ---

131/* The control value for the ALPS TSCH5 Tuner */
132#define TSCH5_FCONTROL 0x82
133#define TSCH5_RADIO 0x86
134
135/* The control value for the ALPS TSBH1 Tuner */
136#define TSBH1_FCONTROL 0xce
137
138
139static void mt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq);
140static int mt2032_init(bktr_ptr_t bktr);
141
142
139static const struct TUNER tuners[] = {
140/* XXX FIXME: fill in the band-switch crosspoints */
141 /* NO_TUNER */
142 { "<no>", /* the 'name' */
143 TTYPE_XXX, /* input type */
144 { 0x00, /* control byte for Tuner PLL */
145 0x00,
146 0x00,

--- 124 unchanged lines hidden (view full) ---

271 /* ALPS TSBH1 NTSC */
272 { "ALPS TSBH1 NTSC", /* the 'name' */
273 TTYPE_NTSC, /* input type */
274 { TSBH1_FCONTROL, /* control byte for Tuner PLL */
275 TSBH1_FCONTROL,
276 TSBH1_FCONTROL,
277 0x00 },
278 { 0x00, 0x00 }, /* band-switch crosspoints */
143static const struct TUNER tuners[] = {
144/* XXX FIXME: fill in the band-switch crosspoints */
145 /* NO_TUNER */
146 { "<no>", /* the 'name' */
147 TTYPE_XXX, /* input type */
148 { 0x00, /* control byte for Tuner PLL */
149 0x00,
150 0x00,

--- 124 unchanged lines hidden (view full) ---

275 /* ALPS TSBH1 NTSC */
276 { "ALPS TSBH1 NTSC", /* the 'name' */
277 TTYPE_NTSC, /* input type */
278 { TSBH1_FCONTROL, /* control byte for Tuner PLL */
279 TSBH1_FCONTROL,
280 TSBH1_FCONTROL,
281 0x00 },
282 { 0x00, 0x00 }, /* band-switch crosspoints */
279 { 0x01, 0x02, 0x08, 0x00 } } /* the band-switch values */
283 { 0x01, 0x02, 0x08, 0x00 } }, /* the band-switch values */
284
285 /* MT2032 Microtune */
286 { "MT2032", /* the 'name' */
287 TTYPE_PAL, /* input type */
288 { TSA552x_SCONTROL, /* control byte for Tuner PLL */
289 TSA552x_SCONTROL,
290 TSA552x_SCONTROL,
291 0x00 },
292 { 0x00, 0x00 }, /* band-switch crosspoints */
293 { 0xa0, 0x90, 0x30, 0x00 } }, /* the band-switch values */
280};
281
282
283/* scaling factor for frequencies expressed as ints */
284#define FREQFACTOR 16
285
286/*
287 * Format:

--- 419 unchanged lines hidden (view full) ---

707/* This is needed as the tuner details are no longer globally declared */
708
709void select_tuner( bktr_ptr_t bktr, int tuner_type ) {
710 if (tuner_type < Bt848_MAX_TUNER) {
711 bktr->card.tuner = &tuners[ tuner_type ];
712 } else {
713 bktr->card.tuner = NULL;
714 }
294};
295
296
297/* scaling factor for frequencies expressed as ints */
298#define FREQFACTOR 16
299
300/*
301 * Format:

--- 419 unchanged lines hidden (view full) ---

721/* This is needed as the tuner details are no longer globally declared */
722
723void select_tuner( bktr_ptr_t bktr, int tuner_type ) {
724 if (tuner_type < Bt848_MAX_TUNER) {
725 bktr->card.tuner = &tuners[ tuner_type ];
726 } else {
727 bktr->card.tuner = NULL;
728 }
729 if (tuner_type == TUNER_MT2032) {
730 mt2032_init(bktr);
731 }
715}
716
717/*
718 * Tuner Notes:
719 * Programming the tuner properly is quite complicated.
720 * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner.
721 * The tuner (front end) covers 45.75 Mhz - 855.25 Mhz and an FM band of
722 * 87.5 Mhz to 108.0 Mhz.

--- 61 unchanged lines hidden (view full) ---

784#if defined( TEST_TUNER_AFC )
785 int oldFrequency, afcDelta;
786#endif
787
788 tuner = bktr->card.tuner;
789 if ( tuner == NULL )
790 return( -1 );
791
732}
733
734/*
735 * Tuner Notes:
736 * Programming the tuner properly is quite complicated.
737 * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner.
738 * The tuner (front end) covers 45.75 Mhz - 855.25 Mhz and an FM band of
739 * 87.5 Mhz to 108.0 Mhz.

--- 61 unchanged lines hidden (view full) ---

801#if defined( TEST_TUNER_AFC )
802 int oldFrequency, afcDelta;
803#endif
804
805 tuner = bktr->card.tuner;
806 if ( tuner == NULL )
807 return( -1 );
808
809 if (tuner == &tuners[TUNER_MT2032]) {
810 mt2032_set_tv_freq(bktr, frequency);
811 return 0;
812 }
792 if (type == TV_FREQUENCY) {
793 /*
794 * select the band based on frequency
795 * XXX FIXME: get the cross-over points from the tuner struct
796 */
797 if ( frequency < (160 * FREQFACTOR ) )
798 band_select = LOW_BAND;
799 else if ( frequency < (454 * FREQFACTOR ) )

--- 171 unchanged lines hidden (view full) ---

971#endif /* TUNER_AFC */
972#undef TBL_IF
973
974
975/*
976 * Get the Tuner status and signal strength
977 */
978int get_tuner_status( bktr_ptr_t bktr ) {
813 if (type == TV_FREQUENCY) {
814 /*
815 * select the band based on frequency
816 * XXX FIXME: get the cross-over points from the tuner struct
817 */
818 if ( frequency < (160 * FREQFACTOR ) )
819 band_select = LOW_BAND;
820 else if ( frequency < (454 * FREQFACTOR ) )

--- 171 unchanged lines hidden (view full) ---

992#endif /* TUNER_AFC */
993#undef TBL_IF
994
995
996/*
997 * Get the Tuner status and signal strength
998 */
999int get_tuner_status( bktr_ptr_t bktr ) {
1000 if (bktr->card.tuner == &tuners[TUNER_MT2032])
1001 return 0;
979 return i2cRead( bktr, bktr->card.tuner_pllAddr + 1 );
980}
981
982/*
983 * set the channel of the tuner
984 */
985int
986tv_channel( bktr_ptr_t bktr, int channel )

--- 23 unchanged lines hidden (view full) ---

1010 return( EINVAL );
1011
1012 memcpy(&chnlset->name, &freqTable[chnlset->index].name,
1013 BT848_MAX_CHNLSET_NAME_LEN);
1014
1015 chnlset->max_channel=freqTable[chnlset->index].ptr[0];
1016 return( 0 );
1017}
1002 return i2cRead( bktr, bktr->card.tuner_pllAddr + 1 );
1003}
1004
1005/*
1006 * set the channel of the tuner
1007 */
1008int
1009tv_channel( bktr_ptr_t bktr, int channel )

--- 23 unchanged lines hidden (view full) ---

1033 return( EINVAL );
1034
1035 memcpy(&chnlset->name, &freqTable[chnlset->index].name,
1036 BT848_MAX_CHNLSET_NAME_LEN);
1037
1038 chnlset->max_channel=freqTable[chnlset->index].ptr[0];
1039 return( 0 );
1040}
1041
1042
1043
1044
1045#define TDA9887_ADDR 0x86
1046
1047int
1048TDA9887_init(bktr_ptr_t bktr, int output2_enable)
1049{
1050 u_char addr = TDA9887_ADDR;
1051#if 0
1052 char buf[8];
1053
1054 /* NOTE: these are PAL values */
1055 buf[0] = 0; /* sub address */
1056 buf[1] = 0x50; /* output port1 inactive */
1057 buf[2] = 0x6e; /* tuner takeover point / de-emphasis */
1058 buf[3] = 0x09; /* fVIF = 38.9 MHz, fFM = 5.5 MHz */
1059
1060 if (!output2_enable)
1061 buf[1] |= 0x80;
1062
1063 if (i2cWriteBuf(bktr, addr, 4, buf) == -1) {
1064 printf("%s: TDA9887 write failed\n", bktr_name(bktr));
1065 return -1;
1066 }
1067#else
1068 i2cWrite(bktr, addr, 0, output2_enable ? 0x50 : 0xd0);
1069 i2cWrite(bktr, addr, 1, 0x6e);
1070 i2cWrite(bktr, addr, 2, 0x09);
1071#endif
1072 return 0;
1073}
1074
1075
1076
1077#define MT2032_OPTIMIZE_VCO 1
1078
1079/* holds the value of XOGC register after init */
1080static int MT2032_XOGC = 4;
1081
1082/* card.tuner_pllAddr not set during init */
1083#define MT2032_ADDR 0xc0
1084
1085#ifndef MT2032_ADDR
1086#define MT2032_ADDR (bktr->card.tuner_pllAddr)
1087#endif
1088
1089static u_char
1090_MT2032_GetRegister(bktr_ptr_t bktr, u_char regNum)
1091{
1092 int ch;
1093
1094 if (i2cWrite(bktr, MT2032_ADDR, regNum, -1) == -1) {
1095 printf("%s: MT2032 write failed (i2c addr %#x)\n",
1096 bktr_name(bktr), MT2032_ADDR);
1097 }
1098 if ((ch = i2cRead(bktr, MT2032_ADDR + 1)) == -1) {
1099 printf("%s: MT2032 get register %d failed\n",
1100 bktr_name(bktr), regNum);
1101 return 0;
1102 }
1103 return ch;
1104}
1105
1106static void
1107_MT2032_SetRegister(bktr_ptr_t bktr, u_char regNum, u_char data)
1108{
1109 i2cWrite(bktr, MT2032_ADDR, regNum, data);
1110}
1111
1112#define MT2032_GetRegister(r) _MT2032_GetRegister(bktr,r)
1113#define MT2032_SetRegister(r,d) _MT2032_SetRegister(bktr,r,d)
1114
1115
1116static int
1117mt2032_init(bktr_ptr_t bktr)
1118{
1119 u_char rdbuf[22];
1120 int xogc, xok = 0;
1121 int i;
1122
1123 TDA9887_init(bktr, 0);
1124
1125 for (i = 0; i < 21; i++)
1126 rdbuf[i] = MT2032_GetRegister(i);
1127
1128 printf("%s: MT2032: Companycode=%02x%02x Part=%02x Revision=%02x\n",
1129 bktr_name(bktr),
1130 rdbuf[0x11], rdbuf[0x12], rdbuf[0x13], rdbuf[0x14]);
1131
1132 /* Initialize Registers per spec. */
1133 MT2032_SetRegister(2, 0xff);
1134 MT2032_SetRegister(3, 0x0f);
1135 MT2032_SetRegister(4, 0x1f);
1136 MT2032_SetRegister(6, 0xe4);
1137 MT2032_SetRegister(7, 0x8f);
1138 MT2032_SetRegister(8, 0xc3);
1139 MT2032_SetRegister(9, 0x4e);
1140 MT2032_SetRegister(10, 0xec);
1141 MT2032_SetRegister(13, 0x32);
1142
1143 /* Adjust XOGC (register 7), wait for XOK */
1144 xogc = 7;
1145 do {
1146 DELAY(10000);
1147 xok = MT2032_GetRegister(0x0e) & 0x01;
1148 if (xok == 1) {
1149 break;
1150 }
1151 xogc--;
1152 if (xogc == 3) {
1153 xogc = 4; /* min. 4 per spec */
1154 break;
1155 }
1156 MT2032_SetRegister(7, 0x88 + xogc);
1157 } while (xok != 1);
1158
1159 TDA9887_init(bktr, 1);
1160
1161 MT2032_XOGC = xogc;
1162
1163 return 0;
1164}
1165
1166static int
1167MT2032_SpurCheck(int f1, int f2, int spectrum_from, int spectrum_to)
1168{
1169 int n1 = 1, n2, f;
1170
1171 f1 = f1 / 1000; /* scale to kHz to avoid 32bit overflows */
1172 f2 = f2 / 1000;
1173 spectrum_from /= 1000;
1174 spectrum_to /= 1000;
1175
1176 do {
1177 n2 = -n1;
1178 f = n1 * (f1 - f2);
1179 do {
1180 n2--;
1181 f = f - f2;
1182 if ((f > spectrum_from) && (f < spectrum_to)) {
1183 return 1;
1184 }
1185 } while ((f > (f2 - spectrum_to)) || (n2 > -5));
1186 n1++;
1187 } while (n1 < 5);
1188
1189 return 0;
1190}
1191
1192static int
1193MT2032_ComputeFreq(
1194 int rfin,
1195 int if1,
1196 int if2,
1197 int spectrum_from,
1198 int spectrum_to,
1199 unsigned char *buf,
1200 int *ret_sel,
1201 int xogc
1202)
1203{ /* all in Hz */
1204 int fref, lo1, lo1n, lo1a, s, sel;
1205 int lo1freq, desired_lo1, desired_lo2, lo2, lo2n, lo2a,
1206 lo2num, lo2freq;
1207 int nLO1adjust;
1208
1209 fref = 5250 * 1000; /* 5.25MHz */
1210
1211 /* per spec 2.3.1 */
1212 desired_lo1 = rfin + if1;
1213 lo1 = (2 * (desired_lo1 / 1000) + (fref / 1000)) / (2 * fref / 1000);
1214 lo1freq = lo1 * fref;
1215 desired_lo2 = lo1freq - rfin - if2;
1216
1217 /* per spec 2.3.2 */
1218 for (nLO1adjust = 1; nLO1adjust < 3; nLO1adjust++) {
1219 if (!MT2032_SpurCheck(lo1freq, desired_lo2, spectrum_from, spectrum_to)) {
1220 break;
1221 }
1222 if (lo1freq < desired_lo1) {
1223 lo1 += nLO1adjust;
1224 } else {
1225 lo1 -= nLO1adjust;
1226 }
1227
1228 lo1freq = lo1 * fref;
1229 desired_lo2 = lo1freq - rfin - if2;
1230 }
1231
1232 /* per spec 2.3.3 */
1233 s = lo1freq / 1000 / 1000;
1234
1235 if (MT2032_OPTIMIZE_VCO) {
1236 if (s > 1890) {
1237 sel = 0;
1238 } else if (s > 1720) {
1239 sel = 1;
1240 } else if (s > 1530) {
1241 sel = 2;
1242 } else if (s > 1370) {
1243 sel = 3;
1244 } else {
1245 sel = 4;/* >1090 */
1246 }
1247 } else {
1248 if (s > 1790) {
1249 sel = 0;/* <1958 */
1250 } else if (s > 1617) {
1251 sel = 1;
1252 } else if (s > 1449) {
1253 sel = 2;
1254 } else if (s > 1291) {
1255 sel = 3;
1256 } else {
1257 sel = 4;/* >1090 */
1258 }
1259 }
1260
1261 *ret_sel = sel;
1262
1263 /* per spec 2.3.4 */
1264 lo1n = lo1 / 8;
1265 lo1a = lo1 - (lo1n * 8);
1266 lo2 = desired_lo2 / fref;
1267 lo2n = lo2 / 8;
1268 lo2a = lo2 - (lo2n * 8);
1269 /* scale to fit in 32bit arith */
1270 lo2num = ((desired_lo2 / 1000) % (fref / 1000)) * 3780 / (fref / 1000);
1271 lo2freq = (lo2a + 8 * lo2n) * fref + lo2num * (fref / 1000) / 3780 * 1000;
1272
1273 if (lo1a < 0 || lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a < 0 ||
1274 lo2a > 7 || lo2n < 17 || lo2n > 30) {
1275 printf("MT2032: parameter out of range\n");
1276 return -1;
1277 }
1278 /* set up MT2032 register map for transfer over i2c */
1279 buf[0] = lo1n - 1;
1280 buf[1] = lo1a | (sel << 4);
1281 buf[2] = 0x86; /* LOGC */
1282 buf[3] = 0x0f; /* reserved */
1283 buf[4] = 0x1f;
1284 buf[5] = (lo2n - 1) | (lo2a << 5);
1285 if (rfin < 400 * 1000 * 1000) {
1286 buf[6] = 0xe4;
1287 } else {
1288 buf[6] = 0xf4; /* set PKEN per rev 1.2 */
1289 }
1290
1291 buf[7] = 8 + xogc;
1292 buf[8] = 0xc3; /* reserved */
1293 buf[9] = 0x4e; /* reserved */
1294 buf[10] = 0xec; /* reserved */
1295 buf[11] = (lo2num & 0xff);
1296 buf[12] = (lo2num >> 8) | 0x80; /* Lo2RST */
1297
1298 return 0;
1299}
1300
1301static int
1302MT2032_CheckLOLock(bktr_ptr_t bktr)
1303{
1304 int t, lock = 0;
1305 for (t = 0; t < 10; t++) {
1306 lock = MT2032_GetRegister(0x0e) & 0x06;
1307 if (lock == 6) {
1308 break;
1309 }
1310 DELAY(1000);
1311 }
1312 return lock;
1313}
1314
1315static int
1316MT2032_OptimizeVCO(bktr_ptr_t bktr, int sel, int lock)
1317{
1318 int tad1, lo1a;
1319
1320 tad1 = MT2032_GetRegister(0x0f) & 0x07;
1321
1322 if (tad1 == 0) {
1323 return lock;
1324 }
1325 if (tad1 == 1) {
1326 return lock;
1327 }
1328 if (tad1 == 2) {
1329 if (sel == 0) {
1330 return lock;
1331 } else {
1332 sel--;
1333 }
1334 } else {
1335 if (sel < 4) {
1336 sel++;
1337 } else {
1338 return lock;
1339 }
1340 }
1341 lo1a = MT2032_GetRegister(0x01) & 0x07;
1342 MT2032_SetRegister(0x01, lo1a | (sel << 4));
1343 lock = MT2032_CheckLOLock(bktr);
1344 return lock;
1345}
1346
1347static int
1348MT2032_SetIFFreq(bktr_ptr_t bktr, int rfin, int if1, int if2, int from, int to)
1349{
1350 u_char buf[21];
1351 int lint_try, sel, lock = 0;
1352
1353 if (MT2032_ComputeFreq(rfin, if1, if2, from, to, &buf[0], &sel, MT2032_XOGC) == -1)
1354 return -1;
1355
1356 TDA9887_init(bktr, 0);
1357
1358 printf("%s: MT2032-SetIFFreq: 0x%02X%02X%02X%02X...\n",
1359 bktr_name(bktr),
1360 buf[0x00], buf[0x01], buf[0x02], buf[0x03]);
1361
1362 /* send only the relevant registers per Rev. 1.2 */
1363 MT2032_SetRegister(0, buf[0x00]);
1364 MT2032_SetRegister(1, buf[0x01]);
1365 MT2032_SetRegister(2, buf[0x02]);
1366
1367 MT2032_SetRegister(5, buf[0x05]);
1368 MT2032_SetRegister(6, buf[0x06]);
1369 MT2032_SetRegister(7, buf[0x07]);
1370
1371 MT2032_SetRegister(11, buf[0x0B]);
1372 MT2032_SetRegister(12, buf[0x0C]);
1373
1374 /* wait for PLLs to lock (per manual), retry LINT if not. */
1375 for (lint_try = 0; lint_try < 2; lint_try++) {
1376 lock = MT2032_CheckLOLock(bktr);
1377
1378 if (MT2032_OPTIMIZE_VCO) {
1379 lock = MT2032_OptimizeVCO(bktr, sel, lock);
1380 }
1381 if (lock == 6) {
1382 break;
1383 }
1384 /* set LINT to re-init PLLs */
1385 MT2032_SetRegister(7, 0x80 + 8 + MT2032_XOGC);
1386 DELAY(10000);
1387 MT2032_SetRegister(7, 8 + MT2032_XOGC);
1388 }
1389 if (lock != 6)
1390 printf("%s: PLL didn't lock\n", bktr_name(bktr));
1391
1392 MT2032_SetRegister(2, 0x20);
1393
1394 TDA9887_init(bktr, 1);
1395 return 0;
1396}
1397
1398static void
1399mt2032_set_tv_freq(bktr_ptr_t bktr, unsigned int freq)
1400{
1401 int if2,from,to;
1402
1403 from=32900*1000;
1404 to=39900*1000;
1405 if2=38900*1000;
1406
1407 printf("%s: setting frequency to %d\n", bktr_name(bktr), freq*62500);
1408 MT2032_SetIFFreq(bktr, freq*62500 /* freq*1000*1000/16 */,
1409 1090*1000*1000, if2, from, to);
1410}