0001
0002
0003
0004
0005
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
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
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
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
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
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
0101 ret = firmware_request_nowarn(&fw, fw_name, &client->dev);
0102 if (ret)
0103 return ret;
0104
0105
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
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
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
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
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
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;
0239
0240
0241 if (dev->part_id == SI2146) {
0242
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
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
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
0268 ret = si2157_find_and_load_firmware(fe);
0269 if (ret < 0)
0270 goto err;
0271
0272
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
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
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
0314 c->strength.len = 1;
0315 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
0316
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
0339 cancel_delayed_work_sync(&dev->stat_work);
0340
0341
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
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
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
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
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:
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
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
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
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);
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;
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;
0583 u8 invert_analog = 1;
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
0602
0603
0604
0605
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);
0613 freq = (u32)tmp_lval;
0614
0615 if (freq < 1000000)
0616 freq = freq * 1000;
0617 dev->frequency = freq;
0618
0619
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;
0650 system = 4;
0651 } else if (params->std & V4L2_STD_DK) {
0652 std = "palDK";
0653 bandwidth = 8000000;
0654 if_frequency = 6900000;
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;
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;
0670 system = 7;
0671 color = 0x10;
0672 } else {
0673 std = "unknown";
0674 }
0675
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
0684 memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6);
0685
0686
0687
0688 cmd.args[4] = (dev->if_port == 1) ? 8 : 10;
0689
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
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
0706 dev->if_frequency = if_frequency | 1;
0707
0708
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
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
0730 memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6);
0731 cmd.args[4] = system | color;
0732
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
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);
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;
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
0817
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;
0901 mutex_init(&dev->i2c_mutex);
0902 INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);
0903
0904
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
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
0978
0979
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);