1 /* 2 * Fitipower FC0013 tuner driver 3 * 4 * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net> 5 * partially based on driver code from Fitipower 6 * Copyright (C) 2010 Fitipower Integrated Technology Inc 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 * 22 */ 23 24 #include "fc0013.h" 25 #include "fc0013-priv.h" 26 27 static int fc0013_writereg(struct fc0013_priv *priv, u8 reg, u8 val) 28 { 29 u8 buf[2] = {reg, val}; 30 struct i2c_msg msg = { 31 .addr = priv->addr, .flags = 0, .buf = buf, .len = 2 32 }; 33 34 if (i2c_transfer(priv->i2c, &msg, 1) != 1) { 35 err("I2C write reg failed, reg: %02x, val: %02x", reg, val); 36 return -EREMOTEIO; 37 } 38 return 0; 39 } 40 41 static int fc0013_readreg(struct fc0013_priv *priv, u8 reg, u8 *val) 42 { 43 struct i2c_msg msg[2] = { 44 { .addr = priv->addr, .flags = 0, .buf = ®, .len = 1 }, 45 { .addr = priv->addr, .flags = I2C_M_RD, .buf = val, .len = 1 }, 46 }; 47 48 if (i2c_transfer(priv->i2c, msg, 2) != 2) { 49 err("I2C read reg failed, reg: %02x", reg); 50 return -EREMOTEIO; 51 } 52 return 0; 53 } 54 55 static int fc0013_release(struct dvb_frontend *fe) 56 { 57 kfree(fe->tuner_priv); 58 fe->tuner_priv = NULL; 59 return 0; 60 } 61 62 static int fc0013_init(struct dvb_frontend *fe) 63 { 64 struct fc0013_priv *priv = fe->tuner_priv; 65 int i, ret = 0; 66 unsigned char reg[] = { 67 0x00, /* reg. 0x00: dummy */ 68 0x09, /* reg. 0x01 */ 69 0x16, /* reg. 0x02 */ 70 0x00, /* reg. 0x03 */ 71 0x00, /* reg. 0x04 */ 72 0x17, /* reg. 0x05 */ 73 0x02, /* reg. 0x06 */ 74 0x0a, /* reg. 0x07: CHECK */ 75 0xff, /* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256, 76 Loop Bw 1/8 */ 77 0x6f, /* reg. 0x09: enable LoopThrough */ 78 0xb8, /* reg. 0x0a: Disable LO Test Buffer */ 79 0x82, /* reg. 0x0b: CHECK */ 80 0xfc, /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */ 81 0x01, /* reg. 0x0d: AGC Not Forcing & LNA Forcing, may need 0x02 */ 82 0x00, /* reg. 0x0e */ 83 0x00, /* reg. 0x0f */ 84 0x00, /* reg. 0x10 */ 85 0x00, /* reg. 0x11 */ 86 0x00, /* reg. 0x12 */ 87 0x00, /* reg. 0x13 */ 88 0x50, /* reg. 0x14: DVB-t High Gain, UHF. 89 Middle Gain: 0x48, Low Gain: 0x40 */ 90 0x01, /* reg. 0x15 */ 91 }; 92 93 switch (priv->xtal_freq) { 94 case FC_XTAL_27_MHZ: 95 case FC_XTAL_28_8_MHZ: 96 reg[0x07] |= 0x20; 97 break; 98 case FC_XTAL_36_MHZ: 99 default: 100 break; 101 } 102 103 if (priv->dual_master) 104 reg[0x0c] |= 0x02; 105 106 if (fe->ops.i2c_gate_ctrl) 107 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 108 109 for (i = 1; i < sizeof(reg); i++) { 110 ret = fc0013_writereg(priv, i, reg[i]); 111 if (ret) 112 break; 113 } 114 115 if (fe->ops.i2c_gate_ctrl) 116 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 117 118 if (ret) 119 err("fc0013_writereg failed: %d", ret); 120 121 return ret; 122 } 123 124 static int fc0013_sleep(struct dvb_frontend *fe) 125 { 126 /* nothing to do here */ 127 return 0; 128 } 129 130 int fc0013_rc_cal_add(struct dvb_frontend *fe, int rc_val) 131 { 132 struct fc0013_priv *priv = fe->tuner_priv; 133 int ret; 134 u8 rc_cal; 135 int val; 136 137 if (fe->ops.i2c_gate_ctrl) 138 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 139 140 /* push rc_cal value, get rc_cal value */ 141 ret = fc0013_writereg(priv, 0x10, 0x00); 142 if (ret) 143 goto error_out; 144 145 /* get rc_cal value */ 146 ret = fc0013_readreg(priv, 0x10, &rc_cal); 147 if (ret) 148 goto error_out; 149 150 rc_cal &= 0x0f; 151 152 val = (int)rc_cal + rc_val; 153 154 /* forcing rc_cal */ 155 ret = fc0013_writereg(priv, 0x0d, 0x11); 156 if (ret) 157 goto error_out; 158 159 /* modify rc_cal value */ 160 if (val > 15) 161 ret = fc0013_writereg(priv, 0x10, 0x0f); 162 else if (val < 0) 163 ret = fc0013_writereg(priv, 0x10, 0x00); 164 else 165 ret = fc0013_writereg(priv, 0x10, (u8)val); 166 167 error_out: 168 if (fe->ops.i2c_gate_ctrl) 169 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 170 171 return ret; 172 } 173 EXPORT_SYMBOL(fc0013_rc_cal_add); 174 175 int fc0013_rc_cal_reset(struct dvb_frontend *fe) 176 { 177 struct fc0013_priv *priv = fe->tuner_priv; 178 int ret; 179 180 if (fe->ops.i2c_gate_ctrl) 181 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 182 183 ret = fc0013_writereg(priv, 0x0d, 0x01); 184 if (!ret) 185 ret = fc0013_writereg(priv, 0x10, 0x00); 186 187 if (fe->ops.i2c_gate_ctrl) 188 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 189 190 return ret; 191 } 192 EXPORT_SYMBOL(fc0013_rc_cal_reset); 193 194 static int fc0013_set_vhf_track(struct fc0013_priv *priv, u32 freq) 195 { 196 int ret; 197 u8 tmp; 198 199 ret = fc0013_readreg(priv, 0x1d, &tmp); 200 if (ret) 201 goto error_out; 202 tmp &= 0xe3; 203 if (freq <= 177500) { /* VHF Track: 7 */ 204 ret = fc0013_writereg(priv, 0x1d, tmp | 0x1c); 205 } else if (freq <= 184500) { /* VHF Track: 6 */ 206 ret = fc0013_writereg(priv, 0x1d, tmp | 0x18); 207 } else if (freq <= 191500) { /* VHF Track: 5 */ 208 ret = fc0013_writereg(priv, 0x1d, tmp | 0x14); 209 } else if (freq <= 198500) { /* VHF Track: 4 */ 210 ret = fc0013_writereg(priv, 0x1d, tmp | 0x10); 211 } else if (freq <= 205500) { /* VHF Track: 3 */ 212 ret = fc0013_writereg(priv, 0x1d, tmp | 0x0c); 213 } else if (freq <= 219500) { /* VHF Track: 2 */ 214 ret = fc0013_writereg(priv, 0x1d, tmp | 0x08); 215 } else if (freq < 300000) { /* VHF Track: 1 */ 216 ret = fc0013_writereg(priv, 0x1d, tmp | 0x04); 217 } else { /* UHF and GPS */ 218 ret = fc0013_writereg(priv, 0x1d, tmp | 0x1c); 219 } 220 if (ret) 221 goto error_out; 222 error_out: 223 return ret; 224 } 225 226 static int fc0013_set_params(struct dvb_frontend *fe) 227 { 228 struct fc0013_priv *priv = fe->tuner_priv; 229 int i, ret = 0; 230 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 231 u32 freq = p->frequency / 1000; 232 u32 delsys = p->delivery_system; 233 unsigned char reg[7], am, pm, multi, tmp; 234 unsigned long f_vco; 235 unsigned short xtal_freq_khz_2, xin, xdiv; 236 bool vco_select = false; 237 238 if (fe->callback) { 239 ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 240 FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1)); 241 if (ret) 242 goto exit; 243 } 244 245 switch (priv->xtal_freq) { 246 case FC_XTAL_27_MHZ: 247 xtal_freq_khz_2 = 27000 / 2; 248 break; 249 case FC_XTAL_36_MHZ: 250 xtal_freq_khz_2 = 36000 / 2; 251 break; 252 case FC_XTAL_28_8_MHZ: 253 default: 254 xtal_freq_khz_2 = 28800 / 2; 255 break; 256 } 257 258 if (fe->ops.i2c_gate_ctrl) 259 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 260 261 /* set VHF track */ 262 ret = fc0013_set_vhf_track(priv, freq); 263 if (ret) 264 goto exit; 265 266 if (freq < 300000) { 267 /* enable VHF filter */ 268 ret = fc0013_readreg(priv, 0x07, &tmp); 269 if (ret) 270 goto exit; 271 ret = fc0013_writereg(priv, 0x07, tmp | 0x10); 272 if (ret) 273 goto exit; 274 275 /* disable UHF & disable GPS */ 276 ret = fc0013_readreg(priv, 0x14, &tmp); 277 if (ret) 278 goto exit; 279 ret = fc0013_writereg(priv, 0x14, tmp & 0x1f); 280 if (ret) 281 goto exit; 282 } else if (freq <= 862000) { 283 /* disable VHF filter */ 284 ret = fc0013_readreg(priv, 0x07, &tmp); 285 if (ret) 286 goto exit; 287 ret = fc0013_writereg(priv, 0x07, tmp & 0xef); 288 if (ret) 289 goto exit; 290 291 /* enable UHF & disable GPS */ 292 ret = fc0013_readreg(priv, 0x14, &tmp); 293 if (ret) 294 goto exit; 295 ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x40); 296 if (ret) 297 goto exit; 298 } else { 299 /* disable VHF filter */ 300 ret = fc0013_readreg(priv, 0x07, &tmp); 301 if (ret) 302 goto exit; 303 ret = fc0013_writereg(priv, 0x07, tmp & 0xef); 304 if (ret) 305 goto exit; 306 307 /* disable UHF & enable GPS */ 308 ret = fc0013_readreg(priv, 0x14, &tmp); 309 if (ret) 310 goto exit; 311 ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x20); 312 if (ret) 313 goto exit; 314 } 315 316 /* select frequency divider and the frequency of VCO */ 317 if (freq < 37084) { /* freq * 96 < 3560000 */ 318 multi = 96; 319 reg[5] = 0x82; 320 reg[6] = 0x00; 321 } else if (freq < 55625) { /* freq * 64 < 3560000 */ 322 multi = 64; 323 reg[5] = 0x02; 324 reg[6] = 0x02; 325 } else if (freq < 74167) { /* freq * 48 < 3560000 */ 326 multi = 48; 327 reg[5] = 0x42; 328 reg[6] = 0x00; 329 } else if (freq < 111250) { /* freq * 32 < 3560000 */ 330 multi = 32; 331 reg[5] = 0x82; 332 reg[6] = 0x02; 333 } else if (freq < 148334) { /* freq * 24 < 3560000 */ 334 multi = 24; 335 reg[5] = 0x22; 336 reg[6] = 0x00; 337 } else if (freq < 222500) { /* freq * 16 < 3560000 */ 338 multi = 16; 339 reg[5] = 0x42; 340 reg[6] = 0x02; 341 } else if (freq < 296667) { /* freq * 12 < 3560000 */ 342 multi = 12; 343 reg[5] = 0x12; 344 reg[6] = 0x00; 345 } else if (freq < 445000) { /* freq * 8 < 3560000 */ 346 multi = 8; 347 reg[5] = 0x22; 348 reg[6] = 0x02; 349 } else if (freq < 593334) { /* freq * 6 < 3560000 */ 350 multi = 6; 351 reg[5] = 0x0a; 352 reg[6] = 0x00; 353 } else if (freq < 950000) { /* freq * 4 < 3800000 */ 354 multi = 4; 355 reg[5] = 0x12; 356 reg[6] = 0x02; 357 } else { 358 multi = 2; 359 reg[5] = 0x0a; 360 reg[6] = 0x02; 361 } 362 363 f_vco = freq * multi; 364 365 if (f_vco >= 3060000) { 366 reg[6] |= 0x08; 367 vco_select = true; 368 } 369 370 if (freq >= 45000) { 371 /* From divided value (XDIV) determined the FA and FP value */ 372 xdiv = (unsigned short)(f_vco / xtal_freq_khz_2); 373 if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2)) 374 xdiv++; 375 376 pm = (unsigned char)(xdiv / 8); 377 am = (unsigned char)(xdiv - (8 * pm)); 378 379 if (am < 2) { 380 reg[1] = am + 8; 381 reg[2] = pm - 1; 382 } else { 383 reg[1] = am; 384 reg[2] = pm; 385 } 386 } else { 387 /* fix for frequency less than 45 MHz */ 388 reg[1] = 0x06; 389 reg[2] = 0x11; 390 } 391 392 /* fix clock out */ 393 reg[6] |= 0x20; 394 395 /* From VCO frequency determines the XIN ( fractional part of Delta 396 Sigma PLL) and divided value (XDIV) */ 397 xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2); 398 xin = (xin << 15) / xtal_freq_khz_2; 399 if (xin >= 16384) 400 xin += 32768; 401 402 reg[3] = xin >> 8; 403 reg[4] = xin & 0xff; 404 405 if (delsys == SYS_DVBT) { 406 reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */ 407 switch (p->bandwidth_hz) { 408 case 6000000: 409 reg[6] |= 0x80; 410 break; 411 case 7000000: 412 reg[6] |= 0x40; 413 break; 414 case 8000000: 415 default: 416 break; 417 } 418 } else { 419 err("%s: modulation type not supported!", __func__); 420 return -EINVAL; 421 } 422 423 /* modified for Realtek demod */ 424 reg[5] |= 0x07; 425 426 for (i = 1; i <= 6; i++) { 427 ret = fc0013_writereg(priv, i, reg[i]); 428 if (ret) 429 goto exit; 430 } 431 432 ret = fc0013_readreg(priv, 0x11, &tmp); 433 if (ret) 434 goto exit; 435 if (multi == 64) 436 ret = fc0013_writereg(priv, 0x11, tmp | 0x04); 437 else 438 ret = fc0013_writereg(priv, 0x11, tmp & 0xfb); 439 if (ret) 440 goto exit; 441 442 /* VCO Calibration */ 443 ret = fc0013_writereg(priv, 0x0e, 0x80); 444 if (!ret) 445 ret = fc0013_writereg(priv, 0x0e, 0x00); 446 447 /* VCO Re-Calibration if needed */ 448 if (!ret) 449 ret = fc0013_writereg(priv, 0x0e, 0x00); 450 451 if (!ret) { 452 msleep(10); 453 ret = fc0013_readreg(priv, 0x0e, &tmp); 454 } 455 if (ret) 456 goto exit; 457 458 /* vco selection */ 459 tmp &= 0x3f; 460 461 if (vco_select) { 462 if (tmp > 0x3c) { 463 reg[6] &= ~0x08; 464 ret = fc0013_writereg(priv, 0x06, reg[6]); 465 if (!ret) 466 ret = fc0013_writereg(priv, 0x0e, 0x80); 467 if (!ret) 468 ret = fc0013_writereg(priv, 0x0e, 0x00); 469 } 470 } else { 471 if (tmp < 0x02) { 472 reg[6] |= 0x08; 473 ret = fc0013_writereg(priv, 0x06, reg[6]); 474 if (!ret) 475 ret = fc0013_writereg(priv, 0x0e, 0x80); 476 if (!ret) 477 ret = fc0013_writereg(priv, 0x0e, 0x00); 478 } 479 } 480 481 priv->frequency = p->frequency; 482 priv->bandwidth = p->bandwidth_hz; 483 484 exit: 485 if (fe->ops.i2c_gate_ctrl) 486 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 487 if (ret) 488 warn("%s: failed: %d", __func__, ret); 489 return ret; 490 } 491 492 static int fc0013_get_frequency(struct dvb_frontend *fe, u32 *frequency) 493 { 494 struct fc0013_priv *priv = fe->tuner_priv; 495 *frequency = priv->frequency; 496 return 0; 497 } 498 499 static int fc0013_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 500 { 501 /* always ? */ 502 *frequency = 0; 503 return 0; 504 } 505 506 static int fc0013_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) 507 { 508 struct fc0013_priv *priv = fe->tuner_priv; 509 *bandwidth = priv->bandwidth; 510 return 0; 511 } 512 513 #define INPUT_ADC_LEVEL -8 514 515 static int fc0013_get_rf_strength(struct dvb_frontend *fe, u16 *strength) 516 { 517 struct fc0013_priv *priv = fe->tuner_priv; 518 int ret; 519 unsigned char tmp; 520 int int_temp, lna_gain, int_lna, tot_agc_gain, power; 521 const int fc0013_lna_gain_table[] = { 522 /* low gain */ 523 -63, -58, -99, -73, 524 -63, -65, -54, -60, 525 /* middle gain */ 526 71, 70, 68, 67, 527 65, 63, 61, 58, 528 /* high gain */ 529 197, 191, 188, 186, 530 184, 182, 181, 179, 531 }; 532 533 if (fe->ops.i2c_gate_ctrl) 534 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 535 536 ret = fc0013_writereg(priv, 0x13, 0x00); 537 if (ret) 538 goto err; 539 540 ret = fc0013_readreg(priv, 0x13, &tmp); 541 if (ret) 542 goto err; 543 int_temp = tmp; 544 545 ret = fc0013_readreg(priv, 0x14, &tmp); 546 if (ret) 547 goto err; 548 lna_gain = tmp & 0x1f; 549 550 if (fe->ops.i2c_gate_ctrl) 551 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 552 553 if (lna_gain < ARRAY_SIZE(fc0013_lna_gain_table)) { 554 int_lna = fc0013_lna_gain_table[lna_gain]; 555 tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 + 556 (int_temp & 0x1f)) * 2; 557 power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10; 558 559 if (power >= 45) 560 *strength = 255; /* 100% */ 561 else if (power < -95) 562 *strength = 0; 563 else 564 *strength = (power + 95) * 255 / 140; 565 566 *strength |= *strength << 8; 567 } else { 568 ret = -1; 569 } 570 571 goto exit; 572 573 err: 574 if (fe->ops.i2c_gate_ctrl) 575 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 576 exit: 577 if (ret) 578 warn("%s: failed: %d", __func__, ret); 579 return ret; 580 } 581 582 static const struct dvb_tuner_ops fc0013_tuner_ops = { 583 .info = { 584 .name = "Fitipower FC0013", 585 586 .frequency_min = 37000000, /* estimate */ 587 .frequency_max = 1680000000, /* CHECK */ 588 .frequency_step = 0, 589 }, 590 591 .release = fc0013_release, 592 593 .init = fc0013_init, 594 .sleep = fc0013_sleep, 595 596 .set_params = fc0013_set_params, 597 598 .get_frequency = fc0013_get_frequency, 599 .get_if_frequency = fc0013_get_if_frequency, 600 .get_bandwidth = fc0013_get_bandwidth, 601 602 .get_rf_strength = fc0013_get_rf_strength, 603 }; 604 605 struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe, 606 struct i2c_adapter *i2c, u8 i2c_address, int dual_master, 607 enum fc001x_xtal_freq xtal_freq) 608 { 609 struct fc0013_priv *priv = NULL; 610 611 priv = kzalloc(sizeof(struct fc0013_priv), GFP_KERNEL); 612 if (priv == NULL) 613 return NULL; 614 615 priv->i2c = i2c; 616 priv->dual_master = dual_master; 617 priv->addr = i2c_address; 618 priv->xtal_freq = xtal_freq; 619 620 info("Fitipower FC0013 successfully attached."); 621 622 fe->tuner_priv = priv; 623 624 memcpy(&fe->ops.tuner_ops, &fc0013_tuner_ops, 625 sizeof(struct dvb_tuner_ops)); 626 627 return fe; 628 } 629 EXPORT_SYMBOL(fc0013_attach); 630 631 MODULE_DESCRIPTION("Fitipower FC0013 silicon tuner driver"); 632 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>"); 633 MODULE_LICENSE("GPL"); 634 MODULE_VERSION("0.2"); 635