1/* 2 * descriptions + helper functions for simple dvb plls. 3 * 4 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21#include <linux/module.h> 22#include <linux/dvb/frontend.h> 23#include <asm/types.h> 24 25#include "dvb-pll.h" 26 27/* ----------------------------------------------------------- */ 28/* descriptions */ 29 30/* Set AGC TOP value to 103 dBuV: 31 0x80 = Control Byte 32 0x40 = 250 uA charge pump (irrelevant) 33 0x18 = Aux Byte to follow 34 0x06 = 64.5 kHz divider (irrelevant) 35 0x01 = Disable Vt (aka sleep) 36 37 0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA) 38 0x50 = AGC Take over point = 103 dBuV */ 39static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 }; 40 41struct dvb_pll_desc dvb_pll_thomson_dtt7579 = { 42 .name = "Thomson dtt7579", 43 .min = 177000000, 44 .max = 858000000, 45 .iffreq= 36166667, 46 .sleepdata = (u8[]){ 2, 0xb4, 0x03 }, 47 .count = 4, 48 .entries = { 49 { 443250000, 166667, 0xb4, 0x02 }, 50 { 542000000, 166667, 0xb4, 0x08 }, 51 { 771000000, 166667, 0xbc, 0x08 }, 52 { 999999999, 166667, 0xf4, 0x08 }, 53 }, 54}; 55EXPORT_SYMBOL(dvb_pll_thomson_dtt7579); 56 57struct dvb_pll_desc dvb_pll_thomson_dtt7610 = { 58 .name = "Thomson dtt7610", 59 .min = 44000000, 60 .max = 958000000, 61 .iffreq= 44000000, 62 .count = 3, 63 .entries = { 64 { 157250000, 62500, 0x8e, 0x39 }, 65 { 454000000, 62500, 0x8e, 0x3a }, 66 { 999999999, 62500, 0x8e, 0x3c }, 67 }, 68}; 69EXPORT_SYMBOL(dvb_pll_thomson_dtt7610); 70 71static void thomson_dtt759x_bw(u8 *buf, u32 freq, int bandwidth) 72{ 73 if (BANDWIDTH_7_MHZ == bandwidth) 74 buf[3] |= 0x10; 75} 76 77struct dvb_pll_desc dvb_pll_thomson_dtt759x = { 78 .name = "Thomson dtt759x", 79 .min = 177000000, 80 .max = 896000000, 81 .setbw = thomson_dtt759x_bw, 82 .iffreq= 36166667, 83 .sleepdata = (u8[]){ 2, 0x84, 0x03 }, 84 .count = 5, 85 .entries = { 86 { 264000000, 166667, 0xb4, 0x02 }, 87 { 470000000, 166667, 0xbc, 0x02 }, 88 { 735000000, 166667, 0xbc, 0x08 }, 89 { 835000000, 166667, 0xf4, 0x08 }, 90 { 999999999, 166667, 0xfc, 0x08 }, 91 }, 92}; 93EXPORT_SYMBOL(dvb_pll_thomson_dtt759x); 94 95struct dvb_pll_desc dvb_pll_lg_z201 = { 96 .name = "LG z201", 97 .min = 174000000, 98 .max = 862000000, 99 .iffreq= 36166667, 100 .sleepdata = (u8[]){ 2, 0xbc, 0x03 }, 101 .count = 5, 102 .entries = { 103 { 157500000, 166667, 0xbc, 0x01 }, 104 { 443250000, 166667, 0xbc, 0x02 }, 105 { 542000000, 166667, 0xbc, 0x04 }, 106 { 830000000, 166667, 0xf4, 0x04 }, 107 { 999999999, 166667, 0xfc, 0x04 }, 108 }, 109}; 110EXPORT_SYMBOL(dvb_pll_lg_z201); 111 112struct dvb_pll_desc dvb_pll_microtune_4042 = { 113 .name = "Microtune 4042 FI5", 114 .min = 57000000, 115 .max = 858000000, 116 .iffreq= 44000000, 117 .count = 3, 118 .entries = { 119 { 162000000, 62500, 0x8e, 0xa1 }, 120 { 457000000, 62500, 0x8e, 0x91 }, 121 { 999999999, 62500, 0x8e, 0x31 }, 122 }, 123}; 124EXPORT_SYMBOL(dvb_pll_microtune_4042); 125 126struct dvb_pll_desc dvb_pll_thomson_dtt761x = { 127 /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */ 128 .name = "Thomson dtt761x", 129 .min = 57000000, 130 .max = 863000000, 131 .iffreq= 44000000, 132 .count = 3, 133 .initdata = tua603x_agc103, 134 .entries = { 135 { 147000000, 62500, 0x8e, 0x39 }, 136 { 417000000, 62500, 0x8e, 0x3a }, 137 { 999999999, 62500, 0x8e, 0x3c }, 138 }, 139}; 140EXPORT_SYMBOL(dvb_pll_thomson_dtt761x); 141 142struct dvb_pll_desc dvb_pll_unknown_1 = { 143 .name = "unknown 1", /* used by dntv live dvb-t */ 144 .min = 174000000, 145 .max = 862000000, 146 .iffreq= 36166667, 147 .count = 9, 148 .entries = { 149 { 150000000, 166667, 0xb4, 0x01 }, 150 { 173000000, 166667, 0xbc, 0x01 }, 151 { 250000000, 166667, 0xb4, 0x02 }, 152 { 400000000, 166667, 0xbc, 0x02 }, 153 { 420000000, 166667, 0xf4, 0x02 }, 154 { 470000000, 166667, 0xfc, 0x02 }, 155 { 600000000, 166667, 0xbc, 0x08 }, 156 { 730000000, 166667, 0xf4, 0x08 }, 157 { 999999999, 166667, 0xfc, 0x08 }, 158 }, 159}; 160EXPORT_SYMBOL(dvb_pll_unknown_1); 161 162/* Infineon TUA6010XS 163 * used in Thomson Cable Tuner 164 */ 165struct dvb_pll_desc dvb_pll_tua6010xs = { 166 .name = "Infineon TUA6010XS", 167 .min = 44250000, 168 .max = 858000000, 169 .iffreq= 36125000, 170 .count = 3, 171 .entries = { 172 { 115750000, 62500, 0x8e, 0x03 }, 173 { 403250000, 62500, 0x8e, 0x06 }, 174 { 999999999, 62500, 0x8e, 0x85 }, 175 }, 176}; 177EXPORT_SYMBOL(dvb_pll_tua6010xs); 178 179/* Panasonic env57h1xd5 (some Philips PLL ?) */ 180struct dvb_pll_desc dvb_pll_env57h1xd5 = { 181 .name = "Panasonic ENV57H1XD5", 182 .min = 44250000, 183 .max = 858000000, 184 .iffreq= 36125000, 185 .count = 4, 186 .entries = { 187 { 153000000, 166667, 0xc2, 0x41 }, 188 { 470000000, 166667, 0xc2, 0x42 }, 189 { 526000000, 166667, 0xc2, 0x84 }, 190 { 999999999, 166667, 0xc2, 0xa4 }, 191 }, 192}; 193EXPORT_SYMBOL(dvb_pll_env57h1xd5); 194 195/* Philips TDA6650/TDA6651 196 * used in Panasonic ENV77H11D5 197 */ 198static void tda665x_bw(u8 *buf, u32 freq, int bandwidth) 199{ 200 if (bandwidth == BANDWIDTH_8_MHZ) 201 buf[3] |= 0x08; 202} 203 204struct dvb_pll_desc dvb_pll_tda665x = { 205 .name = "Philips TDA6650/TDA6651", 206 .min = 44250000, 207 .max = 858000000, 208 .setbw = tda665x_bw, 209 .iffreq= 36166667, 210 .count = 12, 211 .entries = { 212 { 93834000, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ }, 213 { 123834000, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, 214 { 161000000, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ }, 215 { 163834000, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, 216 { 253834000, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, 217 { 383834000, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, 218 { 443834000, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, 219 { 444000000, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, 220 { 583834000, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, 221 { 793834000, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, 222 { 444834000, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, 223 { 861000000, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, 224 } 225}; 226EXPORT_SYMBOL(dvb_pll_tda665x); 227 228/* Infineon TUA6034 229 * used in LG TDTP E102P 230 */ 231static void tua6034_bw(u8 *buf, u32 freq, int bandwidth) 232{ 233 if (BANDWIDTH_7_MHZ != bandwidth) 234 buf[3] |= 0x08; 235} 236 237struct dvb_pll_desc dvb_pll_tua6034 = { 238 .name = "Infineon TUA6034", 239 .min = 44250000, 240 .max = 858000000, 241 .iffreq= 36166667, 242 .count = 3, 243 .setbw = tua6034_bw, 244 .entries = { 245 { 174500000, 62500, 0xce, 0x01 }, 246 { 230000000, 62500, 0xce, 0x02 }, 247 { 999999999, 62500, 0xce, 0x04 }, 248 }, 249}; 250EXPORT_SYMBOL(dvb_pll_tua6034); 251 252/* Infineon TUA6034 253 * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F 254 */ 255struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = { 256 .name = "LG TDVS-H06xF", 257 .min = 54000000, 258 .max = 863000000, 259 .iffreq= 44000000, 260 .initdata = tua603x_agc103, 261 .count = 3, 262 .entries = { 263 { 165000000, 62500, 0xce, 0x01 }, 264 { 450000000, 62500, 0xce, 0x02 }, 265 { 999999999, 62500, 0xce, 0x04 }, 266 }, 267}; 268EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf); 269 270/* Philips FMD1216ME 271 * used in Medion Hybrid PCMCIA card and USB Box 272 */ 273static void fmd1216me_bw(u8 *buf, u32 freq, int bandwidth) 274{ 275 if (bandwidth == BANDWIDTH_8_MHZ && freq >= 158870000) 276 buf[3] |= 0x08; 277} 278 279struct dvb_pll_desc dvb_pll_fmd1216me = { 280 .name = "Philips FMD1216ME", 281 .min = 50870000, 282 .max = 858000000, 283 .iffreq= 36125000, 284 .setbw = fmd1216me_bw, 285 .count = 7, 286 .entries = { 287 { 143870000, 166667, 0xbc, 0x41 }, 288 { 158870000, 166667, 0xf4, 0x41 }, 289 { 329870000, 166667, 0xbc, 0x42 }, 290 { 441870000, 166667, 0xf4, 0x42 }, 291 { 625870000, 166667, 0xbc, 0x44 }, 292 { 803870000, 166667, 0xf4, 0x44 }, 293 { 999999999, 166667, 0xfc, 0x44 }, 294 } 295}; 296EXPORT_SYMBOL(dvb_pll_fmd1216me); 297 298/* ALPS TDED4 299 * used in Nebula-Cards and USB boxes 300 */ 301static void tded4_bw(u8 *buf, u32 freq, int bandwidth) 302{ 303 if (bandwidth == BANDWIDTH_8_MHZ) 304 buf[3] |= 0x04; 305} 306 307struct dvb_pll_desc dvb_pll_tded4 = { 308 .name = "ALPS TDED4", 309 .min = 47000000, 310 .max = 863000000, 311 .iffreq= 36166667, 312 .setbw = tded4_bw, 313 .count = 4, 314 .entries = { 315 { 153000000, 166667, 0x85, 0x01 }, 316 { 470000000, 166667, 0x85, 0x02 }, 317 { 823000000, 166667, 0x85, 0x08 }, 318 { 999999999, 166667, 0x85, 0x88 }, 319 } 320}; 321EXPORT_SYMBOL(dvb_pll_tded4); 322 323/* ALPS TDHU2 324 * used in AverTVHD MCE A180 325 */ 326struct dvb_pll_desc dvb_pll_tdhu2 = { 327 .name = "ALPS TDHU2", 328 .min = 54000000, 329 .max = 864000000, 330 .iffreq= 44000000, 331 .count = 4, 332 .entries = { 333 { 162000000, 62500, 0x85, 0x01 }, 334 { 426000000, 62500, 0x85, 0x02 }, 335 { 782000000, 62500, 0x85, 0x08 }, 336 { 999999999, 62500, 0x85, 0x88 }, 337 } 338}; 339EXPORT_SYMBOL(dvb_pll_tdhu2); 340 341/* Philips TUV1236D 342 * used in ATI HDTV Wonder 343 */ 344struct dvb_pll_desc dvb_pll_tuv1236d = { 345 .name = "Philips TUV1236D", 346 .min = 54000000, 347 .max = 864000000, 348 .iffreq= 44000000, 349 .count = 3, 350 .entries = { 351 { 157250000, 62500, 0xc6, 0x41 }, 352 { 454000000, 62500, 0xc6, 0x42 }, 353 { 999999999, 62500, 0xc6, 0x44 }, 354 }, 355}; 356EXPORT_SYMBOL(dvb_pll_tuv1236d); 357 358/* Samsung TBMV30111IN / TBMV30712IN1 359 * used in Air2PC ATSC - 2nd generation (nxt2002) 360 */ 361struct dvb_pll_desc dvb_pll_samsung_tbmv = { 362 .name = "Samsung TBMV30111IN / TBMV30712IN1", 363 .min = 54000000, 364 .max = 860000000, 365 .iffreq= 44000000, 366 .count = 6, 367 .entries = { 368 { 172000000, 166667, 0xb4, 0x01 }, 369 { 214000000, 166667, 0xb4, 0x02 }, 370 { 467000000, 166667, 0xbc, 0x02 }, 371 { 721000000, 166667, 0xbc, 0x08 }, 372 { 841000000, 166667, 0xf4, 0x08 }, 373 { 999999999, 166667, 0xfc, 0x02 }, 374 } 375}; 376EXPORT_SYMBOL(dvb_pll_samsung_tbmv); 377 378/* 379 * Philips SD1878 Tuner. 380 */ 381struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = { 382 .name = "Philips SD1878", 383 .min = 950000, 384 .max = 2150000, 385 .iffreq= 249, /* zero-IF, offset 249 is to round up */ 386 .count = 4, 387 .entries = { 388 { 1250000, 500, 0xc4, 0x00}, 389 { 1550000, 500, 0xc4, 0x40}, 390 { 2050000, 500, 0xc4, 0x80}, 391 { 2150000, 500, 0xc4, 0xc0}, 392 }, 393}; 394EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261); 395 396/* 397 * Philips TD1316 Tuner. 398 */ 399static void td1316_bw(u8 *buf, u32 freq, int bandwidth) 400{ 401 u8 band; 402 403 /* determine band */ 404 if (freq < 161000000) 405 band = 1; 406 else if (freq < 444000000) 407 band = 2; 408 else 409 band = 4; 410 411 buf[3] |= band; 412 413 /* setup PLL filter */ 414 if (bandwidth == BANDWIDTH_8_MHZ) 415 buf[3] |= 1 << 3; 416} 417 418struct dvb_pll_desc dvb_pll_philips_td1316 = { 419 .name = "Philips TD1316", 420 .min = 87000000, 421 .max = 895000000, 422 .iffreq= 36166667, 423 .setbw = td1316_bw, 424 .count = 9, 425 .entries = { 426 { 93834000, 166667, 0xca, 0x60}, 427 { 123834000, 166667, 0xca, 0xa0}, 428 { 163834000, 166667, 0xca, 0xc0}, 429 { 253834000, 166667, 0xca, 0x60}, 430 { 383834000, 166667, 0xca, 0xa0}, 431 { 443834000, 166667, 0xca, 0xc0}, 432 { 583834000, 166667, 0xca, 0x60}, 433 { 793834000, 166667, 0xca, 0xa0}, 434 { 858834000, 166667, 0xca, 0xe0}, 435 }, 436}; 437EXPORT_SYMBOL(dvb_pll_philips_td1316); 438 439/* FE6600 used on DViCO Hybrid */ 440struct dvb_pll_desc dvb_pll_thomson_fe6600 = { 441 .name = "Thomson FE6600", 442 .min = 44250000, 443 .max = 858000000, 444 .iffreq= 36125000, 445 .count = 4, 446 .entries = { 447 { 250000000, 166667, 0xb4, 0x12 }, 448 { 455000000, 166667, 0xfe, 0x11 }, 449 { 775500000, 166667, 0xbc, 0x18 }, 450 { 999999999, 166667, 0xf4, 0x18 }, 451 } 452}; 453EXPORT_SYMBOL(dvb_pll_thomson_fe6600); 454static void opera1_bw(u8 *buf, u32 freq, int bandwidth) 455{ 456 if (bandwidth == BANDWIDTH_8_MHZ) 457 buf[2] |= 0x08; 458} 459 460struct dvb_pll_desc dvb_pll_opera1 = { 461 .name = "Opera Tuner", 462 .min = 900000, 463 .max = 2250000, 464 .iffreq= 0, 465 .setbw = opera1_bw, 466 .count = 8, 467 .entries = { 468 { 1064000, 500, 0xe5, 0xc6 }, 469 { 1169000, 500, 0xe5, 0xe6 }, 470 { 1299000, 500, 0xe5, 0x24 }, 471 { 1444000, 500, 0xe5, 0x44 }, 472 { 1606000, 500, 0xe5, 0x64 }, 473 { 1777000, 500, 0xe5, 0x84 }, 474 { 1941000, 500, 0xe5, 0xa4 }, 475 { 2250000, 500, 0xe5, 0xc4 }, 476 } 477}; 478EXPORT_SYMBOL(dvb_pll_opera1); 479 480struct dvb_pll_priv { 481 /* i2c details */ 482 int pll_i2c_address; 483 struct i2c_adapter *i2c; 484 485 /* the PLL descriptor */ 486 struct dvb_pll_desc *pll_desc; 487 488 /* cached frequency/bandwidth */ 489 u32 frequency; 490 u32 bandwidth; 491}; 492 493/* ----------------------------------------------------------- */ 494/* code */ 495 496static int debug = 0; 497module_param(debug, int, 0644); 498MODULE_PARM_DESC(debug, "enable verbose debug messages"); 499 500int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, 501 u32 freq, int bandwidth) 502{ 503 u32 div; 504 int i; 505 506 if (freq != 0 && (freq < desc->min || freq > desc->max)) 507 return -EINVAL; 508 509 for (i = 0; i < desc->count; i++) { 510 if (freq > desc->entries[i].limit) 511 continue; 512 break; 513 } 514 if (debug) 515 printk("pll: %s: freq=%d bw=%d | i=%d/%d\n", 516 desc->name, freq, bandwidth, i, desc->count); 517 if (i == desc->count) 518 return -EINVAL; 519 520 div = (freq + desc->iffreq + desc->entries[i].stepsize/2) / 521 desc->entries[i].stepsize; 522 buf[0] = div >> 8; 523 buf[1] = div & 0xff; 524 buf[2] = desc->entries[i].config; 525 buf[3] = desc->entries[i].cb; 526 527 if (desc->setbw) 528 desc->setbw(buf, freq, bandwidth); 529 530 if (debug) 531 printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n", 532 desc->name, div, buf[0], buf[1], buf[2], buf[3]); 533 534 // calculate the frequency we set it to 535 return (div * desc->entries[i].stepsize) - desc->iffreq; 536} 537EXPORT_SYMBOL(dvb_pll_configure); 538 539static int dvb_pll_release(struct dvb_frontend *fe) 540{ 541 kfree(fe->tuner_priv); 542 fe->tuner_priv = NULL; 543 return 0; 544} 545 546static int dvb_pll_sleep(struct dvb_frontend *fe) 547{ 548 struct dvb_pll_priv *priv = fe->tuner_priv; 549 550 if (priv->i2c == NULL) 551 return -EINVAL; 552 553 if (priv->pll_desc->sleepdata) { 554 struct i2c_msg msg = { .flags = 0, 555 .addr = priv->pll_i2c_address, 556 .buf = priv->pll_desc->sleepdata + 1, 557 .len = priv->pll_desc->sleepdata[0] }; 558 559 int result; 560 561 if (fe->ops.i2c_gate_ctrl) 562 fe->ops.i2c_gate_ctrl(fe, 1); 563 if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { 564 return result; 565 } 566 return 0; 567 } 568 /* Shouldn't be called when initdata is NULL, maybe BUG()? */ 569 return -EINVAL; 570} 571 572static int dvb_pll_set_params(struct dvb_frontend *fe, 573 struct dvb_frontend_parameters *params) 574{ 575 struct dvb_pll_priv *priv = fe->tuner_priv; 576 u8 buf[4]; 577 struct i2c_msg msg = 578 { .addr = priv->pll_i2c_address, .flags = 0, 579 .buf = buf, .len = sizeof(buf) }; 580 int result; 581 u32 bandwidth = 0, frequency = 0; 582 583 if (priv->i2c == NULL) 584 return -EINVAL; 585 586 // DVBT bandwidth only just now 587 if (fe->ops.info.type == FE_OFDM) { 588 bandwidth = params->u.ofdm.bandwidth; 589 } 590 591 if ((result = dvb_pll_configure(priv->pll_desc, buf, 592 params->frequency, bandwidth)) < 0) 593 return result; 594 else 595 frequency = result; 596 597 if (fe->ops.i2c_gate_ctrl) 598 fe->ops.i2c_gate_ctrl(fe, 1); 599 if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { 600 return result; 601 } 602 603 priv->frequency = frequency; 604 priv->bandwidth = bandwidth; 605 606 return 0; 607} 608 609static int dvb_pll_calc_regs(struct dvb_frontend *fe, 610 struct dvb_frontend_parameters *params, 611 u8 *buf, int buf_len) 612{ 613 struct dvb_pll_priv *priv = fe->tuner_priv; 614 int result; 615 u32 bandwidth = 0, frequency = 0; 616 617 if (buf_len < 5) 618 return -EINVAL; 619 620 // DVBT bandwidth only just now 621 if (fe->ops.info.type == FE_OFDM) { 622 bandwidth = params->u.ofdm.bandwidth; 623 } 624 625 if ((result = dvb_pll_configure(priv->pll_desc, buf+1, 626 params->frequency, bandwidth)) < 0) 627 return result; 628 else 629 frequency = result; 630 631 buf[0] = priv->pll_i2c_address; 632 633 priv->frequency = frequency; 634 priv->bandwidth = bandwidth; 635 636 return 5; 637} 638 639static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency) 640{ 641 struct dvb_pll_priv *priv = fe->tuner_priv; 642 *frequency = priv->frequency; 643 return 0; 644} 645 646static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) 647{ 648 struct dvb_pll_priv *priv = fe->tuner_priv; 649 *bandwidth = priv->bandwidth; 650 return 0; 651} 652 653static int dvb_pll_init(struct dvb_frontend *fe) 654{ 655 struct dvb_pll_priv *priv = fe->tuner_priv; 656 657 if (priv->i2c == NULL) 658 return -EINVAL; 659 660 if (priv->pll_desc->initdata) { 661 struct i2c_msg msg = { .flags = 0, 662 .addr = priv->pll_i2c_address, 663 .buf = priv->pll_desc->initdata + 1, 664 .len = priv->pll_desc->initdata[0] }; 665 666 int result; 667 if (fe->ops.i2c_gate_ctrl) 668 fe->ops.i2c_gate_ctrl(fe, 1); 669 if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) { 670 return result; 671 } 672 return 0; 673 } 674 /* Shouldn't be called when initdata is NULL, maybe BUG()? */ 675 return -EINVAL; 676} 677 678static struct dvb_tuner_ops dvb_pll_tuner_ops = { 679 .release = dvb_pll_release, 680 .sleep = dvb_pll_sleep, 681 .init = dvb_pll_init, 682 .set_params = dvb_pll_set_params, 683 .calc_regs = dvb_pll_calc_regs, 684 .get_frequency = dvb_pll_get_frequency, 685 .get_bandwidth = dvb_pll_get_bandwidth, 686}; 687 688struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, 689 struct i2c_adapter *i2c, 690 struct dvb_pll_desc *desc) 691{ 692 u8 b1 [] = { 0 }; 693 struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, 694 .buf = b1, .len = 1 }; 695 struct dvb_pll_priv *priv = NULL; 696 int ret; 697 698 if (i2c != NULL) { 699 if (fe->ops.i2c_gate_ctrl) 700 fe->ops.i2c_gate_ctrl(fe, 1); 701 702 ret = i2c_transfer (i2c, &msg, 1); 703 if (ret != 1) 704 return NULL; 705 if (fe->ops.i2c_gate_ctrl) 706 fe->ops.i2c_gate_ctrl(fe, 0); 707 } 708 709 priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); 710 if (priv == NULL) 711 return NULL; 712 713 priv->pll_i2c_address = pll_addr; 714 priv->i2c = i2c; 715 priv->pll_desc = desc; 716 717 memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, 718 sizeof(struct dvb_tuner_ops)); 719 720 strncpy(fe->ops.tuner_ops.info.name, desc->name, 721 sizeof(fe->ops.tuner_ops.info.name)); 722 fe->ops.tuner_ops.info.frequency_min = desc->min; 723 fe->ops.tuner_ops.info.frequency_min = desc->max; 724 if (!desc->initdata) 725 fe->ops.tuner_ops.init = NULL; 726 if (!desc->sleepdata) 727 fe->ops.tuner_ops.sleep = NULL; 728 729 fe->tuner_priv = priv; 730 return fe; 731} 732EXPORT_SYMBOL(dvb_pll_attach); 733 734MODULE_DESCRIPTION("dvb pll library"); 735MODULE_AUTHOR("Gerd Knorr"); 736MODULE_LICENSE("GPL"); 737