Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Fitipower FC0012 tuner driver
0004  *
0005  * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
0006  */
0007 
0008 #include "fc0012.h"
0009 #include "fc0012-priv.h"
0010 
0011 static int fc0012_writereg(struct fc0012_priv *priv, u8 reg, u8 val)
0012 {
0013     u8 buf[2] = {reg, val};
0014     struct i2c_msg msg = {
0015         .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
0016     };
0017 
0018     if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
0019         dev_err(&priv->i2c->dev,
0020             "%s: I2C write reg failed, reg: %02x, val: %02x\n",
0021             KBUILD_MODNAME, reg, val);
0022         return -EREMOTEIO;
0023     }
0024     return 0;
0025 }
0026 
0027 static int fc0012_readreg(struct fc0012_priv *priv, u8 reg, u8 *val)
0028 {
0029     struct i2c_msg msg[2] = {
0030         { .addr = priv->cfg->i2c_address, .flags = 0,
0031             .buf = &reg, .len = 1 },
0032         { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
0033             .buf = val, .len = 1 },
0034     };
0035 
0036     if (i2c_transfer(priv->i2c, msg, 2) != 2) {
0037         dev_err(&priv->i2c->dev,
0038             "%s: I2C read reg failed, reg: %02x\n",
0039             KBUILD_MODNAME, reg);
0040         return -EREMOTEIO;
0041     }
0042     return 0;
0043 }
0044 
0045 static void fc0012_release(struct dvb_frontend *fe)
0046 {
0047     kfree(fe->tuner_priv);
0048     fe->tuner_priv = NULL;
0049 }
0050 
0051 static int fc0012_init(struct dvb_frontend *fe)
0052 {
0053     struct fc0012_priv *priv = fe->tuner_priv;
0054     int i, ret = 0;
0055     unsigned char reg[] = {
0056         0x00,   /* dummy reg. 0 */
0057         0x05,   /* reg. 0x01 */
0058         0x10,   /* reg. 0x02 */
0059         0x00,   /* reg. 0x03 */
0060         0x00,   /* reg. 0x04 */
0061         0x0f,   /* reg. 0x05: may also be 0x0a */
0062         0x00,   /* reg. 0x06: divider 2, VCO slow */
0063         0x00,   /* reg. 0x07: may also be 0x0f */
0064         0xff,   /* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256,
0065                Loop Bw 1/8 */
0066         0x6e,   /* reg. 0x09: Disable LoopThrough, Enable LoopThrough: 0x6f */
0067         0xb8,   /* reg. 0x0a: Disable LO Test Buffer */
0068         0x82,   /* reg. 0x0b: Output Clock is same as clock frequency,
0069                may also be 0x83 */
0070         0xfc,   /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */
0071         0x02,   /* reg. 0x0d: AGC Not Forcing & LNA Forcing, 0x02 for DVB-T */
0072         0x00,   /* reg. 0x0e */
0073         0x00,   /* reg. 0x0f */
0074         0x00,   /* reg. 0x10: may also be 0x0d */
0075         0x00,   /* reg. 0x11 */
0076         0x1f,   /* reg. 0x12: Set to maximum gain */
0077         0x08,   /* reg. 0x13: Set to Middle Gain: 0x08,
0078                Low Gain: 0x00, High Gain: 0x10, enable IX2: 0x80 */
0079         0x00,   /* reg. 0x14 */
0080         0x04,   /* reg. 0x15: Enable LNA COMPS */
0081     };
0082 
0083     switch (priv->cfg->xtal_freq) {
0084     case FC_XTAL_27_MHZ:
0085     case FC_XTAL_28_8_MHZ:
0086         reg[0x07] |= 0x20;
0087         break;
0088     case FC_XTAL_36_MHZ:
0089     default:
0090         break;
0091     }
0092 
0093     if (priv->cfg->dual_master)
0094         reg[0x0c] |= 0x02;
0095 
0096     if (priv->cfg->loop_through)
0097         reg[0x09] |= 0x01;
0098 
0099     if (fe->ops.i2c_gate_ctrl)
0100         fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
0101 
0102     for (i = 1; i < sizeof(reg); i++) {
0103         ret = fc0012_writereg(priv, i, reg[i]);
0104         if (ret)
0105             break;
0106     }
0107 
0108     if (fe->ops.i2c_gate_ctrl)
0109         fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
0110 
0111     if (ret)
0112         dev_err(&priv->i2c->dev, "%s: fc0012_writereg failed: %d\n",
0113                 KBUILD_MODNAME, ret);
0114 
0115     return ret;
0116 }
0117 
0118 static int fc0012_set_params(struct dvb_frontend *fe)
0119 {
0120     struct fc0012_priv *priv = fe->tuner_priv;
0121     int i, ret = 0;
0122     struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0123     u32 freq = p->frequency / 1000;
0124     u32 delsys = p->delivery_system;
0125     unsigned char reg[7], am, pm, multi, tmp;
0126     unsigned long f_vco;
0127     unsigned short xtal_freq_khz_2, xin, xdiv;
0128     bool vco_select = false;
0129 
0130     if (fe->callback) {
0131         ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
0132             FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1));
0133         if (ret)
0134             goto exit;
0135     }
0136 
0137     switch (priv->cfg->xtal_freq) {
0138     case FC_XTAL_27_MHZ:
0139         xtal_freq_khz_2 = 27000 / 2;
0140         break;
0141     case FC_XTAL_36_MHZ:
0142         xtal_freq_khz_2 = 36000 / 2;
0143         break;
0144     case FC_XTAL_28_8_MHZ:
0145     default:
0146         xtal_freq_khz_2 = 28800 / 2;
0147         break;
0148     }
0149 
0150     /* select frequency divider and the frequency of VCO */
0151     if (freq < 37084) {     /* freq * 96 < 3560000 */
0152         multi = 96;
0153         reg[5] = 0x82;
0154         reg[6] = 0x00;
0155     } else if (freq < 55625) {  /* freq * 64 < 3560000 */
0156         multi = 64;
0157         reg[5] = 0x82;
0158         reg[6] = 0x02;
0159     } else if (freq < 74167) {  /* freq * 48 < 3560000 */
0160         multi = 48;
0161         reg[5] = 0x42;
0162         reg[6] = 0x00;
0163     } else if (freq < 111250) { /* freq * 32 < 3560000 */
0164         multi = 32;
0165         reg[5] = 0x42;
0166         reg[6] = 0x02;
0167     } else if (freq < 148334) { /* freq * 24 < 3560000 */
0168         multi = 24;
0169         reg[5] = 0x22;
0170         reg[6] = 0x00;
0171     } else if (freq < 222500) { /* freq * 16 < 3560000 */
0172         multi = 16;
0173         reg[5] = 0x22;
0174         reg[6] = 0x02;
0175     } else if (freq < 296667) { /* freq * 12 < 3560000 */
0176         multi = 12;
0177         reg[5] = 0x12;
0178         reg[6] = 0x00;
0179     } else if (freq < 445000) { /* freq * 8 < 3560000 */
0180         multi = 8;
0181         reg[5] = 0x12;
0182         reg[6] = 0x02;
0183     } else if (freq < 593334) { /* freq * 6 < 3560000 */
0184         multi = 6;
0185         reg[5] = 0x0a;
0186         reg[6] = 0x00;
0187     } else {
0188         multi = 4;
0189         reg[5] = 0x0a;
0190         reg[6] = 0x02;
0191     }
0192 
0193     f_vco = freq * multi;
0194 
0195     if (f_vco >= 3060000) {
0196         reg[6] |= 0x08;
0197         vco_select = true;
0198     }
0199 
0200     if (freq >= 45000) {
0201         /* From divided value (XDIV) determined the FA and FP value */
0202         xdiv = (unsigned short)(f_vco / xtal_freq_khz_2);
0203         if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2))
0204             xdiv++;
0205 
0206         pm = (unsigned char)(xdiv / 8);
0207         am = (unsigned char)(xdiv - (8 * pm));
0208 
0209         if (am < 2) {
0210             reg[1] = am + 8;
0211             reg[2] = pm - 1;
0212         } else {
0213             reg[1] = am;
0214             reg[2] = pm;
0215         }
0216     } else {
0217         /* fix for frequency less than 45 MHz */
0218         reg[1] = 0x06;
0219         reg[2] = 0x11;
0220     }
0221 
0222     /* fix clock out */
0223     reg[6] |= 0x20;
0224 
0225     /* From VCO frequency determines the XIN ( fractional part of Delta
0226        Sigma PLL) and divided value (XDIV) */
0227     xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2);
0228     xin = (xin << 15) / xtal_freq_khz_2;
0229     if (xin >= 16384)
0230         xin += 32768;
0231 
0232     reg[3] = xin >> 8;  /* xin with 9 bit resolution */
0233     reg[4] = xin & 0xff;
0234 
0235     if (delsys == SYS_DVBT) {
0236         reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */
0237         switch (p->bandwidth_hz) {
0238         case 6000000:
0239             reg[6] |= 0x80;
0240             break;
0241         case 7000000:
0242             reg[6] |= 0x40;
0243             break;
0244         case 8000000:
0245         default:
0246             break;
0247         }
0248     } else {
0249         dev_err(&priv->i2c->dev, "%s: modulation type not supported!\n",
0250                 KBUILD_MODNAME);
0251         return -EINVAL;
0252     }
0253 
0254     /* modified for Realtek demod */
0255     reg[5] |= 0x07;
0256 
0257     if (fe->ops.i2c_gate_ctrl)
0258         fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
0259 
0260     for (i = 1; i <= 6; i++) {
0261         ret = fc0012_writereg(priv, i, reg[i]);
0262         if (ret)
0263             goto exit;
0264     }
0265 
0266     /* VCO Calibration */
0267     ret = fc0012_writereg(priv, 0x0e, 0x80);
0268     if (!ret)
0269         ret = fc0012_writereg(priv, 0x0e, 0x00);
0270 
0271     /* VCO Re-Calibration if needed */
0272     if (!ret)
0273         ret = fc0012_writereg(priv, 0x0e, 0x00);
0274 
0275     if (!ret) {
0276         msleep(10);
0277         ret = fc0012_readreg(priv, 0x0e, &tmp);
0278     }
0279     if (ret)
0280         goto exit;
0281 
0282     /* vco selection */
0283     tmp &= 0x3f;
0284 
0285     if (vco_select) {
0286         if (tmp > 0x3c) {
0287             reg[6] &= ~0x08;
0288             ret = fc0012_writereg(priv, 0x06, reg[6]);
0289             if (!ret)
0290                 ret = fc0012_writereg(priv, 0x0e, 0x80);
0291             if (!ret)
0292                 ret = fc0012_writereg(priv, 0x0e, 0x00);
0293         }
0294     } else {
0295         if (tmp < 0x02) {
0296             reg[6] |= 0x08;
0297             ret = fc0012_writereg(priv, 0x06, reg[6]);
0298             if (!ret)
0299                 ret = fc0012_writereg(priv, 0x0e, 0x80);
0300             if (!ret)
0301                 ret = fc0012_writereg(priv, 0x0e, 0x00);
0302         }
0303     }
0304 
0305     priv->frequency = p->frequency;
0306     priv->bandwidth = p->bandwidth_hz;
0307 
0308 exit:
0309     if (fe->ops.i2c_gate_ctrl)
0310         fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
0311     if (ret)
0312         dev_warn(&priv->i2c->dev, "%s: %s failed: %d\n",
0313                 KBUILD_MODNAME, __func__, ret);
0314     return ret;
0315 }
0316 
0317 static int fc0012_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0318 {
0319     struct fc0012_priv *priv = fe->tuner_priv;
0320     *frequency = priv->frequency;
0321     return 0;
0322 }
0323 
0324 static int fc0012_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
0325 {
0326     *frequency = 0; /* Zero-IF */
0327     return 0;
0328 }
0329 
0330 static int fc0012_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
0331 {
0332     struct fc0012_priv *priv = fe->tuner_priv;
0333     *bandwidth = priv->bandwidth;
0334     return 0;
0335 }
0336 
0337 #define INPUT_ADC_LEVEL -8
0338 
0339 static int fc0012_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
0340 {
0341     struct fc0012_priv *priv = fe->tuner_priv;
0342     int ret;
0343     unsigned char tmp;
0344     int int_temp, lna_gain, int_lna, tot_agc_gain, power;
0345     static const int fc0012_lna_gain_table[] = {
0346         /* low gain */
0347         -63, -58, -99, -73,
0348         -63, -65, -54, -60,
0349         /* middle gain */
0350          71,  70,  68,  67,
0351          65,  63,  61,  58,
0352         /* high gain */
0353         197, 191, 188, 186,
0354         184, 182, 181, 179,
0355     };
0356 
0357     if (fe->ops.i2c_gate_ctrl)
0358         fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
0359 
0360     ret = fc0012_writereg(priv, 0x12, 0x00);
0361     if (ret)
0362         goto err;
0363 
0364     ret = fc0012_readreg(priv, 0x12, &tmp);
0365     if (ret)
0366         goto err;
0367     int_temp = tmp;
0368 
0369     ret = fc0012_readreg(priv, 0x13, &tmp);
0370     if (ret)
0371         goto err;
0372     lna_gain = tmp & 0x1f;
0373 
0374     if (fe->ops.i2c_gate_ctrl)
0375         fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
0376 
0377     if (lna_gain < ARRAY_SIZE(fc0012_lna_gain_table)) {
0378         int_lna = fc0012_lna_gain_table[lna_gain];
0379         tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 +
0380                 (int_temp & 0x1f)) * 2;
0381         power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10;
0382 
0383         if (power >= 45)
0384             *strength = 255;    /* 100% */
0385         else if (power < -95)
0386             *strength = 0;
0387         else
0388             *strength = (power + 95) * 255 / 140;
0389 
0390         *strength |= *strength << 8;
0391     } else {
0392         ret = -1;
0393     }
0394 
0395     goto exit;
0396 
0397 err:
0398     if (fe->ops.i2c_gate_ctrl)
0399         fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
0400 exit:
0401     if (ret)
0402         dev_warn(&priv->i2c->dev, "%s: %s failed: %d\n",
0403                 KBUILD_MODNAME, __func__, ret);
0404     return ret;
0405 }
0406 
0407 static const struct dvb_tuner_ops fc0012_tuner_ops = {
0408     .info = {
0409         .name              = "Fitipower FC0012",
0410 
0411         .frequency_min_hz  =  37 * MHz, /* estimate */
0412         .frequency_max_hz  = 862 * MHz, /* estimate */
0413     },
0414 
0415     .release    = fc0012_release,
0416 
0417     .init       = fc0012_init,
0418 
0419     .set_params = fc0012_set_params,
0420 
0421     .get_frequency  = fc0012_get_frequency,
0422     .get_if_frequency = fc0012_get_if_frequency,
0423     .get_bandwidth  = fc0012_get_bandwidth,
0424 
0425     .get_rf_strength = fc0012_get_rf_strength,
0426 };
0427 
0428 struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
0429     struct i2c_adapter *i2c, const struct fc0012_config *cfg)
0430 {
0431     struct fc0012_priv *priv;
0432     int ret;
0433     u8 chip_id;
0434 
0435     if (fe->ops.i2c_gate_ctrl)
0436         fe->ops.i2c_gate_ctrl(fe, 1);
0437 
0438     priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL);
0439     if (!priv) {
0440         ret = -ENOMEM;
0441         dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
0442         goto err;
0443     }
0444 
0445     priv->cfg = cfg;
0446     priv->i2c = i2c;
0447 
0448     /* check if the tuner is there */
0449     ret = fc0012_readreg(priv, 0x00, &chip_id);
0450     if (ret < 0)
0451         goto err;
0452 
0453     dev_dbg(&i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
0454 
0455     switch (chip_id) {
0456     case 0xa1:
0457         break;
0458     default:
0459         ret = -ENODEV;
0460         goto err;
0461     }
0462 
0463     dev_info(&i2c->dev, "%s: Fitipower FC0012 successfully identified\n",
0464             KBUILD_MODNAME);
0465 
0466     if (priv->cfg->loop_through) {
0467         ret = fc0012_writereg(priv, 0x09, 0x6f);
0468         if (ret < 0)
0469             goto err;
0470     }
0471 
0472     /*
0473      * TODO: Clock out en or div?
0474      * For dual tuner configuration clearing bit [0] is required.
0475      */
0476     if (priv->cfg->clock_out) {
0477         ret =  fc0012_writereg(priv, 0x0b, 0x82);
0478         if (ret < 0)
0479             goto err;
0480     }
0481 
0482     fe->tuner_priv = priv;
0483     memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops,
0484         sizeof(struct dvb_tuner_ops));
0485 
0486 err:
0487     if (fe->ops.i2c_gate_ctrl)
0488         fe->ops.i2c_gate_ctrl(fe, 0);
0489 
0490     if (ret) {
0491         dev_dbg(&i2c->dev, "%s: failed: %d\n", __func__, ret);
0492         kfree(priv);
0493         return NULL;
0494     }
0495 
0496     return fe;
0497 }
0498 EXPORT_SYMBOL(fc0012_attach);
0499 
0500 MODULE_DESCRIPTION("Fitipower FC0012 silicon tuner driver");
0501 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
0502 MODULE_LICENSE("GPL");
0503 MODULE_VERSION("0.6");