linux/drivers/media/tuners/si2157.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
   4 *
   5 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
   6 */
   7
   8#include "si2157_priv.h"
   9
  10static const struct dvb_tuner_ops si2157_ops;
  11
  12static int tuner_lock_debug;
  13module_param(tuner_lock_debug, int, 0644);
  14MODULE_PARM_DESC(tuner_lock_debug, "if set, signal lock is briefly waited on after setting params");
  15
  16/* execute firmware command */
  17static int si2157_cmd_execute(struct i2c_client *client, struct si2157_cmd *cmd)
  18{
  19        struct si2157_dev *dev = i2c_get_clientdata(client);
  20        int ret;
  21        unsigned long timeout;
  22
  23        mutex_lock(&dev->i2c_mutex);
  24
  25        if (cmd->wlen) {
  26                /* write cmd and args for firmware */
  27                ret = i2c_master_send(client, cmd->args, cmd->wlen);
  28                if (ret < 0) {
  29                        goto err_mutex_unlock;
  30                } else if (ret != cmd->wlen) {
  31                        ret = -EREMOTEIO;
  32                        goto err_mutex_unlock;
  33                }
  34        }
  35
  36        if (cmd->rlen) {
  37                /* wait cmd execution terminate */
  38                #define TIMEOUT 80
  39                timeout = jiffies + msecs_to_jiffies(TIMEOUT);
  40                while (!time_after(jiffies, timeout)) {
  41                        ret = i2c_master_recv(client, cmd->args, cmd->rlen);
  42                        if (ret < 0) {
  43                                goto err_mutex_unlock;
  44                        } else if (ret != cmd->rlen) {
  45                                ret = -EREMOTEIO;
  46                                goto err_mutex_unlock;
  47                        }
  48
  49                        /* firmware ready? */
  50                        if ((cmd->args[0] >> 7) & 0x01)
  51                                break;
  52                }
  53
  54                dev_dbg(&client->dev, "cmd execution took %d ms, status=%x\n",
  55                        jiffies_to_msecs(jiffies) -
  56                        (jiffies_to_msecs(timeout) - TIMEOUT),
  57                        cmd->args[0]);
  58
  59                if (!((cmd->args[0] >> 7) & 0x01)) {
  60                        ret = -ETIMEDOUT;
  61                        goto err_mutex_unlock;
  62                }
  63                /* check error status bit */
  64                if (cmd->args[0] & 0x40) {
  65                        ret = -EAGAIN;
  66                        goto err_mutex_unlock;
  67                }
  68        }
  69
  70        mutex_unlock(&dev->i2c_mutex);
  71        return 0;
  72
  73err_mutex_unlock:
  74        mutex_unlock(&dev->i2c_mutex);
  75        dev_dbg(&client->dev, "failed=%d\n", ret);
  76        return ret;
  77}
  78
  79static int si2157_init(struct dvb_frontend *fe)
  80{
  81        struct i2c_client *client = fe->tuner_priv;
  82        struct si2157_dev *dev = i2c_get_clientdata(client);
  83        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  84        int ret, len, remaining;
  85        struct si2157_cmd cmd;
  86        const struct firmware *fw;
  87        const char *fw_name;
  88        unsigned int chip_id, xtal_trim;
  89
  90        dev_dbg(&client->dev, "\n");
  91
  92        /* Try to get Xtal trim property, to verify tuner still running */
  93        memcpy(cmd.args, "\x15\x00\x04\x02", 4);
  94        cmd.wlen = 4;
  95        cmd.rlen = 4;
  96        ret = si2157_cmd_execute(client, &cmd);
  97
  98        xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
  99
 100        if (ret == 0 && xtal_trim < 16)
 101                goto warm;
 102
 103        dev->if_frequency = 0; /* we no longer know current tuner state */
 104
 105        /* power up */
 106        if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
 107                memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
 108                cmd.wlen = 9;
 109        } else if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
 110                memcpy(cmd.args, "\xc0\x00\x0d\x0e\x00\x01\x01\x01\x01\x03", 10);
 111                cmd.wlen = 10;
 112        } else {
 113                memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
 114                cmd.wlen = 15;
 115        }
 116        cmd.rlen = 1;
 117        ret = si2157_cmd_execute(client, &cmd);
 118        if (ret && (dev->chiptype != SI2157_CHIPTYPE_SI2141 || ret != -EAGAIN))
 119                goto err;
 120
 121        /* Si2141 needs a second command before it answers the revision query */
 122        if (dev->chiptype == SI2157_CHIPTYPE_SI2141) {
 123                memcpy(cmd.args, "\xc0\x08\x01\x02\x00\x00\x01", 7);
 124                cmd.wlen = 7;
 125                ret = si2157_cmd_execute(client, &cmd);
 126                if (ret)
 127                        goto err;
 128        }
 129
 130        if (dev->dont_load_firmware) {
 131                dev_info(&client->dev, "device is buggy, skipping firmware download\n");
 132                goto skip_fw_download;
 133        }
 134
 135        /* query chip revision */
 136        memcpy(cmd.args, "\x02", 1);
 137        cmd.wlen = 1;
 138        cmd.rlen = 13;
 139        ret = si2157_cmd_execute(client, &cmd);
 140        if (ret)
 141                goto err;
 142
 143        chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
 144                        cmd.args[4] << 0;
 145
 146        #define SI2177_A30 ('A' << 24 | 77 << 16 | '3' << 8 | '0' << 0)
 147        #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
 148        #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
 149        #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
 150        #define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
 151        #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
 152        #define SI2141_A10 ('A' << 24 | 41 << 16 | '1' << 8 | '0' << 0)
 153
 154        switch (chip_id) {
 155        case SI2158_A20:
 156        case SI2148_A20:
 157                fw_name = SI2158_A20_FIRMWARE;
 158                break;
 159        case SI2141_A10:
 160                fw_name = SI2141_A10_FIRMWARE;
 161                break;
 162        case SI2177_A30:
 163                fw_name = SI2157_A30_FIRMWARE;
 164                break;
 165        case SI2157_A30:
 166        case SI2147_A30:
 167        case SI2146_A10:
 168                fw_name = NULL;
 169                break;
 170        default:
 171                dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
 172                                cmd.args[2], cmd.args[1],
 173                                cmd.args[3], cmd.args[4]);
 174                ret = -EINVAL;
 175                goto err;
 176        }
 177
 178        dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
 179                        cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
 180
 181        if (fw_name == NULL)
 182                goto skip_fw_download;
 183
 184        /* request the firmware, this will block and timeout */
 185        ret = request_firmware(&fw, fw_name, &client->dev);
 186        if (ret) {
 187                dev_err(&client->dev, "firmware file '%s' not found\n",
 188                                fw_name);
 189                goto err;
 190        }
 191
 192        /* firmware should be n chunks of 17 bytes */
 193        if (fw->size % 17 != 0) {
 194                dev_err(&client->dev, "firmware file '%s' is invalid\n",
 195                                fw_name);
 196                ret = -EINVAL;
 197                goto err_release_firmware;
 198        }
 199
 200        dev_info(&client->dev, "downloading firmware from file '%s'\n",
 201                        fw_name);
 202
 203        for (remaining = fw->size; remaining > 0; remaining -= 17) {
 204                len = fw->data[fw->size - remaining];
 205                if (len > SI2157_ARGLEN) {
 206                        dev_err(&client->dev, "Bad firmware length\n");
 207                        ret = -EINVAL;
 208                        goto err_release_firmware;
 209                }
 210                memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
 211                cmd.wlen = len;
 212                cmd.rlen = 1;
 213                ret = si2157_cmd_execute(client, &cmd);
 214                if (ret) {
 215                        dev_err(&client->dev, "firmware download failed %d\n",
 216                                        ret);
 217                        goto err_release_firmware;
 218                }
 219        }
 220
 221        release_firmware(fw);
 222
 223skip_fw_download:
 224        /* reboot the tuner with new firmware? */
 225        memcpy(cmd.args, "\x01\x01", 2);
 226        cmd.wlen = 2;
 227        cmd.rlen = 1;
 228        ret = si2157_cmd_execute(client, &cmd);
 229        if (ret)
 230                goto err;
 231
 232        /* query firmware version */
 233        memcpy(cmd.args, "\x11", 1);
 234        cmd.wlen = 1;
 235        cmd.rlen = 10;
 236        ret = si2157_cmd_execute(client, &cmd);
 237        if (ret)
 238                goto err;
 239
 240        dev_info(&client->dev, "firmware version: %c.%c.%d\n",
 241                        cmd.args[6], cmd.args[7], cmd.args[8]);
 242
 243        /* enable tuner status flags */
 244        memcpy(cmd.args, "\x14\x00\x01\x05\x01\x00", 6);
 245        cmd.wlen = 6;
 246        cmd.rlen = 1;
 247        ret = si2157_cmd_execute(client, &cmd);
 248        if (ret)
 249                goto err;
 250
 251        memcpy(cmd.args, "\x14\x00\x01\x06\x01\x00", 6);
 252        cmd.wlen = 6;
 253        cmd.rlen = 1;
 254        ret = si2157_cmd_execute(client, &cmd);
 255        if (ret)
 256                goto err;
 257
 258        memcpy(cmd.args, "\x14\x00\x01\x07\x01\x00", 6);
 259        cmd.wlen = 6;
 260        cmd.rlen = 1;
 261        ret = si2157_cmd_execute(client, &cmd);
 262        if (ret)
 263                goto err;
 264warm:
 265        /* init statistics in order signal app which are supported */
 266        c->strength.len = 1;
 267        c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 268        /* start statistics polling */
 269        schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(1000));
 270
 271        dev->active = true;
 272        return 0;
 273err_release_firmware:
 274        release_firmware(fw);
 275err:
 276        dev_dbg(&client->dev, "failed=%d\n", ret);
 277        return ret;
 278}
 279
 280static int si2157_sleep(struct dvb_frontend *fe)
 281{
 282        struct i2c_client *client = fe->tuner_priv;
 283        struct si2157_dev *dev = i2c_get_clientdata(client);
 284        int ret;
 285        struct si2157_cmd cmd;
 286
 287        dev_dbg(&client->dev, "\n");
 288
 289        dev->active = false;
 290
 291        /* stop statistics polling */
 292        cancel_delayed_work_sync(&dev->stat_work);
 293
 294        /* standby */
 295        memcpy(cmd.args, "\x16\x00", 2);
 296        cmd.wlen = 2;
 297        cmd.rlen = 1;
 298        ret = si2157_cmd_execute(client, &cmd);
 299        if (ret)
 300                goto err;
 301
 302        return 0;
 303err:
 304        dev_dbg(&client->dev, "failed=%d\n", ret);
 305        return ret;
 306}
 307
 308static int si2157_tune_wait(struct i2c_client *client, u8 is_digital)
 309{
 310#define TUN_TIMEOUT 40
 311#define DIG_TIMEOUT 30
 312#define ANALOG_TIMEOUT 150
 313        struct si2157_dev *dev = i2c_get_clientdata(client);
 314        int ret;
 315        unsigned long timeout;
 316        unsigned long start_time;
 317        u8 wait_status;
 318        u8  tune_lock_mask;
 319
 320        if (is_digital)
 321                tune_lock_mask = 0x04;
 322        else
 323                tune_lock_mask = 0x02;
 324
 325        mutex_lock(&dev->i2c_mutex);
 326
 327        /* wait tuner command complete */
 328        start_time = jiffies;
 329        timeout = start_time + msecs_to_jiffies(TUN_TIMEOUT);
 330        while (1) {
 331                ret = i2c_master_recv(client, &wait_status,
 332                                      sizeof(wait_status));
 333                if (ret < 0) {
 334                        goto err_mutex_unlock;
 335                } else if (ret != sizeof(wait_status)) {
 336                        ret = -EREMOTEIO;
 337                        goto err_mutex_unlock;
 338                }
 339
 340                if (time_after(jiffies, timeout))
 341                        break;
 342
 343                /* tuner done? */
 344                if ((wait_status & 0x81) == 0x81)
 345                        break;
 346                usleep_range(5000, 10000);
 347        }
 348
 349        dev_dbg(&client->dev, "tuning took %d ms, status=0x%x\n",
 350                jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
 351                wait_status);
 352
 353        /* if we tuned ok, wait a bit for tuner lock */
 354        if (tuner_lock_debug && (wait_status & 0x81) == 0x81) {
 355                if (is_digital)
 356                        timeout = jiffies + msecs_to_jiffies(DIG_TIMEOUT);
 357                else
 358                        timeout = jiffies + msecs_to_jiffies(ANALOG_TIMEOUT);
 359
 360                while (!time_after(jiffies, timeout)) {
 361                        ret = i2c_master_recv(client, &wait_status,
 362                                              sizeof(wait_status));
 363                        if (ret < 0) {
 364                                goto err_mutex_unlock;
 365                        } else if (ret != sizeof(wait_status)) {
 366                                ret = -EREMOTEIO;
 367                                goto err_mutex_unlock;
 368                        }
 369
 370                        /* tuner locked? */
 371                        if (wait_status & tune_lock_mask)
 372                                break;
 373                        usleep_range(5000, 10000);
 374                }
 375
 376                dev_dbg(&client->dev, "tuning+lock took %d ms, status=0x%x\n",
 377                        jiffies_to_msecs(jiffies) - jiffies_to_msecs(start_time),
 378                        wait_status);
 379        }
 380
 381        if ((wait_status & 0xc0) != 0x80) {
 382                ret = -ETIMEDOUT;
 383                goto err_mutex_unlock;
 384        }
 385
 386        mutex_unlock(&dev->i2c_mutex);
 387        return 0;
 388
 389err_mutex_unlock:
 390        mutex_unlock(&dev->i2c_mutex);
 391        dev_err(&client->dev, "failed=%d\n", ret);
 392        return ret;
 393}
 394
 395static int si2157_set_params(struct dvb_frontend *fe)
 396{
 397        struct i2c_client *client = fe->tuner_priv;
 398        struct si2157_dev *dev = i2c_get_clientdata(client);
 399        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 400        int ret;
 401        struct si2157_cmd cmd;
 402        u8 bandwidth, delivery_system;
 403        u32 if_frequency = 5000000;
 404
 405        dev_dbg(&client->dev,
 406                        "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
 407                        c->delivery_system, c->frequency, c->bandwidth_hz);
 408
 409        if (!dev->active) {
 410                ret = -EAGAIN;
 411                goto err;
 412        }
 413
 414        if (c->bandwidth_hz <= 6000000)
 415                bandwidth = 0x06;
 416        else if (c->bandwidth_hz <= 7000000)
 417                bandwidth = 0x07;
 418        else if (c->bandwidth_hz <= 8000000)
 419                bandwidth = 0x08;
 420        else
 421                bandwidth = 0x0f;
 422
 423        switch (c->delivery_system) {
 424        case SYS_ATSC:
 425                        delivery_system = 0x00;
 426                        if_frequency = 3250000;
 427                        break;
 428        case SYS_DVBC_ANNEX_B:
 429                        delivery_system = 0x10;
 430                        if_frequency = 4000000;
 431                        break;
 432        case SYS_DVBT:
 433        case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
 434                        delivery_system = 0x20;
 435                        break;
 436        case SYS_DVBC_ANNEX_A:
 437                        delivery_system = 0x30;
 438                        break;
 439        default:
 440                        ret = -EINVAL;
 441                        goto err;
 442        }
 443
 444        memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
 445        cmd.args[4] = delivery_system | bandwidth;
 446        if (dev->inversion)
 447                cmd.args[5] = 0x01;
 448        cmd.wlen = 6;
 449        cmd.rlen = 4;
 450        ret = si2157_cmd_execute(client, &cmd);
 451        if (ret)
 452                goto err;
 453
 454        if (dev->chiptype == SI2157_CHIPTYPE_SI2146)
 455                memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
 456        else
 457                memcpy(cmd.args, "\x14\x00\x02\x07\x00\x00", 6);
 458        cmd.args[4] = dev->if_port;
 459        cmd.wlen = 6;
 460        cmd.rlen = 4;
 461        ret = si2157_cmd_execute(client, &cmd);
 462        if (ret)
 463                goto err;
 464
 465        /* set digital if frequency if needed */
 466        if (if_frequency != dev->if_frequency) {
 467                memcpy(cmd.args, "\x14\x00\x06\x07", 4);
 468                cmd.args[4] = (if_frequency / 1000) & 0xff;
 469                cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
 470                cmd.wlen = 6;
 471                cmd.rlen = 4;
 472                ret = si2157_cmd_execute(client, &cmd);
 473                if (ret)
 474                        goto err;
 475
 476                dev->if_frequency = if_frequency;
 477        }
 478
 479        /* set digital frequency */
 480        memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
 481        cmd.args[4] = (c->frequency >>  0) & 0xff;
 482        cmd.args[5] = (c->frequency >>  8) & 0xff;
 483        cmd.args[6] = (c->frequency >> 16) & 0xff;
 484        cmd.args[7] = (c->frequency >> 24) & 0xff;
 485        cmd.wlen = 8;
 486        cmd.rlen = 1;
 487        ret = si2157_cmd_execute(client, &cmd);
 488        if (ret)
 489                goto err;
 490
 491        dev->bandwidth = bandwidth;
 492        dev->frequency = c->frequency;
 493
 494        si2157_tune_wait(client, 1); /* wait to complete, ignore any errors */
 495
 496        return 0;
 497err:
 498        dev->bandwidth = 0;
 499        dev->frequency = 0;
 500        dev->if_frequency = 0;
 501        dev_dbg(&client->dev, "failed=%d\n", ret);
 502        return ret;
 503}
 504
 505static int si2157_set_analog_params(struct dvb_frontend *fe,
 506                                    struct analog_parameters *params)
 507{
 508        struct i2c_client *client = fe->tuner_priv;
 509        struct si2157_dev *dev = i2c_get_clientdata(client);
 510        char *std; /* for debugging */
 511        int ret;
 512        struct si2157_cmd cmd;
 513        u32 bandwidth = 0;
 514        u32 if_frequency = 0;
 515        u32 freq = 0;
 516        u64 tmp_lval = 0;
 517        u8 system = 0;
 518        u8 color = 0;    /* 0=NTSC/PAL, 0x10=SECAM */
 519        u8 invert_analog = 1; /* analog tuner spectrum; 0=normal, 1=inverted */
 520
 521        if (dev->chiptype != SI2157_CHIPTYPE_SI2157) {
 522                dev_info(&client->dev, "Analog tuning not supported for chiptype=%u\n",
 523                         dev->chiptype);
 524                ret = -EINVAL;
 525                goto err;
 526        }
 527
 528        if (!dev->active)
 529                si2157_init(fe);
 530
 531        if (!dev->active) {
 532                ret = -EAGAIN;
 533                goto err;
 534        }
 535        if (params->mode == V4L2_TUNER_RADIO) {
 536        /*
 537         * std = "fm";
 538         * bandwidth = 1700000; //best can do for FM, AGC will be a mess though
 539         * if_frequency = 1250000;  //HVR-225x(saa7164), HVR-12xx(cx23885)
 540         * if_frequency = 6600000;  //HVR-9xx(cx231xx)
 541         * if_frequency = 5500000;  //HVR-19xx(pvrusb2)
 542         */
 543                dev_err(&client->dev, "si2157 does not currently support FM radio\n");
 544                ret = -EINVAL;
 545                goto err;
 546        }
 547        tmp_lval = params->frequency * 625LL;
 548        do_div(tmp_lval, 10); /* convert to HZ */
 549        freq = (u32)tmp_lval;
 550
 551        if (freq < 1000000) /* is freq in KHz */
 552                freq = freq * 1000;
 553        dev->frequency = freq;
 554
 555        /* if_frequency values based on tda187271C2 */
 556        if (params->std & (V4L2_STD_B | V4L2_STD_GH)) {
 557                if (freq >= 470000000) {
 558                        std = "palGH";
 559                        bandwidth = 8000000;
 560                        if_frequency = 6000000;
 561                        system = 1;
 562                        if (params->std &
 563                            (V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)) {
 564                                std = "secamGH";
 565                                color = 0x10;
 566                        }
 567                } else {
 568                        std = "palB";
 569                        bandwidth = 7000000;
 570                        if_frequency = 6000000;
 571                        system = 0;
 572                        if (params->std & V4L2_STD_SECAM_B) {
 573                                std = "secamB";
 574                                color = 0x10;
 575                        }
 576                }
 577        } else if (params->std & V4L2_STD_MN) {
 578                std = "MN";
 579                bandwidth = 6000000;
 580                if_frequency = 5400000;
 581                system = 2;
 582        } else if (params->std & V4L2_STD_PAL_I) {
 583                std = "palI";
 584                bandwidth = 8000000;
 585                if_frequency = 7250000; /* TODO: does not work yet */
 586                system = 4;
 587        } else if (params->std & V4L2_STD_DK) {
 588                std = "palDK";
 589                bandwidth = 8000000;
 590                if_frequency = 6900000; /* TODO: does not work yet */
 591                system = 5;
 592                if (params->std & V4L2_STD_SECAM_DK) {
 593                        std = "secamDK";
 594                        color = 0x10;
 595                }
 596        } else if (params->std & V4L2_STD_SECAM_L) {
 597                std = "secamL";
 598                bandwidth = 8000000;
 599                if_frequency = 6750000; /* TODO: untested */
 600                system = 6;
 601                color = 0x10;
 602        } else if (params->std & V4L2_STD_SECAM_LC) {
 603                std = "secamL'";
 604                bandwidth = 7000000;
 605                if_frequency = 1250000; /* TODO: untested */
 606                system = 7;
 607                color = 0x10;
 608        } else {
 609                std = "unknown";
 610        }
 611        /* calc channel center freq */
 612        freq = freq - 1250000 + (bandwidth / 2);
 613
 614        dev_dbg(&client->dev,
 615                "mode=%d system=%u std='%s' params->frequency=%u center freq=%u if=%u bandwidth=%u\n",
 616                params->mode, system, std, params->frequency,
 617                freq, if_frequency, bandwidth);
 618
 619        /* set analog IF port */
 620        memcpy(cmd.args, "\x14\x00\x03\x06\x08\x02", 6);
 621        /* in using dev->if_port, we assume analog and digital IF's */
 622        /*   are always on different ports */
 623        /* assumes if_port definition is 0 or 1 for digital out */
 624        cmd.args[4] = (dev->if_port == 1) ? 8 : 10;
 625        /* Analog AGC assumed external */
 626        cmd.args[5] = (dev->if_port == 1) ? 2 : 1;
 627        cmd.wlen = 6;
 628        cmd.rlen = 4;
 629        ret = si2157_cmd_execute(client, &cmd);
 630        if (ret)
 631                goto err;
 632
 633        /* set analog IF output config */
 634        memcpy(cmd.args, "\x14\x00\x0d\x06\x94\x64", 6);
 635        cmd.wlen = 6;
 636        cmd.rlen = 4;
 637        ret = si2157_cmd_execute(client, &cmd);
 638        if (ret)
 639                goto err;
 640
 641        /* make this distinct from a digital IF */
 642        dev->if_frequency = if_frequency | 1;
 643
 644        /* calc and set tuner analog if center frequency */
 645        if_frequency = if_frequency + 1250000 - (bandwidth / 2);
 646        dev_dbg(&client->dev, "IF Ctr freq=%d\n", if_frequency);
 647
 648        memcpy(cmd.args, "\x14\x00\x0C\x06", 4);
 649        cmd.args[4] = (if_frequency / 1000) & 0xff;
 650        cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
 651        cmd.wlen = 6;
 652        cmd.rlen = 4;
 653        ret = si2157_cmd_execute(client, &cmd);
 654        if (ret)
 655                goto err;
 656
 657        /* set analog AGC config */
 658        memcpy(cmd.args, "\x14\x00\x07\x06\x32\xc8", 6);
 659        cmd.wlen = 6;
 660        cmd.rlen = 4;
 661        ret = si2157_cmd_execute(client, &cmd);
 662        if (ret)
 663                goto err;
 664
 665        /* set analog video mode */
 666        memcpy(cmd.args, "\x14\x00\x04\x06\x00\x00", 6);
 667        cmd.args[4] = system | color;
 668        /* can use dev->inversion if assumed applies to both digital/analog */
 669        if (invert_analog)
 670                cmd.args[5] |= 0x02;
 671        cmd.wlen = 6;
 672        cmd.rlen = 1;
 673        ret = si2157_cmd_execute(client, &cmd);
 674        if (ret)
 675                goto err;
 676
 677        /* set analog frequency */
 678        memcpy(cmd.args, "\x41\x01\x00\x00\x00\x00\x00\x00", 8);
 679        cmd.args[4] = (freq >>  0) & 0xff;
 680        cmd.args[5] = (freq >>  8) & 0xff;
 681        cmd.args[6] = (freq >> 16) & 0xff;
 682        cmd.args[7] = (freq >> 24) & 0xff;
 683        cmd.wlen = 8;
 684        cmd.rlen = 1;
 685        ret = si2157_cmd_execute(client, &cmd);
 686        if (ret)
 687                goto err;
 688
 689        dev->bandwidth = bandwidth;
 690
 691        si2157_tune_wait(client, 0); /* wait to complete, ignore any errors */
 692
 693        return 0;
 694err:
 695        dev->bandwidth = 0;
 696        dev->frequency = 0;
 697        dev->if_frequency = 0;
 698        dev_dbg(&client->dev, "failed=%d\n", ret);
 699        return ret;
 700}
 701
 702static int si2157_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 703{
 704        struct i2c_client *client = fe->tuner_priv;
 705        struct si2157_dev *dev = i2c_get_clientdata(client);
 706
 707        *frequency = dev->frequency;
 708        dev_dbg(&client->dev, "freq=%u\n", dev->frequency);
 709        return 0;
 710}
 711
 712static int si2157_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 713{
 714        struct i2c_client *client = fe->tuner_priv;
 715        struct si2157_dev *dev = i2c_get_clientdata(client);
 716
 717        *bandwidth = dev->bandwidth;
 718        dev_dbg(&client->dev, "bandwidth=%u\n", dev->bandwidth);
 719        return 0;
 720}
 721
 722static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 723{
 724        struct i2c_client *client = fe->tuner_priv;
 725        struct si2157_dev *dev = i2c_get_clientdata(client);
 726
 727        *frequency = dev->if_frequency & ~1; /* strip analog IF indicator bit */
 728        dev_dbg(&client->dev, "if_frequency=%u\n", *frequency);
 729        return 0;
 730}
 731
 732static int si2157_get_rf_strength(struct dvb_frontend *fe, u16 *rssi)
 733{
 734        struct i2c_client *client = fe->tuner_priv;
 735        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 736        struct si2157_cmd cmd;
 737        int ret;
 738        int strength;
 739
 740        dev_dbg(&client->dev, "\n");
 741
 742        memcpy(cmd.args, "\x42\x00", 2);
 743        cmd.wlen = 2;
 744        cmd.rlen = 12;
 745        ret = si2157_cmd_execute(client, &cmd);
 746        if (ret)
 747                goto err;
 748
 749        c->strength.stat[0].scale = FE_SCALE_DECIBEL;
 750        c->strength.stat[0].svalue = (s8)cmd.args[3] * 1000;
 751
 752        /* normalize values based on Silicon Labs reference
 753         * add 100, then anything > 80 is 100% signal
 754         */
 755        strength = (s8)cmd.args[3] + 100;
 756        strength = clamp_val(strength, 0, 80);
 757        *rssi = (u16)(strength * 0xffff / 80);
 758
 759        dev_dbg(&client->dev, "strength=%d rssi=%u\n",
 760                (s8)cmd.args[3], *rssi);
 761
 762        return 0;
 763err:
 764        dev_dbg(&client->dev, "failed=%d\n", ret);
 765        return ret;
 766}
 767
 768static const struct dvb_tuner_ops si2157_ops = {
 769        .info = {
 770                .name             = "Silicon Labs Si2141/Si2146/2147/2148/2157/2158",
 771                .frequency_min_hz =  42 * MHz,
 772                .frequency_max_hz = 870 * MHz,
 773        },
 774
 775        .init = si2157_init,
 776        .sleep = si2157_sleep,
 777        .set_params = si2157_set_params,
 778        .set_analog_params = si2157_set_analog_params,
 779        .get_frequency     = si2157_get_frequency,
 780        .get_bandwidth     = si2157_get_bandwidth,
 781        .get_if_frequency  = si2157_get_if_frequency,
 782
 783        .get_rf_strength   = si2157_get_rf_strength,
 784};
 785
 786static void si2157_stat_work(struct work_struct *work)
 787{
 788        struct si2157_dev *dev = container_of(work, struct si2157_dev, stat_work.work);
 789        struct dvb_frontend *fe = dev->fe;
 790        struct i2c_client *client = fe->tuner_priv;
 791        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 792        struct si2157_cmd cmd;
 793        int ret;
 794
 795        dev_dbg(&client->dev, "\n");
 796
 797        memcpy(cmd.args, "\x42\x00", 2);
 798        cmd.wlen = 2;
 799        cmd.rlen = 12;
 800        ret = si2157_cmd_execute(client, &cmd);
 801        if (ret)
 802                goto err;
 803
 804        c->strength.stat[0].scale = FE_SCALE_DECIBEL;
 805        c->strength.stat[0].svalue = (s8) cmd.args[3] * 1000;
 806
 807        schedule_delayed_work(&dev->stat_work, msecs_to_jiffies(2000));
 808        return;
 809err:
 810        c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 811        dev_dbg(&client->dev, "failed=%d\n", ret);
 812}
 813
 814static int si2157_probe(struct i2c_client *client,
 815                        const struct i2c_device_id *id)
 816{
 817        struct si2157_config *cfg = client->dev.platform_data;
 818        struct dvb_frontend *fe = cfg->fe;
 819        struct si2157_dev *dev;
 820        struct si2157_cmd cmd;
 821        int ret;
 822
 823        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 824        if (!dev) {
 825                ret = -ENOMEM;
 826                dev_err(&client->dev, "kzalloc() failed\n");
 827                goto err;
 828        }
 829
 830        i2c_set_clientdata(client, dev);
 831        dev->fe = cfg->fe;
 832        dev->inversion = cfg->inversion;
 833        dev->dont_load_firmware = cfg->dont_load_firmware;
 834        dev->if_port = cfg->if_port;
 835        dev->chiptype = (u8)id->driver_data;
 836        dev->if_frequency = 5000000; /* default value of property 0x0706 */
 837        mutex_init(&dev->i2c_mutex);
 838        INIT_DELAYED_WORK(&dev->stat_work, si2157_stat_work);
 839
 840        /* check if the tuner is there */
 841        cmd.wlen = 0;
 842        cmd.rlen = 1;
 843        ret = si2157_cmd_execute(client, &cmd);
 844        if (ret && ret != -EAGAIN)
 845                goto err_kfree;
 846
 847        memcpy(&fe->ops.tuner_ops, &si2157_ops, sizeof(struct dvb_tuner_ops));
 848        fe->tuner_priv = client;
 849
 850#ifdef CONFIG_MEDIA_CONTROLLER
 851        if (cfg->mdev) {
 852                dev->mdev = cfg->mdev;
 853
 854                dev->ent.name = KBUILD_MODNAME;
 855                dev->ent.function = MEDIA_ENT_F_TUNER;
 856
 857                dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK;
 858                dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
 859                dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
 860                dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG;
 861                dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE;
 862                dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO;
 863
 864                ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS,
 865                                             &dev->pad[0]);
 866
 867                if (ret)
 868                        goto err_kfree;
 869
 870                ret = media_device_register_entity(cfg->mdev, &dev->ent);
 871                if (ret) {
 872                        media_entity_cleanup(&dev->ent);
 873                        goto err_kfree;
 874                }
 875        }
 876#endif
 877
 878        dev_info(&client->dev, "Silicon Labs %s successfully attached\n",
 879                        dev->chiptype == SI2157_CHIPTYPE_SI2141 ?  "Si2141" :
 880                        dev->chiptype == SI2157_CHIPTYPE_SI2146 ?
 881                        "Si2146" : "Si2147/2148/2157/2158");
 882
 883        return 0;
 884
 885err_kfree:
 886        kfree(dev);
 887err:
 888        dev_dbg(&client->dev, "failed=%d\n", ret);
 889        return ret;
 890}
 891
 892static int si2157_remove(struct i2c_client *client)
 893{
 894        struct si2157_dev *dev = i2c_get_clientdata(client);
 895        struct dvb_frontend *fe = dev->fe;
 896
 897        dev_dbg(&client->dev, "\n");
 898
 899        /* stop statistics polling */
 900        cancel_delayed_work_sync(&dev->stat_work);
 901
 902#ifdef CONFIG_MEDIA_CONTROLLER_DVB
 903        if (dev->mdev)
 904                media_device_unregister_entity(&dev->ent);
 905#endif
 906
 907        memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
 908        fe->tuner_priv = NULL;
 909        kfree(dev);
 910
 911        return 0;
 912}
 913
 914static const struct i2c_device_id si2157_id_table[] = {
 915        {"si2157", SI2157_CHIPTYPE_SI2157},
 916        {"si2146", SI2157_CHIPTYPE_SI2146},
 917        {"si2141", SI2157_CHIPTYPE_SI2141},
 918        {"si2177", SI2157_CHIPTYPE_SI2177},
 919        {}
 920};
 921MODULE_DEVICE_TABLE(i2c, si2157_id_table);
 922
 923static struct i2c_driver si2157_driver = {
 924        .driver = {
 925                .name                = "si2157",
 926                .suppress_bind_attrs = true,
 927        },
 928        .probe          = si2157_probe,
 929        .remove         = si2157_remove,
 930        .id_table       = si2157_id_table,
 931};
 932
 933module_i2c_driver(si2157_driver);
 934
 935MODULE_DESCRIPTION("Silicon Labs Si2141/Si2146/2147/2148/2157/2158 silicon tuner driver");
 936MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 937MODULE_LICENSE("GPL");
 938MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
 939MODULE_FIRMWARE(SI2141_A10_FIRMWARE);
 940MODULE_FIRMWARE(SI2157_A30_FIRMWARE);
 941