Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
0004  *
0005  * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
0006  */
0007 
0008 #include "si2157_priv.h"
0009 
0010 static const struct dvb_tuner_ops si2157_ops;
0011 
0012 static int tuner_lock_debug;
0013 module_param(tuner_lock_debug, int, 0644);
0014 MODULE_PARM_DESC(tuner_lock_debug, "if set, signal lock is briefly waited on after setting params");
0015 
0016 /* execute firmware command */
0017 static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
0018 {
0019     struct si2157_dev *dev = i2c_get_clientdata(client);
0020     int ret;
0021     unsigned long timeout;
0022 
0023     mutex_lock(&dev->i2c_mutex);
0024 
0025     if (cmd->wlen) {
0026         /* write cmd and args for firmware */
0027         ret = i2c_master_send(client, cmd->args, cmd->wlen);
0028         if (ret < 0) {
0029             goto err_mutex_unlock;
0030         } else if (ret != cmd->wlen) {
0031             ret = -EREMOTEIO;
0032             goto err_mutex_unlock;
0033         }
0034     }
0035 
0036     if (cmd->rlen) {
0037         /* wait cmd execution terminate */
0038         #define TIMEOUT 80
0039         timeout = jiffies + msecs_to_jiffies(TIMEOUT);
0040         while (!time_after(jiffies, timeout)) {
0041             ret = i2c_master_recv(client, cmd->args, cmd->rlen);
0042             if (ret < 0) {
0043                 goto err_mutex_unlock;
0044             } else if (ret != cmd->rlen) {
0045                 ret = -EREMOTEIO;
0046                 goto err_mutex_unlock;
0047             }
0048 
0049             /* firmware ready? */
0050             if ((cmd->args[0] >> 7) & 0x01)
0051                 break;
0052         }
0053 
0054         dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n",
0055             jiffies_to_msecs(jiffies) -
0056             (jiffies_to_msecs(timeout) - TIMEOUT),
0057             cmd->args[0]);
0058 
0059         if (!((cmd->args[0] >> 7) & 0x01)) {
0060             ret = -ETIMEDOUT;
0061             goto err_mutex_unlock;
0062         }
0063         /* check error status bit */
0064         if (cmd->args[0] & 0x40) {
0065             ret = -EAGAIN;
0066             goto err_mutex_unlock;
0067         }
0068     }
0069 
0070     mutex_unlock(&dev->i2c_mutex);
0071     return 0;
0072 
0073 err_mutex_unlock:
0074     mutex_unlock(&dev->i2c_mutex);
0075     dev_dbg(&client->dev, "failed=%d\n", ret);
0076     return ret;
0077 }
0078 
0079 static const struct si2157_tuner_info si2157_tuners[] = {
0080     { SI2141, 0x60, false, SI2141_60_FIRMWARE, SI2141_A10_FIRMWARE },
0081     { SI2141, 0x61, false, SI2141_61_FIRMWARE, SI2141_A10_FIRMWARE },
0082     { SI2146, 0x11, false, SI2146_11_FIRMWARE, NULL },
0083     { SI2147, 0x50, false, SI2147_50_FIRMWARE, NULL },
0084     { SI2148, 0x32, true,  SI2148_32_FIRMWARE, SI2158_A20_FIRMWARE },
0085     { SI2148, 0x33, true,  SI2148_33_FIRMWARE, SI2158_A20_FIRMWARE },
0086     { SI2157, 0x50, false, SI2157_50_FIRMWARE, SI2157_A30_FIRMWARE },
0087     { SI2158, 0x50, false, SI2158_50_FIRMWARE, SI2158_A20_FIRMWARE },
0088     { SI2158, 0x51, false, SI2158_51_FIRMWARE, SI2158_A20_FIRMWARE },
0089     { SI2177, 0x50, false, SI2177_50_FIRMWARE, SI2157_A30_FIRMWARE },
0090 };
0091 
0092 static int si2157_load_firmware(struct dvb_frontend *fe,
0093                 const char *fw_name)
0094 {
0095     struct i2c_client *client = fe->tuner_priv;
0096     const struct firmware *fw;
0097     int ret, len, remaining;
0098     struct si2157_cmd cmd;
0099 
0100     /* request the firmware, this will block and timeout */
0101     ret = firmware_request_nowarn(&fw, fw_name, &client->dev);
0102     if (ret)
0103         return ret;
0104 
0105     /* firmware should be n chunks of 17 bytes */
0106     if (fw->size % 17 != 0) {
0107         dev_err(&client->dev, "firmware file '%s' is invalid\n",
0108             fw_name);
0109         ret = -EINVAL;
0110         goto err_release_firmware;
0111     }
0112 
0113     dev_info(&client->dev, "downloading firmware from file '%s'\n",
0114          fw_name);
0115 
0116     for (remaining = fw->size; remaining > 0; remaining -= 17) {
0117         len = fw->data[fw->size - remaining];
0118         if (len > SI2157_ARGLEN) {
0119             dev_err(&client->dev, "Bad firmware length\n");
0120             ret = -EINVAL;
0121             goto err_release_firmware;
0122         }
0123         memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
0124         cmd.wlen = len;
0125         cmd.rlen = 1;
0126         ret = si2157_cmd_execute(client, &cmd);
0127         if (ret) {
0128             dev_err(&client->dev, "firmware download failed %d\n",
0129                     ret);
0130             goto err_release_firmware;
0131         }
0132     }
0133 
0134 err_release_firmware:
0135     release_firmware(fw);
0136 
0137     return ret;
0138 }
0139 
0140 static int si2157_find_and_load_firmware(struct dvb_frontend *fe)
0141 {
0142     struct i2c_client *client = fe->tuner_priv;
0143     struct si2157_dev *dev = i2c_get_clientdata(client);
0144     const char *fw_alt_name = NULL;
0145     unsigned char part_id, rom_id;
0146     const char *fw_name = NULL;
0147     struct si2157_cmd cmd;
0148     bool required = true;
0149     int ret, i;
0150 
0151     if (dev->dont_load_firmware) {
0152         dev_info(&client->dev,
0153              "device is buggy, skipping firmware download\n");
0154         return 0;
0155     }
0156 
0157     /* query chip revision */
0158     memcpy(cmd.args, "\x02", 1);
0159     cmd.wlen = 1;
0160     cmd.rlen = 13;
0161     ret = si2157_cmd_execute(client, &cmd);
0162     if (ret)
0163         return ret;
0164 
0165     part_id = cmd.args[2];
0166     rom_id = cmd.args[12];
0167 
0168     for (i = 0; i < ARRAY_SIZE(si2157_tuners); i++) {
0169         if (si2157_tuners[i].part_id != part_id)
0170             continue;
0171         required = si2157_tuners[i].required;
0172         fw_alt_name = si2157_tuners[i].fw_alt_name;
0173 
0174         /* Both part and rom ID match */
0175         if (si2157_tuners[i].rom_id == rom_id) {
0176             fw_name = si2157_tuners[i].fw_name;
0177             break;
0178         }
0179     }
0180 
0181     if (required && !fw_name && !fw_alt_name) {
0182         dev_err(&client->dev,
0183             "unknown chip version Si21%d-%c%c%c ROM 0x%02x\n",
0184             part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);
0185         return -EINVAL;
0186     }
0187 
0188     /* Update the part id based on device's report */
0189     dev->part_id = part_id;
0190 
0191     dev_info(&client->dev,
0192          "found a 'Silicon Labs Si21%d-%c%c%c ROM 0x%02x'\n",
0193          part_id, cmd.args[1], cmd.args[3], cmd.args[4], rom_id);
0194 
0195     if (fw_name)
0196         ret = si2157_load_firmware(fe, fw_name);
0197     else
0198         ret = -ENOENT;
0199 
0200     /* Try alternate name, if any */
0201     if (ret == -ENOENT && fw_alt_name)
0202         ret = si2157_load_firmware(fe, fw_alt_name);
0203 
0204     if (ret == -ENOENT) {
0205         if (!required) {
0206             dev_info(&client->dev, "Using ROM firmware.\n");
0207             return 0;
0208         }
0209         dev_err(&client->dev, "Can't continue without a firmware.\n");
0210     } else if (ret < 0) {
0211         dev_err(&client->dev, "error %d when loading firmware\n", ret);
0212     }
0213     return ret;
0214 }
0215 
0216 static int si2157_init(struct dvb_frontend *fe)
0217 {
0218     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0219     struct i2c_client *client = fe->tuner_priv;
0220     struct si2157_dev *dev = i2c_get_clientdata(client);
0221     unsigned int xtal_trim;
0222     struct si2157_cmd cmd;
0223     int ret;
0224 
0225     dev_dbg(&client->dev, "\n");
0226 
0227     /* Try to get Xtal trim property, to verify tuner still running */
0228     memcpy(cmd.args, "\x15\x00\x02\x04", 4);
0229     cmd.wlen = 4;
0230     cmd.rlen = 4;
0231     ret = si2157_cmd_execute(client, &cmd);
0232 
0233     xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
0234 
0235     if (ret == 0 && xtal_trim < 16)
0236         goto warm;
0237 
0238     dev->if_frequency = 0; /* we no longer know current tuner state */
0239 
0240     /* power up */
0241     if (dev->part_id == SI2146) {
0242         /* clock_mode = XTAL, clock_freq = 24MHz */
0243         memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
0244         cmd.wlen = 9;
0245     } else if (dev->part_id == SI2141) {
0246         /* clock_mode: XTAL, xout enabled */
0247         memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);
0248         cmd.wlen = 10;
0249     } else {
0250         memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
0251         cmd.wlen = 15;
0252     }
0253     cmd.rlen = 1;
0254     ret = si2157_cmd_execute(client, &cmd);
0255     if (ret && (dev->part_id != SI2141 || ret != -EAGAIN))
0256         goto err;
0257 
0258     /* Si2141 needs a wake up command */
0259     if (dev->part_id == SI2141) {
0260         memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7);
0261         cmd.wlen = 7;
0262         ret = si2157_cmd_execute(client, &cmd);
0263         if (ret)
0264             goto err;
0265     }
0266 
0267     /* Try to load the firmware */
0268     ret = si2157_find_and_load_firmware(fe);
0269     if (ret < 0)
0270         goto err;
0271 
0272     /* reboot the tuner with new firmware? */
0273     memcpy(cmd.args, "\x01\x01", 2);
0274     cmd.wlen = 2;
0275     cmd.rlen = 1;
0276     ret = si2157_cmd_execute(client, &cmd);
0277     if (ret)
0278         goto err;
0279 
0280     /* query firmware version */
0281     memcpy(cmd.args, "\x11", 1);
0282     cmd.wlen = 1;
0283     cmd.rlen = 10;
0284     ret = si2157_cmd_execute(client, &cmd);
0285     if (ret)
0286         goto err;
0287 
0288     dev_info(&client->dev, "firmware version: %c.%c.%d\n",
0289             cmd.args[6], cmd.args[7], cmd.args[8]);
0290 
0291     /* enable tuner status flags */
0292     memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);
0293     cmd.wlen = 6;
0294     cmd.rlen = 1;
0295     ret = si2157_cmd_execute(client, &cmd);
0296     if (ret)
0297         goto err;
0298 
0299     memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6);
0300     cmd.wlen = 6;
0301     cmd.rlen = 1;
0302     ret = si2157_cmd_execute(client, &cmd);
0303     if (ret)
0304         goto err;
0305 
0306     memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6);
0307     cmd.wlen = 6;
0308     cmd.rlen = 1;
0309     ret = si2157_cmd_execute(client, &cmd);
0310     if (ret)
0311         goto err;
0312 warm:
0313     /* init statistics in order signal app which are supported */
0314     c->strength.len = 1;
0315     c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0316     /* start statistics polling */
0317     schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000));
0318 
0319     dev->active = true;
0320     return 0;
0321 
0322 err:
0323     dev_dbg(&client->dev, "failed=%d\n", ret);
0324     return ret;
0325 }
0326 
0327 static int si2157_sleep(struct dvb_frontend *fe)
0328 {
0329     struct i2c_client *client = fe->tuner_priv;
0330     struct si2157_dev *dev = i2c_get_clientdata(client);
0331     int ret;
0332     struct si2157_cmd cmd;
0333 
0334     dev_dbg(&client->dev, "\n");
0335 
0336     dev->active = false;
0337 
0338     /* stop statistics polling */
0339     cancel_delayed_work_sync(&dev->stat_work);
0340 
0341     /* standby */
0342     memcpy(cmd.args, "\x16\x00", 2);
0343     cmd.wlen = 2;
0344     cmd.rlen = 1;
0345     ret = si2157_cmd_execute(client, &cmd);
0346     if (ret)
0347         goto err;
0348 
0349     return 0;
0350 err:
0351     dev_dbg(&client->dev, "failed=%d\n", ret);
0352     return ret;
0353 }
0354 
0355 static int si2157_tune_wait(struct i2c_client *client, u8 is_digital)
0356 {
0357 #define TUN_TIMEOUT 40
0358 #define DIG_TIMEOUT 30
0359 #define ANALOG_TIMEOUT 150
0360     struct si2157_dev *dev = i2c_get_clientdata(client);
0361     int ret;
0362     unsigned long timeout;
0363     unsigned long start_time;
0364     u8 wait_status;
0365     u8  tune_lock_mask;
0366 
0367     if (is_digital)
0368         tune_lock_mask = 0x04;
0369     else
0370         tune_lock_mask = 0x02;
0371 
0372     mutex_lock(&dev->i2c_mutex);
0373 
0374     /* wait tuner command complete */
0375     start_time = jiffies;
0376     timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT);
0377     while (1) {
0378         ret = i2c_master_recv(client, &wait_status,
0379                       sizeof(wait_status));
0380         if (ret < 0) {
0381             goto err_mutex_unlock;
0382         } else if (ret != sizeof(wait_status)) {
0383             ret = -EREMOTEIO;
0384             goto err_mutex_unlock;
0385         }
0386 
0387         if (time_after(jiffies, timeout))
0388             break;
0389 
0390         /* tuner done? */
0391         if ((wait_status & 0x81) == 0x81)
0392             break;
0393         usleep_range(5000, 10000);
0394     }
0395 
0396     dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n",
0397         jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
0398         wait_status);
0399 
0400     /* if we tuned ok, wait a bit for tuner lock */
0401     if (tuner_lock_debug && (wait_status & 0x81) == 0x81) {
0402         if (is_digital)
0403             timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT);
0404         else
0405             timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT);
0406 
0407         while (!time_after(jiffies, timeout)) {
0408             ret = i2c_master_recv(client, &wait_status,
0409                           sizeof(wait_status));
0410             if (ret < 0) {
0411                 goto err_mutex_unlock;
0412             } else if (ret != sizeof(wait_status)) {
0413                 ret = -EREMOTEIO;
0414                 goto err_mutex_unlock;
0415             }
0416 
0417             /* tuner locked? */
0418             if (wait_status & tune_lock_mask)
0419                 break;
0420             usleep_range(5000, 10000);
0421         }
0422 
0423         dev_dbg(&client->dev, "tuning+lock took %d ms, status=0x%x\n",
0424             jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
0425             wait_status);
0426     }
0427 
0428     if ((wait_status & 0xc0) != 0x80) {
0429         ret = -ETIMEDOUT;
0430         goto err_mutex_unlock;
0431     }
0432 
0433     mutex_unlock(&dev->i2c_mutex);
0434     return 0;
0435 
0436 err_mutex_unlock:
0437     mutex_unlock(&dev->i2c_mutex);
0438     dev_err(&client->dev, "failed=%d\n", ret);
0439     return ret;
0440 }
0441 
0442 static int si2157_set_params(struct dvb_frontend *fe)
0443 {
0444     struct i2c_client *client = fe->tuner_priv;
0445     struct si2157_dev *dev = i2c_get_clientdata(client);
0446     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0447     int ret;
0448     struct si2157_cmd cmd;
0449     u8 bw, delivery_system;
0450     u32 bandwidth;
0451     u32 if_frequency = 5000000;
0452 
0453     dev_dbg(&client->dev,
0454             "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
0455             c->delivery_system, c->frequency, c->bandwidth_hz);
0456 
0457     if (!dev->active) {
0458         ret = -EAGAIN;
0459         goto err;
0460     }
0461 
0462     if (SUPPORTS_1700KHz(dev) && c->bandwidth_hz <= 1700000) {
0463         bandwidth = 1700000;
0464         bw = 9;
0465     } else if (c->bandwidth_hz <= 6000000) {
0466         bandwidth = 6000000;
0467         bw = 6;
0468     } else if (SUPPORTS_1700KHz(dev) && c->bandwidth_hz <= 6100000) {
0469         bandwidth = 6100000;
0470         bw = 10;
0471     } else if (c->bandwidth_hz <= 7000000) {
0472         bandwidth = 7000000;
0473         bw = 7;
0474     } else {
0475         bandwidth = 8000000;
0476         bw = 8;
0477     }
0478 
0479     switch (c->delivery_system) {
0480     case SYS_ATSC:
0481             delivery_system = 0x00;
0482             if_frequency = 3250000;
0483             break;
0484     case SYS_DVBC_ANNEX_B:
0485             delivery_system = 0x10;
0486             if_frequency = 4000000;
0487             break;
0488     case SYS_DVBT:
0489     case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
0490             delivery_system = 0x20;
0491             break;
0492     case SYS_DVBC_ANNEX_A:
0493     case SYS_DVBC_ANNEX_C:
0494             delivery_system = 0x30;
0495             break;
0496     case SYS_ISDBT:
0497             delivery_system = 0x40;
0498             break;
0499     case SYS_DTMB:
0500             delivery_system = 0x60;
0501             break;
0502     default:
0503             ret = -EINVAL;
0504             goto err;
0505     }
0506 
0507     memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
0508     cmd.args[4] = delivery_system | bw;
0509     if (dev->inversion)
0510         cmd.args[5] = 0x01;
0511     cmd.wlen = 6;
0512     cmd.rlen = 4;
0513     ret = si2157_cmd_execute(client, &cmd);
0514     if (ret)
0515         goto err;
0516 
0517     /* On SI2146, set DTV AGC source to DLIF_AGC_3DB */
0518     if (dev->part_id == SI2146)
0519         memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
0520     else
0521         memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6);
0522     cmd.args[4] = dev->if_port;
0523     cmd.wlen = 6;
0524     cmd.rlen = 4;
0525     ret = si2157_cmd_execute(client, &cmd);
0526     if (ret)
0527         goto err;
0528 
0529     /* set digital if frequency if needed */
0530     if (if_frequency != dev->if_frequency) {
0531         memcpy(cmd.args, "\x14\x00\x06\x07", 4);
0532         cmd.args[4] = (if_frequency / 1000) & 0xff;
0533         cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
0534         cmd.wlen = 6;
0535         cmd.rlen = 4;
0536         ret = si2157_cmd_execute(client, &cmd);
0537         if (ret)
0538             goto err;
0539 
0540         dev->if_frequency = if_frequency;
0541     }
0542 
0543     /* set digital frequency */
0544     memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
0545     cmd.args[4] = (c->frequency >>  0) & 0xff;
0546     cmd.args[5] = (c->frequency >>  8) & 0xff;
0547     cmd.args[6] = (c->frequency >> 16) & 0xff;
0548     cmd.args[7] = (c->frequency >> 24) & 0xff;
0549     cmd.wlen = 8;
0550     cmd.rlen = 1;
0551     ret = si2157_cmd_execute(client, &cmd);
0552     if (ret)
0553         goto err;
0554 
0555     dev->bandwidth = bandwidth;
0556     dev->frequency = c->frequency;
0557 
0558     si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */
0559 
0560     return 0;
0561 err:
0562     dev->bandwidth = 0;
0563     dev->frequency = 0;
0564     dev->if_frequency = 0;
0565     dev_dbg(&client->dev, "failed=%d\n", ret);
0566     return ret;
0567 }
0568 
0569 static int si2157_set_analog_params(struct dvb_frontend *fe,
0570                     struct analog_parameters *params)
0571 {
0572     struct i2c_client *client = fe->tuner_priv;
0573     struct si2157_dev *dev = i2c_get_clientdata(client);
0574     char *std; /* for debugging */
0575     int ret;
0576     struct si2157_cmd cmd;
0577     u32 bandwidth = 0;
0578     u32 if_frequency = 0;
0579     u32 freq = 0;
0580     u64 tmp_lval = 0;
0581     u8 system = 0;
0582     u8 color = 0;    /* 0=NTSC/PAL, 0x10=SECAM */
0583     u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */
0584 
0585     if (!SUPPORTS_ATV_IF(dev)) {
0586         dev_info(&client->dev, "Analog tuning not supported yet for Si21%d\n",
0587              dev->part_id);
0588         ret = -EINVAL;
0589         goto err;
0590     }
0591 
0592     if (!dev->active)
0593         si2157_init(fe);
0594 
0595     if (!dev->active) {
0596         ret = -EAGAIN;
0597         goto err;
0598     }
0599     if (params->mode == V4L2_TUNER_RADIO) {
0600     /*
0601      * std = "fm";
0602      * bandwidth = 1700000; //best can do for FM, AGC will be a mess though
0603      * if_frequency = 1250000;  //HVR-225x(saa7164), HVR-12xx(cx23885)
0604      * if_frequency = 6600000;  //HVR-9xx(cx231xx)
0605      * if_frequency = 5500000;  //HVR-19xx(pvrusb2)
0606      */
0607         dev_err(&client->dev, "si2157 does not currently support FM radio\n");
0608         ret = -EINVAL;
0609         goto err;
0610     }
0611     tmp_lval = params->frequency * 625LL;
0612     do_div(tmp_lval, 10); /* convert to HZ */
0613     freq = (u32)tmp_lval;
0614 
0615     if (freq < 1000000) /* is freq in KHz */
0616         freq = freq * 1000;
0617     dev->frequency = freq;
0618 
0619     /* if_frequency values based on tda187271C2 */
0620     if (params->std & (V4L2_STD_B | V4L2_STD_GH)) {
0621         if (freq >= 470000000) {
0622             std = "palGH";
0623             bandwidth = 8000000;
0624             if_frequency = 6000000;
0625             system = 1;
0626             if (params->std &
0627                 (V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)) {
0628                 std = "secamGH";
0629                 color = 0x10;
0630             }
0631         } else {
0632             std = "palB";
0633             bandwidth = 7000000;
0634             if_frequency = 6000000;
0635             system = 0;
0636             if (params->std & V4L2_STD_SECAM_B) {
0637                 std = "secamB";
0638                 color = 0x10;
0639             }
0640         }
0641     } else if (params->std & V4L2_STD_MN) {
0642         std = "MN";
0643         bandwidth = 6000000;
0644         if_frequency = 5400000;
0645         system = 2;
0646     } else if (params->std & V4L2_STD_PAL_I) {
0647         std = "palI";
0648         bandwidth = 8000000;
0649         if_frequency = 7250000; /* TODO: does not work yet */
0650         system = 4;
0651     } else if (params->std & V4L2_STD_DK) {
0652         std = "palDK";
0653         bandwidth = 8000000;
0654         if_frequency = 6900000; /* TODO: does not work yet */
0655         system = 5;
0656         if (params->std & V4L2_STD_SECAM_DK) {
0657             std = "secamDK";
0658             color = 0x10;
0659         }
0660     } else if (params->std & V4L2_STD_SECAM_L) {
0661         std = "secamL";
0662         bandwidth = 8000000;
0663         if_frequency = 6750000; /* TODO: untested */
0664         system = 6;
0665         color = 0x10;
0666     } else if (params->std & V4L2_STD_SECAM_LC) {
0667         std = "secamL'";
0668         bandwidth = 7000000;
0669         if_frequency = 1250000; /* TODO: untested */
0670         system = 7;
0671         color = 0x10;
0672     } else {
0673         std = "unknown";
0674     }
0675     /* calc channel center freq */
0676     freq = freq - 1250000 + (bandwidth / 2);
0677 
0678     dev_dbg(&client->dev,
0679         "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n",
0680         params->mode, system, std, params->frequency,
0681         freq, if_frequency, bandwidth);
0682 
0683     /* set analog IF port */
0684     memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6);
0685     /* in using dev->if_port, we assume analog and digital IF's */
0686     /*   are always on different ports */
0687     /* assumes if_port definition is 0 or 1 for digital out */
0688     cmd.args[4] = (dev->if_port == 1) ? 8 : 10;
0689     /* Analog AGC assumed external */
0690     cmd.args[5] = (dev->if_port == 1) ? 2 : 1;
0691     cmd.wlen = 6;
0692     cmd.rlen = 4;
0693     ret = si2157_cmd_execute(client, &cmd);
0694     if (ret)
0695         goto err;
0696 
0697     /* set analog IF output config */
0698     memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6);
0699     cmd.wlen = 6;
0700     cmd.rlen = 4;
0701     ret = si2157_cmd_execute(client, &cmd);
0702     if (ret)
0703         goto err;
0704 
0705     /* make this distinct from a digital IF */
0706     dev->if_frequency = if_frequency | 1;
0707 
0708     /* calc and set tuner analog if center frequency */
0709     if_frequency = if_frequency + 1250000 - (bandwidth / 2);
0710     dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency);
0711 
0712     memcpy(cmd.args, "\x14\x00\x0C\x06", 4);
0713     cmd.args[4] = (if_frequency / 1000) & 0xff;
0714     cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
0715     cmd.wlen = 6;
0716     cmd.rlen = 4;
0717     ret = si2157_cmd_execute(client, &cmd);
0718     if (ret)
0719         goto err;
0720 
0721     /* set analog AGC config */
0722     memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6);
0723     cmd.wlen = 6;
0724     cmd.rlen = 4;
0725     ret = si2157_cmd_execute(client, &cmd);
0726     if (ret)
0727         goto err;
0728 
0729     /* set analog video mode */
0730     memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6);
0731     cmd.args[4] = system | color;
0732     /* can use dev->inversion if assumed applies to both digital/analog */
0733     if (invert_analog)
0734         cmd.args[5] |= 0x02;
0735     cmd.wlen = 6;
0736     cmd.rlen = 1;
0737     ret = si2157_cmd_execute(client, &cmd);
0738     if (ret)
0739         goto err;
0740 
0741     /* set analog frequency */
0742     memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8);
0743     cmd.args[4] = (freq >>  0) & 0xff;
0744     cmd.args[5] = (freq >>  8) & 0xff;
0745     cmd.args[6] = (freq >> 16) & 0xff;
0746     cmd.args[7] = (freq >> 24) & 0xff;
0747     cmd.wlen = 8;
0748     cmd.rlen = 1;
0749     ret = si2157_cmd_execute(client, &cmd);
0750     if (ret)
0751         goto err;
0752 
0753     dev->bandwidth = bandwidth;
0754 
0755     si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */
0756 
0757     return 0;
0758 err:
0759     dev->bandwidth = 0;
0760     dev->frequency = 0;
0761     dev->if_frequency = 0;
0762     dev_dbg(&client->dev, "failed=%d\n", ret);
0763     return ret;
0764 }
0765 
0766 static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0767 {
0768     struct i2c_client *client = fe->tuner_priv;
0769     struct si2157_dev *dev = i2c_get_clientdata(client);
0770 
0771     *frequency = dev->frequency;
0772     dev_dbg(&client->dev, "freq=%u\n", dev->frequency);
0773     return 0;
0774 }
0775 
0776 static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
0777 {
0778     struct i2c_client *client = fe->tuner_priv;
0779     struct si2157_dev *dev = i2c_get_clientdata(client);
0780 
0781     *bandwidth = dev->bandwidth;
0782     dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth);
0783     return 0;
0784 }
0785 
0786 static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
0787 {
0788     struct i2c_client *client = fe->tuner_priv;
0789     struct si2157_dev *dev = i2c_get_clientdata(client);
0790 
0791     *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */
0792     dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);
0793     return 0;
0794 }
0795 
0796 static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)
0797 {
0798     struct i2c_client *client = fe->tuner_priv;
0799     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0800     struct si2157_cmd cmd;
0801     int ret;
0802     int strength;
0803 
0804     dev_dbg(&client->dev, "\n");
0805 
0806     memcpy(cmd.args, "\x42\x00", 2);
0807     cmd.wlen = 2;
0808     cmd.rlen = 12;
0809     ret = si2157_cmd_execute(client, &cmd);
0810     if (ret)
0811         goto err;
0812 
0813     c->strength.stat[0].scale = FE_SCALE_DECIBEL;
0814     c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;
0815 
0816     /* normalize values based on Silicon Labs reference
0817      * add 100, then anything > 80 is 100% signal
0818      */
0819     strength = (s8)cmd.args[3] + 100;
0820     strength = clamp_val(strength, 0, 80);
0821     *rssi = (u16)(strength * 0xffff / 80);
0822 
0823     dev_dbg(&client->dev, "strength=%d rssi=%u\n",
0824         (s8)cmd.args[3], *rssi);
0825 
0826     return 0;
0827 err:
0828     dev_dbg(&client->dev, "failed=%d\n", ret);
0829     return ret;
0830 }
0831 
0832 static const struct dvb_tuner_ops si2157_ops = {
0833     .info = {
0834         .name             = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158",
0835         .frequency_min_hz =  42 * MHz,
0836         .frequency_max_hz = 870 * MHz,
0837     },
0838 
0839     .init = si2157_init,
0840     .sleep = si2157_sleep,
0841     .set_params = si2157_set_params,
0842     .set_analog_params = si2157_set_analog_params,
0843     .get_frequency     = si2157_get_frequency,
0844     .get_bandwidth     = si2157_get_bandwidth,
0845     .get_if_frequency  = si2157_get_if_frequency,
0846 
0847     .get_rf_strength   = si2157_get_rf_strength,
0848 };
0849 
0850 static void si2157_stat_work(struct work_struct *work)
0851 {
0852     struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work);
0853     struct dvb_frontend *fe = dev->fe;
0854     struct i2c_client *client = fe->tuner_priv;
0855     struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0856     struct si2157_cmd cmd;
0857     int ret;
0858 
0859     dev_dbg(&client->dev, "\n");
0860 
0861     memcpy(cmd.args, "\x42\x00", 2);
0862     cmd.wlen = 2;
0863     cmd.rlen = 12;
0864     ret = si2157_cmd_execute(client, &cmd);
0865     if (ret)
0866         goto err;
0867 
0868     c->strength.stat[0].scale = FE_SCALE_DECIBEL;
0869     c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
0870 
0871     schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
0872     return;
0873 err:
0874     c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0875     dev_dbg(&client->dev, "failed=%d\n", ret);
0876 }
0877 
0878 static int si2157_probe(struct i2c_client *client,
0879             const struct i2c_device_id *id)
0880 {
0881     struct si2157_config *cfg = client->dev.platform_data;
0882     struct dvb_frontend *fe = cfg->fe;
0883     struct si2157_dev *dev;
0884     struct si2157_cmd cmd;
0885     int ret;
0886 
0887     dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0888     if (!dev) {
0889         ret = -ENOMEM;
0890         dev_err(&client->dev, "kzalloc() failed\n");
0891         goto err;
0892     }
0893 
0894     i2c_set_clientdata(client, dev);
0895     dev->fe = cfg->fe;
0896     dev->inversion = cfg->inversion;
0897     dev->dont_load_firmware = cfg->dont_load_firmware;
0898     dev->if_port = cfg->if_port;
0899     dev->part_id = (u8)id->driver_data;
0900     dev->if_frequency = 5000000; /* default value of property 0x0706 */
0901     mutex_init(&dev->i2c_mutex);
0902     INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);
0903 
0904     /* check if the tuner is there */
0905     cmd.wlen = 0;
0906     cmd.rlen = 1;
0907     ret = si2157_cmd_execute(client, &cmd);
0908     if (ret && ret != -EAGAIN)
0909         goto err_kfree;
0910 
0911     memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
0912     fe->tuner_priv = client;
0913 
0914 #ifdef CONFIG_MEDIA_CONTROLLER
0915     if (cfg->mdev) {
0916         dev->mdev = cfg->mdev;
0917 
0918         dev->ent.name = KBUILD_MODNAME;
0919         dev->ent.function = MEDIA_ENT_F_TUNER;
0920 
0921         dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
0922         dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
0923         dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
0924         dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG;
0925         dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
0926         dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
0927 
0928         ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
0929                          &dev->pad[0]);
0930 
0931         if (ret)
0932             goto err_kfree;
0933 
0934         ret = media_device_register_entity(cfg->mdev, &dev->ent);
0935         if (ret) {
0936             media_entity_cleanup(&dev->ent);
0937             goto err_kfree;
0938         }
0939     }
0940 #endif
0941 
0942     dev_info(&client->dev, "Silicon Labs Si21%d successfully attached\n",
0943          dev->part_id);
0944 
0945     return 0;
0946 
0947 err_kfree:
0948     kfree(dev);
0949 err:
0950     dev_dbg(&client->dev, "failed=%d\n", ret);
0951     return ret;
0952 }
0953 
0954 static int si2157_remove(struct i2c_client *client)
0955 {
0956     struct si2157_dev *dev = i2c_get_clientdata(client);
0957     struct dvb_frontend *fe = dev->fe;
0958 
0959     dev_dbg(&client->dev, "\n");
0960 
0961     /* stop statistics polling */
0962     cancel_delayed_work_sync(&dev->stat_work);
0963 
0964 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
0965     if (dev->mdev)
0966         media_device_unregister_entity(&dev->ent);
0967 #endif
0968 
0969     memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
0970     fe->tuner_priv = NULL;
0971     kfree(dev);
0972 
0973     return 0;
0974 }
0975 
0976 /*
0977  * The part_id used here will only be used on buggy devices that don't
0978  * accept firmware uploads. Non-buggy devices should just use "si2157" for
0979  * all SiLabs TER tuners, as the driver should auto-detect it.
0980  */
0981 static const struct i2c_device_id si2157_id_table[] = {
0982     {"si2157", SI2157},
0983     {"si2146", SI2146},
0984     {"si2141", SI2141},
0985     {"si2177", SI2177},
0986     {}
0987 };
0988 MODULE_DEVICE_TABLE(i2c, si2157_id_table);
0989 
0990 static struct i2c_driver si2157_driver = {
0991     .driver = {
0992         .name            = "si2157",
0993         .suppress_bind_attrs = true,
0994     },
0995     .probe      = si2157_probe,
0996     .remove     = si2157_remove,
0997     .id_table   = si2157_id_table,
0998 };
0999 
1000 module_i2c_driver(si2157_driver);
1001 
1002 MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");
1003 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
1004 MODULE_LICENSE("GPL");
1005 MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
1006 MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
1007 MODULE_FIRMWARE(SI2157_A30_FIRMWARE);
1008 MODULE_FIRMWARE(SI2141_60_FIRMWARE);
1009 MODULE_FIRMWARE(SI2141_61_FIRMWARE);
1010 MODULE_FIRMWARE(SI2146_11_FIRMWARE);
1011 MODULE_FIRMWARE(SI2147_50_FIRMWARE);
1012 MODULE_FIRMWARE(SI2148_32_FIRMWARE);
1013 MODULE_FIRMWARE(SI2148_33_FIRMWARE);
1014 MODULE_FIRMWARE(SI2157_50_FIRMWARE);
1015 MODULE_FIRMWARE(SI2158_50_FIRMWARE);
1016 MODULE_FIRMWARE(SI2158_51_FIRMWARE);
1017 MODULE_FIRMWARE(SI2177_50_FIRMWARE);