Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *
0004  * (c) 2005 Hartmut Hackmann
0005  * (c) 2007 Michael Krufky
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/slab.h>
0010 #include <asm/types.h>
0011 #include <linux/dvb/frontend.h>
0012 #include <linux/videodev2.h>
0013 
0014 #include "tda827x.h"
0015 
0016 static int debug;
0017 module_param(debug, int, 0644);
0018 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
0019 
0020 #define dprintk(args...) \
0021     do {                        \
0022         if (debug) printk(KERN_DEBUG "tda827x: " args); \
0023     } while (0)
0024 
0025 struct tda827x_priv {
0026     int i2c_addr;
0027     struct i2c_adapter *i2c_adap;
0028     struct tda827x_config *cfg;
0029 
0030     unsigned int sgIF;
0031     unsigned char lpsel;
0032 
0033     u32 frequency;
0034     u32 bandwidth;
0035 };
0036 
0037 static void tda827x_set_std(struct dvb_frontend *fe,
0038                 struct analog_parameters *params)
0039 {
0040     struct tda827x_priv *priv = fe->tuner_priv;
0041     char *mode;
0042 
0043     priv->lpsel = 0;
0044     if (params->std & V4L2_STD_MN) {
0045         priv->sgIF = 92;
0046         priv->lpsel = 1;
0047         mode = "MN";
0048     } else if (params->std & V4L2_STD_B) {
0049         priv->sgIF = 108;
0050         mode = "B";
0051     } else if (params->std & V4L2_STD_GH) {
0052         priv->sgIF = 124;
0053         mode = "GH";
0054     } else if (params->std & V4L2_STD_PAL_I) {
0055         priv->sgIF = 124;
0056         mode = "I";
0057     } else if (params->std & V4L2_STD_DK) {
0058         priv->sgIF = 124;
0059         mode = "DK";
0060     } else if (params->std & V4L2_STD_SECAM_L) {
0061         priv->sgIF = 124;
0062         mode = "L";
0063     } else if (params->std & V4L2_STD_SECAM_LC) {
0064         priv->sgIF = 20;
0065         mode = "LC";
0066     } else {
0067         priv->sgIF = 124;
0068         mode = "xx";
0069     }
0070 
0071     if (params->mode == V4L2_TUNER_RADIO) {
0072         priv->sgIF = 88; /* if frequency is 5.5 MHz */
0073         dprintk("setting tda827x to radio FM\n");
0074     } else
0075         dprintk("setting tda827x to system %s\n", mode);
0076 }
0077 
0078 
0079 /* ------------------------------------------------------------------ */
0080 
0081 struct tda827x_data {
0082     u32 lomax;
0083     u8  spd;
0084     u8  bs;
0085     u8  bp;
0086     u8  cp;
0087     u8  gc3;
0088     u8 div1p5;
0089 };
0090 
0091 static const struct tda827x_data tda827x_table[] = {
0092     { .lomax =  62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
0093     { .lomax =  66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
0094     { .lomax =  76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
0095     { .lomax =  84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
0096     { .lomax =  93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
0097     { .lomax =  98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
0098     { .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
0099     { .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
0100     { .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
0101     { .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
0102     { .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
0103     { .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
0104     { .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
0105     { .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
0106     { .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
0107     { .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
0108     { .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
0109     { .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
0110     { .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
0111     { .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
0112     { .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
0113     { .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
0114     { .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
0115     { .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
0116     { .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
0117     { .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
0118     { .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
0119     { .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
0120     { .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
0121 };
0122 
0123 static int tuner_transfer(struct dvb_frontend *fe,
0124               struct i2c_msg *msg,
0125               const int size)
0126 {
0127     int rc;
0128     struct tda827x_priv *priv = fe->tuner_priv;
0129 
0130     if (fe->ops.i2c_gate_ctrl)
0131         fe->ops.i2c_gate_ctrl(fe, 1);
0132     rc = i2c_transfer(priv->i2c_adap, msg, size);
0133     if (fe->ops.i2c_gate_ctrl)
0134         fe->ops.i2c_gate_ctrl(fe, 0);
0135 
0136     if (rc >= 0 && rc != size)
0137         return -EIO;
0138 
0139     return rc;
0140 }
0141 
0142 static int tda827xo_set_params(struct dvb_frontend *fe)
0143 {
0144     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0145     struct tda827x_priv *priv = fe->tuner_priv;
0146     u8 buf[14];
0147     int rc;
0148 
0149     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
0150                    .buf = buf, .len = sizeof(buf) };
0151     int i, tuner_freq, if_freq;
0152     u32 N;
0153 
0154     dprintk("%s:\n", __func__);
0155     if (c->bandwidth_hz == 0) {
0156         if_freq = 5000000;
0157     } else if (c->bandwidth_hz <= 6000000) {
0158         if_freq = 4000000;
0159     } else if (c->bandwidth_hz <= 7000000) {
0160         if_freq = 4500000;
0161     } else {    /* 8 MHz */
0162         if_freq = 5000000;
0163     }
0164     tuner_freq = c->frequency;
0165 
0166     i = 0;
0167     while (tda827x_table[i].lomax < tuner_freq) {
0168         if (tda827x_table[i + 1].lomax == 0)
0169             break;
0170         i++;
0171     }
0172 
0173     tuner_freq += if_freq;
0174 
0175     N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
0176     buf[0] = 0;
0177     buf[1] = (N>>8) | 0x40;
0178     buf[2] = N & 0xff;
0179     buf[3] = 0;
0180     buf[4] = 0x52;
0181     buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
0182                 (tda827x_table[i].bs << 3) +
0183                 tda827x_table[i].bp;
0184     buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
0185     buf[7] = 0xbf;
0186     buf[8] = 0x2a;
0187     buf[9] = 0x05;
0188     buf[10] = 0xff;
0189     buf[11] = 0x00;
0190     buf[12] = 0x00;
0191     buf[13] = 0x40;
0192 
0193     msg.len = 14;
0194     rc = tuner_transfer(fe, &msg, 1);
0195     if (rc < 0)
0196         goto err;
0197 
0198     msleep(500);
0199     /* correct CP value */
0200     buf[0] = 0x30;
0201     buf[1] = 0x50 + tda827x_table[i].cp;
0202     msg.len = 2;
0203 
0204     rc = tuner_transfer(fe, &msg, 1);
0205     if (rc < 0)
0206         goto err;
0207 
0208     priv->frequency = c->frequency;
0209     priv->bandwidth = c->bandwidth_hz;
0210 
0211     return 0;
0212 
0213 err:
0214     printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
0215            __func__, priv->i2c_addr << 1);
0216     return rc;
0217 }
0218 
0219 static int tda827xo_sleep(struct dvb_frontend *fe)
0220 {
0221     struct tda827x_priv *priv = fe->tuner_priv;
0222     static u8 buf[] = { 0x30, 0xd0 };
0223     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
0224                    .buf = buf, .len = sizeof(buf) };
0225 
0226     dprintk("%s:\n", __func__);
0227     tuner_transfer(fe, &msg, 1);
0228 
0229     if (priv->cfg && priv->cfg->sleep)
0230         priv->cfg->sleep(fe);
0231 
0232     return 0;
0233 }
0234 
0235 /* ------------------------------------------------------------------ */
0236 
0237 static int tda827xo_set_analog_params(struct dvb_frontend *fe,
0238                       struct analog_parameters *params)
0239 {
0240     unsigned char tuner_reg[8];
0241     unsigned char reg2[2];
0242     u32 N;
0243     int i;
0244     struct tda827x_priv *priv = fe->tuner_priv;
0245     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
0246     unsigned int freq = params->frequency;
0247 
0248     tda827x_set_std(fe, params);
0249 
0250     if (params->mode == V4L2_TUNER_RADIO)
0251         freq = freq / 1000;
0252 
0253     N = freq + priv->sgIF;
0254 
0255     i = 0;
0256     while (tda827x_table[i].lomax < N * 62500) {
0257         if (tda827x_table[i + 1].lomax == 0)
0258             break;
0259         i++;
0260     }
0261 
0262     N = N << tda827x_table[i].spd;
0263 
0264     tuner_reg[0] = 0;
0265     tuner_reg[1] = (unsigned char)(N>>8);
0266     tuner_reg[2] = (unsigned char) N;
0267     tuner_reg[3] = 0x40;
0268     tuner_reg[4] = 0x52 + (priv->lpsel << 5);
0269     tuner_reg[5] = (tda827x_table[i].spd    << 6) +
0270                (tda827x_table[i].div1p5 << 5) +
0271                (tda827x_table[i].bs     << 3) + tda827x_table[i].bp;
0272     tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
0273     tuner_reg[7] = 0x8f;
0274 
0275     msg.buf = tuner_reg;
0276     msg.len = 8;
0277     tuner_transfer(fe, &msg, 1);
0278 
0279     msg.buf = reg2;
0280     msg.len = 2;
0281     reg2[0] = 0x80;
0282     reg2[1] = 0;
0283     tuner_transfer(fe, &msg, 1);
0284 
0285     reg2[0] = 0x60;
0286     reg2[1] = 0xbf;
0287     tuner_transfer(fe, &msg, 1);
0288 
0289     reg2[0] = 0x30;
0290     reg2[1] = tuner_reg[4] + 0x80;
0291     tuner_transfer(fe, &msg, 1);
0292 
0293     msleep(1);
0294     reg2[0] = 0x30;
0295     reg2[1] = tuner_reg[4] + 4;
0296     tuner_transfer(fe, &msg, 1);
0297 
0298     msleep(1);
0299     reg2[0] = 0x30;
0300     reg2[1] = tuner_reg[4];
0301     tuner_transfer(fe, &msg, 1);
0302 
0303     msleep(550);
0304     reg2[0] = 0x30;
0305     reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
0306     tuner_transfer(fe, &msg, 1);
0307 
0308     reg2[0] = 0x60;
0309     reg2[1] = 0x3f;
0310     tuner_transfer(fe, &msg, 1);
0311 
0312     reg2[0] = 0x80;
0313     reg2[1] = 0x08;   /* Vsync en */
0314     tuner_transfer(fe, &msg, 1);
0315 
0316     priv->frequency = params->frequency;
0317 
0318     return 0;
0319 }
0320 
0321 static void tda827xo_agcf(struct dvb_frontend *fe)
0322 {
0323     struct tda827x_priv *priv = fe->tuner_priv;
0324     unsigned char data[] = { 0x80, 0x0c };
0325     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
0326                    .buf = data, .len = 2};
0327 
0328     tuner_transfer(fe, &msg, 1);
0329 }
0330 
0331 /* ------------------------------------------------------------------ */
0332 
0333 struct tda827xa_data {
0334     u32 lomax;
0335     u8  svco;
0336     u8  spd;
0337     u8  scr;
0338     u8  sbs;
0339     u8  gc3;
0340 };
0341 
0342 static struct tda827xa_data tda827xa_dvbt[] = {
0343     { .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
0344     { .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
0345     { .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
0346     { .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
0347     { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
0348     { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0349     { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0350     { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0351     { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0352     { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
0353     { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
0354     { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
0355     { .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
0356     { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
0357     { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
0358     { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
0359     { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
0360     { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
0361     { .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
0362     { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
0363     { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
0364     { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
0365     { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
0366     { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
0367     { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
0368     { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
0369     { .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
0370 };
0371 
0372 static struct tda827xa_data tda827xa_dvbc[] = {
0373     { .lomax =  50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
0374     { .lomax =  58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
0375     { .lomax =  69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
0376     { .lomax =  83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
0377     { .lomax =  97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
0378     { .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
0379     { .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
0380     { .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
0381     { .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
0382     { .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
0383     { .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1},
0384     { .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3},
0385     { .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3},
0386     { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1},
0387     { .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
0388     { .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
0389     { .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1},
0390     { .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
0391     { .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1},
0392     { .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
0393     { .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
0394     { .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
0395     { .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
0396     { .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
0397     { .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
0398     { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
0399     { .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
0400 };
0401 
0402 static struct tda827xa_data tda827xa_analog[] = {
0403     { .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
0404     { .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
0405     { .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
0406     { .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
0407     { .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
0408     { .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0409     { .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0410     { .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0411     { .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
0412     { .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
0413     { .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
0414     { .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
0415     { .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
0416     { .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
0417     { .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
0418     { .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
0419     { .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
0420     { .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
0421     { .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
0422     { .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
0423     { .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
0424     { .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
0425     { .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
0426     { .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
0427     { .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
0428     { .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
0429 };
0430 
0431 static int tda827xa_sleep(struct dvb_frontend *fe)
0432 {
0433     struct tda827x_priv *priv = fe->tuner_priv;
0434     static u8 buf[] = { 0x30, 0x90 };
0435     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
0436                    .buf = buf, .len = sizeof(buf) };
0437 
0438     dprintk("%s:\n", __func__);
0439 
0440     tuner_transfer(fe, &msg, 1);
0441 
0442     if (priv->cfg && priv->cfg->sleep)
0443         priv->cfg->sleep(fe);
0444 
0445     return 0;
0446 }
0447 
0448 static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
0449                   struct analog_parameters *params)
0450 {
0451     struct tda827x_priv *priv = fe->tuner_priv;
0452     unsigned char buf[] = {0x22, 0x01};
0453     int arg;
0454     int gp_func;
0455     struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
0456 
0457     if (NULL == priv->cfg) {
0458         dprintk("tda827x_config not defined, cannot set LNA gain!\n");
0459         return;
0460     }
0461     msg.addr = priv->cfg->switch_addr;
0462     if (priv->cfg->config) {
0463         if (high)
0464             dprintk("setting LNA to high gain\n");
0465         else
0466             dprintk("setting LNA to low gain\n");
0467     }
0468     switch (priv->cfg->config) {
0469     case TDA8290_LNA_OFF: /* no LNA */
0470         break;
0471     case TDA8290_LNA_GP0_HIGH_ON: /* switch is GPIO 0 of tda8290 */
0472     case TDA8290_LNA_GP0_HIGH_OFF:
0473         if (params == NULL) {
0474             gp_func = 0;
0475             arg  = 0;
0476         } else {
0477             /* turn Vsync on */
0478             gp_func = 1;
0479             if (params->std & V4L2_STD_MN)
0480                 arg = 1;
0481             else
0482                 arg = 0;
0483         }
0484         if (fe->callback)
0485             fe->callback(priv->i2c_adap->algo_data,
0486                      DVB_FRONTEND_COMPONENT_TUNER,
0487                      gp_func, arg);
0488         buf[1] = high ? 0 : 1;
0489         if (priv->cfg->config == TDA8290_LNA_GP0_HIGH_OFF)
0490             buf[1] = high ? 1 : 0;
0491         tuner_transfer(fe, &msg, 1);
0492         break;
0493     case TDA8290_LNA_ON_BRIDGE: /* switch with GPIO of saa713x */
0494         if (fe->callback)
0495             fe->callback(priv->i2c_adap->algo_data,
0496                      DVB_FRONTEND_COMPONENT_TUNER, 0, high);
0497         break;
0498     }
0499 }
0500 
0501 static int tda827xa_set_params(struct dvb_frontend *fe)
0502 {
0503     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0504     struct tda827x_priv *priv = fe->tuner_priv;
0505     struct tda827xa_data *frequency_map = tda827xa_dvbt;
0506     u8 buf[11];
0507 
0508     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
0509                    .buf = buf, .len = sizeof(buf) };
0510 
0511     int i, tuner_freq, if_freq, rc;
0512     u32 N;
0513 
0514     dprintk("%s:\n", __func__);
0515 
0516     tda827xa_lna_gain(fe, 1, NULL);
0517     msleep(20);
0518 
0519     if (c->bandwidth_hz == 0) {
0520         if_freq = 5000000;
0521     } else if (c->bandwidth_hz <= 6000000) {
0522         if_freq = 4000000;
0523     } else if (c->bandwidth_hz <= 7000000) {
0524         if_freq = 4500000;
0525     } else {    /* 8 MHz */
0526         if_freq = 5000000;
0527     }
0528     tuner_freq = c->frequency;
0529 
0530     switch (c->delivery_system) {
0531     case SYS_DVBC_ANNEX_A:
0532     case SYS_DVBC_ANNEX_C:
0533         dprintk("%s select tda827xa_dvbc\n", __func__);
0534         frequency_map = tda827xa_dvbc;
0535         break;
0536     default:
0537         break;
0538     }
0539 
0540     i = 0;
0541     while (frequency_map[i].lomax < tuner_freq) {
0542         if (frequency_map[i + 1].lomax == 0)
0543             break;
0544         i++;
0545     }
0546 
0547     tuner_freq += if_freq;
0548 
0549     N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
0550     buf[0] = 0;            // subaddress
0551     buf[1] = N >> 8;
0552     buf[2] = N & 0xff;
0553     buf[3] = 0;
0554     buf[4] = 0x16;
0555     buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
0556             frequency_map[i].sbs;
0557     buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
0558     buf[7] = 0x1c;
0559     buf[8] = 0x06;
0560     buf[9] = 0x24;
0561     buf[10] = 0x00;
0562     msg.len = 11;
0563     rc = tuner_transfer(fe, &msg, 1);
0564     if (rc < 0)
0565         goto err;
0566 
0567     buf[0] = 0x90;
0568     buf[1] = 0xff;
0569     buf[2] = 0x60;
0570     buf[3] = 0x00;
0571     buf[4] = 0x59;  // lpsel, for 6MHz + 2
0572     msg.len = 5;
0573     rc = tuner_transfer(fe, &msg, 1);
0574     if (rc < 0)
0575         goto err;
0576 
0577     buf[0] = 0xa0;
0578     buf[1] = 0x40;
0579     msg.len = 2;
0580     rc = tuner_transfer(fe, &msg, 1);
0581     if (rc < 0)
0582         goto err;
0583 
0584     msleep(11);
0585     msg.flags = I2C_M_RD;
0586     rc = tuner_transfer(fe, &msg, 1);
0587     if (rc < 0)
0588         goto err;
0589     msg.flags = 0;
0590 
0591     buf[1] >>= 4;
0592     dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
0593     if ((buf[1]) < 2) {
0594         tda827xa_lna_gain(fe, 0, NULL);
0595         buf[0] = 0x60;
0596         buf[1] = 0x0c;
0597         rc = tuner_transfer(fe, &msg, 1);
0598         if (rc < 0)
0599             goto err;
0600     }
0601 
0602     buf[0] = 0xc0;
0603     buf[1] = 0x99;    // lpsel, for 6MHz + 2
0604     rc = tuner_transfer(fe, &msg, 1);
0605     if (rc < 0)
0606         goto err;
0607 
0608     buf[0] = 0x60;
0609     buf[1] = 0x3c;
0610     rc = tuner_transfer(fe, &msg, 1);
0611     if (rc < 0)
0612         goto err;
0613 
0614     /* correct CP value */
0615     buf[0] = 0x30;
0616     buf[1] = 0x10 + frequency_map[i].scr;
0617     rc = tuner_transfer(fe, &msg, 1);
0618     if (rc < 0)
0619         goto err;
0620 
0621     msleep(163);
0622     buf[0] = 0xc0;
0623     buf[1] = 0x39;  // lpsel, for 6MHz + 2
0624     rc = tuner_transfer(fe, &msg, 1);
0625     if (rc < 0)
0626         goto err;
0627 
0628     msleep(3);
0629     /* freeze AGC1 */
0630     buf[0] = 0x50;
0631     buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
0632     rc = tuner_transfer(fe, &msg, 1);
0633     if (rc < 0)
0634         goto err;
0635 
0636     priv->frequency = c->frequency;
0637     priv->bandwidth = c->bandwidth_hz;
0638 
0639     return 0;
0640 
0641 err:
0642     printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
0643            __func__, priv->i2c_addr << 1);
0644     return rc;
0645 }
0646 
0647 
0648 static int tda827xa_set_analog_params(struct dvb_frontend *fe,
0649                       struct analog_parameters *params)
0650 {
0651     unsigned char tuner_reg[11];
0652     u32 N;
0653     int i;
0654     struct tda827x_priv *priv = fe->tuner_priv;
0655     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
0656                    .buf = tuner_reg, .len = sizeof(tuner_reg) };
0657     unsigned int freq = params->frequency;
0658 
0659     tda827x_set_std(fe, params);
0660 
0661     tda827xa_lna_gain(fe, 1, params);
0662     msleep(10);
0663 
0664     if (params->mode == V4L2_TUNER_RADIO)
0665         freq = freq / 1000;
0666 
0667     N = freq + priv->sgIF;
0668 
0669     i = 0;
0670     while (tda827xa_analog[i].lomax < N * 62500) {
0671         if (tda827xa_analog[i + 1].lomax == 0)
0672             break;
0673         i++;
0674     }
0675 
0676     N = N << tda827xa_analog[i].spd;
0677 
0678     tuner_reg[0] = 0;
0679     tuner_reg[1] = (unsigned char)(N>>8);
0680     tuner_reg[2] = (unsigned char) N;
0681     tuner_reg[3] = 0;
0682     tuner_reg[4] = 0x16;
0683     tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
0684                (tda827xa_analog[i].svco << 3) +
0685             tda827xa_analog[i].sbs;
0686     tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
0687     tuner_reg[7] = 0x1c;
0688     tuner_reg[8] = 4;
0689     tuner_reg[9] = 0x20;
0690     tuner_reg[10] = 0x00;
0691     msg.len = 11;
0692     tuner_transfer(fe, &msg, 1);
0693 
0694     tuner_reg[0] = 0x90;
0695     tuner_reg[1] = 0xff;
0696     tuner_reg[2] = 0xe0;
0697     tuner_reg[3] = 0;
0698     tuner_reg[4] = 0x99 + (priv->lpsel << 1);
0699     msg.len = 5;
0700     tuner_transfer(fe, &msg, 1);
0701 
0702     tuner_reg[0] = 0xa0;
0703     tuner_reg[1] = 0xc0;
0704     msg.len = 2;
0705     tuner_transfer(fe, &msg, 1);
0706 
0707     tuner_reg[0] = 0x30;
0708     tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
0709     tuner_transfer(fe, &msg, 1);
0710 
0711     msg.flags = I2C_M_RD;
0712     tuner_transfer(fe, &msg, 1);
0713     msg.flags = 0;
0714     tuner_reg[1] >>= 4;
0715     dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
0716     if (tuner_reg[1] < 1)
0717         tda827xa_lna_gain(fe, 0, params);
0718 
0719     msleep(100);
0720     tuner_reg[0] = 0x60;
0721     tuner_reg[1] = 0x3c;
0722     tuner_transfer(fe, &msg, 1);
0723 
0724     msleep(163);
0725     tuner_reg[0] = 0x50;
0726     tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
0727     tuner_transfer(fe, &msg, 1);
0728 
0729     tuner_reg[0] = 0x80;
0730     tuner_reg[1] = 0x28;
0731     tuner_transfer(fe, &msg, 1);
0732 
0733     tuner_reg[0] = 0xb0;
0734     tuner_reg[1] = 0x01;
0735     tuner_transfer(fe, &msg, 1);
0736 
0737     tuner_reg[0] = 0xc0;
0738     tuner_reg[1] = 0x19 + (priv->lpsel << 1);
0739     tuner_transfer(fe, &msg, 1);
0740 
0741     priv->frequency = params->frequency;
0742 
0743     return 0;
0744 }
0745 
0746 static void tda827xa_agcf(struct dvb_frontend *fe)
0747 {
0748     struct tda827x_priv *priv = fe->tuner_priv;
0749     unsigned char data[] = {0x80, 0x2c};
0750     struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
0751                   .buf = data, .len = 2};
0752     tuner_transfer(fe, &msg, 1);
0753 }
0754 
0755 /* ------------------------------------------------------------------ */
0756 
0757 static void tda827x_release(struct dvb_frontend *fe)
0758 {
0759     kfree(fe->tuner_priv);
0760     fe->tuner_priv = NULL;
0761 }
0762 
0763 static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0764 {
0765     struct tda827x_priv *priv = fe->tuner_priv;
0766     *frequency = priv->frequency;
0767     return 0;
0768 }
0769 
0770 static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
0771 {
0772     struct tda827x_priv *priv = fe->tuner_priv;
0773     *bandwidth = priv->bandwidth;
0774     return 0;
0775 }
0776 
0777 static int tda827x_init(struct dvb_frontend *fe)
0778 {
0779     struct tda827x_priv *priv = fe->tuner_priv;
0780     dprintk("%s:\n", __func__);
0781     if (priv->cfg && priv->cfg->init)
0782         priv->cfg->init(fe);
0783 
0784     return 0;
0785 }
0786 
0787 static int tda827x_probe_version(struct dvb_frontend *fe);
0788 
0789 static int tda827x_initial_init(struct dvb_frontend *fe)
0790 {
0791     int ret;
0792     ret = tda827x_probe_version(fe);
0793     if (ret)
0794         return ret;
0795     return fe->ops.tuner_ops.init(fe);
0796 }
0797 
0798 static int tda827x_initial_sleep(struct dvb_frontend *fe)
0799 {
0800     int ret;
0801     ret = tda827x_probe_version(fe);
0802     if (ret)
0803         return ret;
0804     return fe->ops.tuner_ops.sleep(fe);
0805 }
0806 
0807 static const struct dvb_tuner_ops tda827xo_tuner_ops = {
0808     .info = {
0809         .name = "Philips TDA827X",
0810         .frequency_min_hz  =  55 * MHz,
0811         .frequency_max_hz  = 860 * MHz,
0812         .frequency_step_hz = 250 * kHz
0813     },
0814     .release = tda827x_release,
0815     .init = tda827x_initial_init,
0816     .sleep = tda827x_initial_sleep,
0817     .set_params = tda827xo_set_params,
0818     .set_analog_params = tda827xo_set_analog_params,
0819     .get_frequency = tda827x_get_frequency,
0820     .get_bandwidth = tda827x_get_bandwidth,
0821 };
0822 
0823 static const struct dvb_tuner_ops tda827xa_tuner_ops = {
0824     .info = {
0825         .name = "Philips TDA827XA",
0826         .frequency_min_hz  =  44 * MHz,
0827         .frequency_max_hz  = 906 * MHz,
0828         .frequency_step_hz = 62500
0829     },
0830     .release = tda827x_release,
0831     .init = tda827x_init,
0832     .sleep = tda827xa_sleep,
0833     .set_params = tda827xa_set_params,
0834     .set_analog_params = tda827xa_set_analog_params,
0835     .get_frequency = tda827x_get_frequency,
0836     .get_bandwidth = tda827x_get_bandwidth,
0837 };
0838 
0839 static int tda827x_probe_version(struct dvb_frontend *fe)
0840 {
0841     u8 data;
0842     int rc;
0843     struct tda827x_priv *priv = fe->tuner_priv;
0844     struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
0845                    .buf = &data, .len = 1 };
0846 
0847     rc = tuner_transfer(fe, &msg, 1);
0848 
0849     if (rc < 0) {
0850         printk("%s: could not read from tuner at addr: 0x%02x\n",
0851                __func__, msg.addr << 1);
0852         return rc;
0853     }
0854     if ((data & 0x3c) == 0) {
0855         dprintk("tda827x tuner found\n");
0856         fe->ops.tuner_ops.init  = tda827x_init;
0857         fe->ops.tuner_ops.sleep = tda827xo_sleep;
0858         if (priv->cfg)
0859             priv->cfg->agcf = tda827xo_agcf;
0860     } else {
0861         dprintk("tda827xa tuner found\n");
0862         memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
0863         if (priv->cfg)
0864             priv->cfg->agcf = tda827xa_agcf;
0865     }
0866     return 0;
0867 }
0868 
0869 struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
0870                     struct i2c_adapter *i2c,
0871                     struct tda827x_config *cfg)
0872 {
0873     struct tda827x_priv *priv = NULL;
0874 
0875     dprintk("%s:\n", __func__);
0876     priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
0877     if (priv == NULL)
0878         return NULL;
0879 
0880     priv->i2c_addr = addr;
0881     priv->i2c_adap = i2c;
0882     priv->cfg = cfg;
0883     memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
0884     fe->tuner_priv = priv;
0885 
0886     dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
0887 
0888     return fe;
0889 }
0890 EXPORT_SYMBOL_GPL(tda827x_attach);
0891 
0892 MODULE_DESCRIPTION("DVB TDA827x driver");
0893 MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
0894 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
0895 MODULE_LICENSE("GPL");