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 error_out: 221 return ret; 222 } 223 224 static int fc0013_set_params(struct dvb_frontend *fe) 225 { 226 struct fc0013_priv *priv = fe->tuner_priv; 227 int i, ret = 0; 228 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 229 u32 freq = p->frequency / 1000; 230 u32 delsys = p->delivery_system; 231 unsigned char reg[7], am, pm, multi, tmp; 232 unsigned long f_vco; 233 unsigned short xtal_freq_khz_2, xin, xdiv; 234 bool vco_select = false; 235 236 if (fe->callback) { 237 ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 238 FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1)); 239 if (ret) 240 goto exit; 241 } 242 243 switch (priv->xtal_freq) { 244 case FC_XTAL_27_MHZ: 245 xtal_freq_khz_2 = 27000 / 2; 246 break; 247 case FC_XTAL_36_MHZ: 248 xtal_freq_khz_2 = 36000 / 2; 249 break; 250 case FC_XTAL_28_8_MHZ: 251 default: 252 xtal_freq_khz_2 = 28800 / 2; 253 break; 254 } 255 256 if (fe->ops.i2c_gate_ctrl) 257 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 258 259 /* set VHF track */ 260 ret = fc0013_set_vhf_track(priv, freq); 261 if (ret) 262 goto exit; 263 264 if (freq < 300000) { 265 /* enable VHF filter */ 266 ret = fc0013_readreg(priv, 0x07, &tmp); 267 if (ret) 268 goto exit; 269 ret = fc0013_writereg(priv, 0x07, tmp | 0x10); 270 if (ret) 271 goto exit; 272 273 /* disable UHF & disable GPS */ 274 ret = fc0013_readreg(priv, 0x14, &tmp); 275 if (ret) 276 goto exit; 277 ret = fc0013_writereg(priv, 0x14, tmp & 0x1f); 278 if (ret) 279 goto exit; 280 } else if (freq <= 862000) { 281 /* disable VHF filter */ 282 ret = fc0013_readreg(priv, 0x07, &tmp); 283 if (ret) 284 goto exit; 285 ret = fc0013_writereg(priv, 0x07, tmp & 0xef); 286 if (ret) 287 goto exit; 288 289 /* enable UHF & disable GPS */ 290 ret = fc0013_readreg(priv, 0x14, &tmp); 291 if (ret) 292 goto exit; 293 ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x40); 294 if (ret) 295 goto exit; 296 } else { 297 /* disable VHF filter */ 298 ret = fc0013_readreg(priv, 0x07, &tmp); 299 if (ret) 300 goto exit; 301 ret = fc0013_writereg(priv, 0x07, tmp & 0xef); 302 if (ret) 303 goto exit; 304 305 /* disable UHF & enable GPS */ 306 ret = fc0013_readreg(priv, 0x14, &tmp); 307 if (ret) 308 goto exit; 309 ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x20); 310 if (ret) 311 goto exit; 312 } 313 314 /* select frequency divider and the frequency of VCO */ 315 if (freq < 37084) { /* freq * 96 < 3560000 */ 316 multi = 96; 317 reg[5] = 0x82; 318 reg[6] = 0x00; 319 } else if (freq < 55625) { /* freq * 64 < 3560000 */ 320 multi = 64; 321 reg[5] = 0x02; 322 reg[6] = 0x02; 323 } else if (freq < 74167) { /* freq * 48 < 3560000 */ 324 multi = 48; 325 reg[5] = 0x42; 326 reg[6] = 0x00; 327 } else if (freq < 111250) { /* freq * 32 < 3560000 */ 328 multi = 32; 329 reg[5] = 0x82; 330 reg[6] = 0x02; 331 } else if (freq < 148334) { /* freq * 24 < 3560000 */ 332 multi = 24; 333 reg[5] = 0x22; 334 reg[6] = 0x00; 335 } else if (freq < 222500) { /* freq * 16 < 3560000 */ 336 multi = 16; 337 reg[5] = 0x42; 338 reg[6] = 0x02; 339 } else if (freq < 296667) { /* freq * 12 < 3560000 */ 340 multi = 12; 341 reg[5] = 0x12; 342 reg[6] = 0x00; 343 } else if (freq < 445000) { /* freq * 8 < 3560000 */ 344 multi = 8; 345 reg[5] = 0x22; 346 reg[6] = 0x02; 347 } else if (freq < 593334) { /* freq * 6 < 3560000 */ 348 multi = 6; 349 reg[5] = 0x0a; 350 reg[6] = 0x00; 351 } else if (freq < 950000) { /* freq * 4 < 3800000 */ 352 multi = 4; 353 reg[5] = 0x12; 354 reg[6] = 0x02; 355 } else { 356 multi = 2; 357 reg[5] = 0x0a; 358 reg[6] = 0x02; 359 } 360 361 f_vco = freq * multi; 362 363 if (f_vco >= 3060000) { 364 reg[6] |= 0x08; 365 vco_select = true; 366 } 367 368 if (freq >= 45000) { 369 /* From divided value (XDIV) determined the FA and FP value */ 370 xdiv = (unsigned short)(f_vco / xtal_freq_khz_2); 371 if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2)) 372 xdiv++; 373 374 pm = (unsigned char)(xdiv / 8); 375 am = (unsigned char)(xdiv - (8 * pm)); 376 377 if (am < 2) { 378 reg[1] = am + 8; 379 reg[2] = pm - 1; 380 } else { 381 reg[1] = am; 382 reg[2] = pm; 383 } 384 } else { 385 /* fix for frequency less than 45 MHz */ 386 reg[1] = 0x06; 387 reg[2] = 0x11; 388 } 389 390 /* fix clock out */ 391 reg[6] |= 0x20; 392 393 /* From VCO frequency determines the XIN ( fractional part of Delta 394 Sigma PLL) and divided value (XDIV) */ 395 xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2); 396 xin = (xin << 15) / xtal_freq_khz_2; 397 if (xin >= 16384) 398 xin += 32768; 399 400 reg[3] = xin >> 8; 401 reg[4] = xin & 0xff; 402 403 if (delsys == SYS_DVBT) { 404 reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */ 405 switch (p->bandwidth_hz) { 406 case 6000000: 407 reg[6] |= 0x80; 408 break; 409 case 7000000: 410 reg[6] |= 0x40; 411 break; 412 case 8000000: 413 default: 414 break; 415 } 416 } else { 417 err("%s: modulation type not supported!", __func__); 418 return -EINVAL; 419 } 420 421 /* modified for Realtek demod */ 422 reg[5] |= 0x07; 423 424 for (i = 1; i <= 6; i++) { 425 ret = fc0013_writereg(priv, i, reg[i]); 426 if (ret) 427 goto exit; 428 } 429 430 ret = fc0013_readreg(priv, 0x11, &tmp); 431 if (ret) 432 goto exit; 433 if (multi == 64) 434 ret = fc0013_writereg(priv, 0x11, tmp | 0x04); 435 else 436 ret = fc0013_writereg(priv, 0x11, tmp & 0xfb); 437 if (ret) 438 goto exit; 439 440 /* VCO Calibration */ 441 ret = fc0013_writereg(priv, 0x0e, 0x80); 442 if (!ret) 443 ret = fc0013_writereg(priv, 0x0e, 0x00); 444 445 /* VCO Re-Calibration if needed */ 446 if (!ret) 447 ret = fc0013_writereg(priv, 0x0e, 0x00); 448 449 if (!ret) { 450 msleep(10); 451 ret = fc0013_readreg(priv, 0x0e, &tmp); 452 } 453 if (ret) 454 goto exit; 455 456 /* vco selection */ 457 tmp &= 0x3f; 458 459 if (vco_select) { 460 if (tmp > 0x3c) { 461 reg[6] &= ~0x08; 462 ret = fc0013_writereg(priv, 0x06, reg[6]); 463 if (!ret) 464 ret = fc0013_writereg(priv, 0x0e, 0x80); 465 if (!ret) 466 ret = fc0013_writereg(priv, 0x0e, 0x00); 467 } 468 } else { 469 if (tmp < 0x02) { 470 reg[6] |= 0x08; 471 ret = fc0013_writereg(priv, 0x06, reg[6]); 472 if (!ret) 473 ret = fc0013_writereg(priv, 0x0e, 0x80); 474 if (!ret) 475 ret = fc0013_writereg(priv, 0x0e, 0x00); 476 } 477 } 478 479 priv->frequency = p->frequency; 480 priv->bandwidth = p->bandwidth_hz; 481 482 exit: 483 if (fe->ops.i2c_gate_ctrl) 484 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 485 if (ret) 486 warn("%s: failed: %d", __func__, ret); 487 return ret; 488 } 489 490 static int fc0013_get_frequency(struct dvb_frontend *fe, u32 *frequency) 491 { 492 struct fc0013_priv *priv = fe->tuner_priv; 493 *frequency = priv->frequency; 494 return 0; 495 } 496 497 static int fc0013_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 498 { 499 /* always ? */ 500 *frequency = 0; 501 return 0; 502 } 503 504 static int fc0013_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) 505 { 506 struct fc0013_priv *priv = fe->tuner_priv; 507 *bandwidth = priv->bandwidth; 508 return 0; 509 } 510 511 #define INPUT_ADC_LEVEL -8 512 513 static int fc0013_get_rf_strength(struct dvb_frontend *fe, u16 *strength) 514 { 515 struct fc0013_priv *priv = fe->tuner_priv; 516 int ret; 517 unsigned char tmp; 518 int int_temp, lna_gain, int_lna, tot_agc_gain, power; 519 const int fc0013_lna_gain_table[] = { 520 /* low gain */ 521 -63, -58, -99, -73, 522 -63, -65, -54, -60, 523 /* middle gain */ 524 71, 70, 68, 67, 525 65, 63, 61, 58, 526 /* high gain */ 527 197, 191, 188, 186, 528 184, 182, 181, 179, 529 }; 530 531 if (fe->ops.i2c_gate_ctrl) 532 fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ 533 534 ret = fc0013_writereg(priv, 0x13, 0x00); 535 if (ret) 536 goto err; 537 538 ret = fc0013_readreg(priv, 0x13, &tmp); 539 if (ret) 540 goto err; 541 int_temp = tmp; 542 543 ret = fc0013_readreg(priv, 0x14, &tmp); 544 if (ret) 545 goto err; 546 lna_gain = tmp & 0x1f; 547 548 if (fe->ops.i2c_gate_ctrl) 549 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 550 551 if (lna_gain < ARRAY_SIZE(fc0013_lna_gain_table)) { 552 int_lna = fc0013_lna_gain_table[lna_gain]; 553 tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 + 554 (int_temp & 0x1f)) * 2; 555 power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10; 556 557 if (power >= 45) 558 *strength = 255; /* 100% */ 559 else if (power < -95) 560 *strength = 0; 561 else 562 *strength = (power + 95) * 255 / 140; 563 564 *strength |= *strength << 8; 565 } else { 566 ret = -1; 567 } 568 569 goto exit; 570 571 err: 572 if (fe->ops.i2c_gate_ctrl) 573 fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ 574 exit: 575 if (ret) 576 warn("%s: failed: %d", __func__, ret); 577 return ret; 578 } 579 580 static const struct dvb_tuner_ops fc0013_tuner_ops = { 581 .info = { 582 .name = "Fitipower FC0013", 583 584 .frequency_min = 37000000, /* estimate */ 585 .frequency_max = 1680000000, /* CHECK */ 586 .frequency_step = 0, 587 }, 588 589 .release = fc0013_release, 590 591 .init = fc0013_init, 592 .sleep = fc0013_sleep, 593 594 .set_params = fc0013_set_params, 595 596 .get_frequency = fc0013_get_frequency, 597 .get_if_frequency = fc0013_get_if_frequency, 598 .get_bandwidth = fc0013_get_bandwidth, 599 600 .get_rf_strength = fc0013_get_rf_strength, 601 }; 602 603 struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe, 604 struct i2c_adapter *i2c, u8 i2c_address, int dual_master, 605 enum fc001x_xtal_freq xtal_freq) 606 { 607 struct fc0013_priv *priv = NULL; 608 609 priv = kzalloc(sizeof(struct fc0013_priv), GFP_KERNEL); 610 if (priv == NULL) 611 return NULL; 612 613 priv->i2c = i2c; 614 priv->dual_master = dual_master; 615 priv->addr = i2c_address; 616 priv->xtal_freq = xtal_freq; 617 618 info("Fitipower FC0013 successfully attached."); 619 620 fe->tuner_priv = priv; 621 622 memcpy(&fe->ops.tuner_ops, &fc0013_tuner_ops, 623 sizeof(struct dvb_tuner_ops)); 624 625 return fe; 626 } 627 EXPORT_SYMBOL(fc0013_attach); 628 629 MODULE_DESCRIPTION("Fitipower FC0013 silicon tuner driver"); 630 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>"); 631 MODULE_LICENSE("GPL"); 632 MODULE_VERSION("0.2"); 633