linux/drivers/media/dvb-frontends/si2168.c
<<
>>
Prefs
   1/*
   2 * Silicon Labs Si2168 DVB-T/T2/C demodulator driver
   3 *
   4 * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
   5 *
   6 *    This program is free software; you can redistribute it and/or modify
   7 *    it under the terms of the GNU General Public License as published by
   8 *    the Free Software Foundation; either version 2 of the License, or
   9 *    (at your option) any later version.
  10 *
  11 *    This program is distributed in the hope that it will be useful,
  12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *    GNU General Public License for more details.
  15 */
  16
  17#include "si2168_priv.h"
  18
  19static const struct dvb_frontend_ops si2168_ops;
  20
  21/* Own I2C adapter locking is needed because of I2C gate logic. */
  22static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
  23                                           const char *buf, int count)
  24{
  25        int ret;
  26        struct i2c_msg msg = {
  27                .addr = client->addr,
  28                .flags = 0,
  29                .len = count,
  30                .buf = (char *)buf,
  31        };
  32
  33        ret = __i2c_transfer(client->adapter, &msg, 1);
  34        return (ret == 1) ? count : ret;
  35}
  36
  37static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
  38                                           char *buf, int count)
  39{
  40        int ret;
  41        struct i2c_msg msg = {
  42                .addr = client->addr,
  43                .flags = I2C_M_RD,
  44                .len = count,
  45                .buf = buf,
  46        };
  47
  48        ret = __i2c_transfer(client->adapter, &msg, 1);
  49        return (ret == 1) ? count : ret;
  50}
  51
  52/* execute firmware command */
  53static int si2168_cmd_execute_unlocked(struct i2c_client *client,
  54                                       struct si2168_cmd *cmd)
  55{
  56        int ret;
  57        unsigned long timeout;
  58
  59        if (cmd->wlen) {
  60                /* write cmd and args for firmware */
  61                ret = si2168_i2c_master_send_unlocked(client, cmd->args,
  62                                                      cmd->wlen);
  63                if (ret < 0) {
  64                        goto err;
  65                } else if (ret != cmd->wlen) {
  66                        ret = -EREMOTEIO;
  67                        goto err;
  68                }
  69        }
  70
  71        if (cmd->rlen) {
  72                /* wait cmd execution terminate */
  73                #define TIMEOUT 70
  74                timeout = jiffies + msecs_to_jiffies(TIMEOUT);
  75                while (!time_after(jiffies, timeout)) {
  76                        ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
  77                                                              cmd->rlen);
  78                        if (ret < 0) {
  79                                goto err;
  80                        } else if (ret != cmd->rlen) {
  81                                ret = -EREMOTEIO;
  82                                goto err;
  83                        }
  84
  85                        /* firmware ready? */
  86                        if ((cmd->args[0] >> 7) & 0x01)
  87                                break;
  88                }
  89
  90                dev_dbg(&client->dev, "cmd execution took %d ms\n",
  91                                jiffies_to_msecs(jiffies) -
  92                                (jiffies_to_msecs(timeout) - TIMEOUT));
  93
  94                /* error bit set? */
  95                if ((cmd->args[0] >> 6) & 0x01) {
  96                        ret = -EREMOTEIO;
  97                        goto err;
  98                }
  99
 100                if (!((cmd->args[0] >> 7) & 0x01)) {
 101                        ret = -ETIMEDOUT;
 102                        goto err;
 103                }
 104        }
 105
 106        return 0;
 107err:
 108        dev_dbg(&client->dev, "failed=%d\n", ret);
 109        return ret;
 110}
 111
 112static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
 113{
 114        int ret;
 115
 116        i2c_lock_adapter(client->adapter);
 117        ret = si2168_cmd_execute_unlocked(client, cmd);
 118        i2c_unlock_adapter(client->adapter);
 119
 120        return ret;
 121}
 122
 123static int si2168_read_status(struct dvb_frontend *fe, enum fe_status *status)
 124{
 125        struct i2c_client *client = fe->demodulator_priv;
 126        struct si2168_dev *dev = i2c_get_clientdata(client);
 127        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 128        int ret;
 129        struct si2168_cmd cmd;
 130
 131        *status = 0;
 132
 133        if (!dev->active) {
 134                ret = -EAGAIN;
 135                goto err;
 136        }
 137
 138        switch (c->delivery_system) {
 139        case SYS_DVBT:
 140                memcpy(cmd.args, "\xa0\x01", 2);
 141                cmd.wlen = 2;
 142                cmd.rlen = 13;
 143                break;
 144        case SYS_DVBC_ANNEX_A:
 145                memcpy(cmd.args, "\x90\x01", 2);
 146                cmd.wlen = 2;
 147                cmd.rlen = 9;
 148                break;
 149        case SYS_DVBT2:
 150                memcpy(cmd.args, "\x50\x01", 2);
 151                cmd.wlen = 2;
 152                cmd.rlen = 14;
 153                break;
 154        default:
 155                ret = -EINVAL;
 156                goto err;
 157        }
 158
 159        ret = si2168_cmd_execute(client, &cmd);
 160        if (ret)
 161                goto err;
 162
 163        switch ((cmd.args[2] >> 1) & 0x03) {
 164        case 0x01:
 165                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
 166                break;
 167        case 0x03:
 168                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
 169                                FE_HAS_SYNC | FE_HAS_LOCK;
 170                break;
 171        }
 172
 173        dev->fe_status = *status;
 174
 175        if (*status & FE_HAS_LOCK) {
 176                c->cnr.len = 1;
 177                c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
 178                c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;
 179        } else {
 180                c->cnr.len = 1;
 181                c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
 182        }
 183
 184        dev_dbg(&client->dev, "status=%02x args=%*ph\n",
 185                        *status, cmd.rlen, cmd.args);
 186
 187        return 0;
 188err:
 189        dev_dbg(&client->dev, "failed=%d\n", ret);
 190        return ret;
 191}
 192
 193static int si2168_set_frontend(struct dvb_frontend *fe)
 194{
 195        struct i2c_client *client = fe->demodulator_priv;
 196        struct si2168_dev *dev = i2c_get_clientdata(client);
 197        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 198        int ret;
 199        struct si2168_cmd cmd;
 200        u8 bandwidth, delivery_system;
 201
 202        dev_dbg(&client->dev,
 203                        "delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%u\n",
 204                        c->delivery_system, c->modulation, c->frequency,
 205                        c->bandwidth_hz, c->symbol_rate, c->inversion,
 206                        c->stream_id);
 207
 208        if (!dev->active) {
 209                ret = -EAGAIN;
 210                goto err;
 211        }
 212
 213        switch (c->delivery_system) {
 214        case SYS_DVBT:
 215                delivery_system = 0x20;
 216                break;
 217        case SYS_DVBC_ANNEX_A:
 218                delivery_system = 0x30;
 219                break;
 220        case SYS_DVBT2:
 221                delivery_system = 0x70;
 222                break;
 223        default:
 224                ret = -EINVAL;
 225                goto err;
 226        }
 227
 228        if (c->bandwidth_hz == 0) {
 229                ret = -EINVAL;
 230                goto err;
 231        } else if (c->bandwidth_hz <= 2000000)
 232                bandwidth = 0x02;
 233        else if (c->bandwidth_hz <= 5000000)
 234                bandwidth = 0x05;
 235        else if (c->bandwidth_hz <= 6000000)
 236                bandwidth = 0x06;
 237        else if (c->bandwidth_hz <= 7000000)
 238                bandwidth = 0x07;
 239        else if (c->bandwidth_hz <= 8000000)
 240                bandwidth = 0x08;
 241        else if (c->bandwidth_hz <= 9000000)
 242                bandwidth = 0x09;
 243        else if (c->bandwidth_hz <= 10000000)
 244                bandwidth = 0x0a;
 245        else
 246                bandwidth = 0x0f;
 247
 248        /* program tuner */
 249        if (fe->ops.tuner_ops.set_params) {
 250                ret = fe->ops.tuner_ops.set_params(fe);
 251                if (ret)
 252                        goto err;
 253        }
 254
 255        memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
 256        cmd.wlen = 5;
 257        cmd.rlen = 5;
 258        ret = si2168_cmd_execute(client, &cmd);
 259        if (ret)
 260                goto err;
 261
 262        /* that has no big effect */
 263        if (c->delivery_system == SYS_DVBT)
 264                memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6);
 265        else if (c->delivery_system == SYS_DVBC_ANNEX_A)
 266                memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6);
 267        else if (c->delivery_system == SYS_DVBT2)
 268                memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
 269        cmd.wlen = 6;
 270        cmd.rlen = 3;
 271        ret = si2168_cmd_execute(client, &cmd);
 272        if (ret)
 273                goto err;
 274
 275        if (c->delivery_system == SYS_DVBT2) {
 276                /* select PLP */
 277                cmd.args[0] = 0x52;
 278                cmd.args[1] = c->stream_id & 0xff;
 279                cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
 280                cmd.wlen = 3;
 281                cmd.rlen = 1;
 282                ret = si2168_cmd_execute(client, &cmd);
 283                if (ret)
 284                        goto err;
 285        }
 286
 287        memcpy(cmd.args, "\x51\x03", 2);
 288        cmd.wlen = 2;
 289        cmd.rlen = 12;
 290        ret = si2168_cmd_execute(client, &cmd);
 291        if (ret)
 292                goto err;
 293
 294        memcpy(cmd.args, "\x12\x08\x04", 3);
 295        cmd.wlen = 3;
 296        cmd.rlen = 3;
 297        ret = si2168_cmd_execute(client, &cmd);
 298        if (ret)
 299                goto err;
 300
 301        memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
 302        cmd.wlen = 6;
 303        cmd.rlen = 4;
 304        ret = si2168_cmd_execute(client, &cmd);
 305        if (ret)
 306                goto err;
 307
 308        memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
 309        cmd.wlen = 6;
 310        cmd.rlen = 4;
 311        ret = si2168_cmd_execute(client, &cmd);
 312        if (ret)
 313                goto err;
 314
 315        memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
 316        cmd.wlen = 6;
 317        cmd.rlen = 4;
 318        ret = si2168_cmd_execute(client, &cmd);
 319        if (ret)
 320                goto err;
 321
 322        memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
 323        cmd.args[4] = delivery_system | bandwidth;
 324        cmd.wlen = 6;
 325        cmd.rlen = 4;
 326        ret = si2168_cmd_execute(client, &cmd);
 327        if (ret)
 328                goto err;
 329
 330        /* set DVB-C symbol rate */
 331        if (c->delivery_system == SYS_DVBC_ANNEX_A) {
 332                memcpy(cmd.args, "\x14\x00\x02\x11", 4);
 333                cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff;
 334                cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
 335                cmd.wlen = 6;
 336                cmd.rlen = 4;
 337                ret = si2168_cmd_execute(client, &cmd);
 338                if (ret)
 339                        goto err;
 340        }
 341
 342        memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
 343        cmd.wlen = 6;
 344        cmd.rlen = 4;
 345        ret = si2168_cmd_execute(client, &cmd);
 346        if (ret)
 347                goto err;
 348
 349        memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6);
 350        cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;
 351        cmd.wlen = 6;
 352        cmd.rlen = 4;
 353        ret = si2168_cmd_execute(client, &cmd);
 354        if (ret)
 355                goto err;
 356
 357        memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6);
 358        cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;
 359        cmd.wlen = 6;
 360        cmd.rlen = 4;
 361        ret = si2168_cmd_execute(client, &cmd);
 362        if (ret)
 363                goto err;
 364
 365        memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
 366        cmd.wlen = 6;
 367        cmd.rlen = 4;
 368        ret = si2168_cmd_execute(client, &cmd);
 369        if (ret)
 370                goto err;
 371
 372        memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
 373        cmd.wlen = 6;
 374        cmd.rlen = 4;
 375        ret = si2168_cmd_execute(client, &cmd);
 376        if (ret)
 377                goto err;
 378
 379        memcpy(cmd.args, "\x85", 1);
 380        cmd.wlen = 1;
 381        cmd.rlen = 1;
 382        ret = si2168_cmd_execute(client, &cmd);
 383        if (ret)
 384                goto err;
 385
 386        dev->delivery_system = c->delivery_system;
 387
 388        return 0;
 389err:
 390        dev_dbg(&client->dev, "failed=%d\n", ret);
 391        return ret;
 392}
 393
 394static int si2168_init(struct dvb_frontend *fe)
 395{
 396        struct i2c_client *client = fe->demodulator_priv;
 397        struct si2168_dev *dev = i2c_get_clientdata(client);
 398        int ret, len, remaining;
 399        const struct firmware *fw;
 400        const char *fw_name;
 401        struct si2168_cmd cmd;
 402        unsigned int chip_id;
 403
 404        dev_dbg(&client->dev, "\n");
 405
 406        /* initialize */
 407        memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
 408        cmd.wlen = 13;
 409        cmd.rlen = 0;
 410        ret = si2168_cmd_execute(client, &cmd);
 411        if (ret)
 412                goto err;
 413
 414        if (dev->fw_loaded) {
 415                /* resume */
 416                memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
 417                cmd.wlen = 8;
 418                cmd.rlen = 1;
 419                ret = si2168_cmd_execute(client, &cmd);
 420                if (ret)
 421                        goto err;
 422
 423                memcpy(cmd.args, "\x85", 1);
 424                cmd.wlen = 1;
 425                cmd.rlen = 1;
 426                ret = si2168_cmd_execute(client, &cmd);
 427                if (ret)
 428                        goto err;
 429
 430                goto warm;
 431        }
 432
 433        /* power up */
 434        memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
 435        cmd.wlen = 8;
 436        cmd.rlen = 1;
 437        ret = si2168_cmd_execute(client, &cmd);
 438        if (ret)
 439                goto err;
 440
 441        /* query chip revision */
 442        memcpy(cmd.args, "\x02", 1);
 443        cmd.wlen = 1;
 444        cmd.rlen = 13;
 445        ret = si2168_cmd_execute(client, &cmd);
 446        if (ret)
 447                goto err;
 448
 449        chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
 450                        cmd.args[4] << 0;
 451
 452        #define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
 453        #define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
 454        #define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
 455
 456        switch (chip_id) {
 457        case SI2168_A20:
 458                fw_name = SI2168_A20_FIRMWARE;
 459                break;
 460        case SI2168_A30:
 461                fw_name = SI2168_A30_FIRMWARE;
 462                break;
 463        case SI2168_B40:
 464                fw_name = SI2168_B40_FIRMWARE;
 465                break;
 466        default:
 467                dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
 468                                cmd.args[2], cmd.args[1],
 469                                cmd.args[3], cmd.args[4]);
 470                ret = -EINVAL;
 471                goto err;
 472        }
 473
 474        dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
 475                        cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
 476
 477        /* request the firmware, this will block and timeout */
 478        ret = request_firmware(&fw, fw_name, &client->dev);
 479        if (ret) {
 480                /* fallback mechanism to handle old name for Si2168 B40 fw */
 481                if (chip_id == SI2168_B40) {
 482                        fw_name = SI2168_B40_FIRMWARE_FALLBACK;
 483                        ret = request_firmware(&fw, fw_name, &client->dev);
 484                }
 485
 486                if (ret == 0) {
 487                        dev_notice(&client->dev,
 488                                        "please install firmware file '%s'\n",
 489                                        SI2168_B40_FIRMWARE);
 490                } else {
 491                        dev_err(&client->dev,
 492                                        "firmware file '%s' not found\n",
 493                                        fw_name);
 494                        goto err_release_firmware;
 495                }
 496        }
 497
 498        dev_info(&client->dev, "downloading firmware from file '%s'\n",
 499                        fw_name);
 500
 501        if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
 502                /* firmware is in the new format */
 503                for (remaining = fw->size; remaining > 0; remaining -= 17) {
 504                        len = fw->data[fw->size - remaining];
 505                        if (len > SI2168_ARGLEN) {
 506                                ret = -EINVAL;
 507                                break;
 508                        }
 509                        memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
 510                        cmd.wlen = len;
 511                        cmd.rlen = 1;
 512                        ret = si2168_cmd_execute(client, &cmd);
 513                        if (ret)
 514                                break;
 515                }
 516        } else if (fw->size % 8 == 0) {
 517                /* firmware is in the old format */
 518                for (remaining = fw->size; remaining > 0; remaining -= 8) {
 519                        len = 8;
 520                        memcpy(cmd.args, &fw->data[fw->size - remaining], len);
 521                        cmd.wlen = len;
 522                        cmd.rlen = 1;
 523                        ret = si2168_cmd_execute(client, &cmd);
 524                        if (ret)
 525                                break;
 526                }
 527        } else {
 528                /* bad or unknown firmware format */
 529                ret = -EINVAL;
 530        }
 531
 532        if (ret) {
 533                dev_err(&client->dev, "firmware download failed %d\n", ret);
 534                goto err_release_firmware;
 535        }
 536
 537        release_firmware(fw);
 538
 539        memcpy(cmd.args, "\x01\x01", 2);
 540        cmd.wlen = 2;
 541        cmd.rlen = 1;
 542        ret = si2168_cmd_execute(client, &cmd);
 543        if (ret)
 544                goto err;
 545
 546        /* query firmware version */
 547        memcpy(cmd.args, "\x11", 1);
 548        cmd.wlen = 1;
 549        cmd.rlen = 10;
 550        ret = si2168_cmd_execute(client, &cmd);
 551        if (ret)
 552                goto err;
 553
 554        dev_info(&client->dev, "firmware version: %c.%c.%d\n",
 555                        cmd.args[6], cmd.args[7], cmd.args[8]);
 556
 557        /* set ts mode */
 558        memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
 559        cmd.args[4] |= dev->ts_mode;
 560        if (dev->ts_clock_gapped)
 561                cmd.args[4] |= 0x40;
 562        cmd.wlen = 6;
 563        cmd.rlen = 4;
 564        ret = si2168_cmd_execute(client, &cmd);
 565        if (ret)
 566                goto err;
 567
 568        dev->fw_loaded = true;
 569warm:
 570        dev->active = true;
 571
 572        return 0;
 573
 574err_release_firmware:
 575        release_firmware(fw);
 576err:
 577        dev_dbg(&client->dev, "failed=%d\n", ret);
 578        return ret;
 579}
 580
 581static int si2168_sleep(struct dvb_frontend *fe)
 582{
 583        struct i2c_client *client = fe->demodulator_priv;
 584        struct si2168_dev *dev = i2c_get_clientdata(client);
 585        int ret;
 586        struct si2168_cmd cmd;
 587
 588        dev_dbg(&client->dev, "\n");
 589
 590        dev->active = false;
 591
 592        memcpy(cmd.args, "\x13", 1);
 593        cmd.wlen = 1;
 594        cmd.rlen = 0;
 595        ret = si2168_cmd_execute(client, &cmd);
 596        if (ret)
 597                goto err;
 598
 599        return 0;
 600err:
 601        dev_dbg(&client->dev, "failed=%d\n", ret);
 602        return ret;
 603}
 604
 605static int si2168_get_tune_settings(struct dvb_frontend *fe,
 606        struct dvb_frontend_tune_settings *s)
 607{
 608        s->min_delay_ms = 900;
 609
 610        return 0;
 611}
 612
 613/*
 614 * I2C gate logic
 615 * We must use unlocked I2C I/O because I2C adapter lock is already taken
 616 * by the caller (usually tuner driver).
 617 */
 618static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
 619{
 620        struct i2c_client *client = mux_priv;
 621        int ret;
 622        struct si2168_cmd cmd;
 623
 624        /* open I2C gate */
 625        memcpy(cmd.args, "\xc0\x0d\x01", 3);
 626        cmd.wlen = 3;
 627        cmd.rlen = 0;
 628        ret = si2168_cmd_execute_unlocked(client, &cmd);
 629        if (ret)
 630                goto err;
 631
 632        return 0;
 633err:
 634        dev_dbg(&client->dev, "failed=%d\n", ret);
 635        return ret;
 636}
 637
 638static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
 639{
 640        struct i2c_client *client = mux_priv;
 641        int ret;
 642        struct si2168_cmd cmd;
 643
 644        /* close I2C gate */
 645        memcpy(cmd.args, "\xc0\x0d\x00", 3);
 646        cmd.wlen = 3;
 647        cmd.rlen = 0;
 648        ret = si2168_cmd_execute_unlocked(client, &cmd);
 649        if (ret)
 650                goto err;
 651
 652        return 0;
 653err:
 654        dev_dbg(&client->dev, "failed=%d\n", ret);
 655        return ret;
 656}
 657
 658static const struct dvb_frontend_ops si2168_ops = {
 659        .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
 660        .info = {
 661                .name = "Silicon Labs Si2168",
 662                .symbol_rate_min = 1000000,
 663                .symbol_rate_max = 7200000,
 664                .caps = FE_CAN_FEC_1_2 |
 665                        FE_CAN_FEC_2_3 |
 666                        FE_CAN_FEC_3_4 |
 667                        FE_CAN_FEC_5_6 |
 668                        FE_CAN_FEC_7_8 |
 669                        FE_CAN_FEC_AUTO |
 670                        FE_CAN_QPSK |
 671                        FE_CAN_QAM_16 |
 672                        FE_CAN_QAM_32 |
 673                        FE_CAN_QAM_64 |
 674                        FE_CAN_QAM_128 |
 675                        FE_CAN_QAM_256 |
 676                        FE_CAN_QAM_AUTO |
 677                        FE_CAN_TRANSMISSION_MODE_AUTO |
 678                        FE_CAN_GUARD_INTERVAL_AUTO |
 679                        FE_CAN_HIERARCHY_AUTO |
 680                        FE_CAN_MUTE_TS |
 681                        FE_CAN_2G_MODULATION |
 682                        FE_CAN_MULTISTREAM
 683        },
 684
 685        .get_tune_settings = si2168_get_tune_settings,
 686
 687        .init = si2168_init,
 688        .sleep = si2168_sleep,
 689
 690        .set_frontend = si2168_set_frontend,
 691
 692        .read_status = si2168_read_status,
 693};
 694
 695static int si2168_probe(struct i2c_client *client,
 696                const struct i2c_device_id *id)
 697{
 698        struct si2168_config *config = client->dev.platform_data;
 699        struct si2168_dev *dev;
 700        int ret;
 701
 702        dev_dbg(&client->dev, "\n");
 703
 704        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 705        if (!dev) {
 706                ret = -ENOMEM;
 707                dev_err(&client->dev, "kzalloc() failed\n");
 708                goto err;
 709        }
 710
 711        /* create mux i2c adapter for tuner */
 712        dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
 713                        client, 0, 0, 0, si2168_select, si2168_deselect);
 714        if (dev->adapter == NULL) {
 715                ret = -ENODEV;
 716                goto err_kfree;
 717        }
 718
 719        /* create dvb_frontend */
 720        memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
 721        dev->fe.demodulator_priv = client;
 722        *config->i2c_adapter = dev->adapter;
 723        *config->fe = &dev->fe;
 724        dev->ts_mode = config->ts_mode;
 725        dev->ts_clock_inv = config->ts_clock_inv;
 726        dev->ts_clock_gapped = config->ts_clock_gapped;
 727        dev->fw_loaded = false;
 728
 729        i2c_set_clientdata(client, dev);
 730
 731        dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n");
 732        return 0;
 733err_kfree:
 734        kfree(dev);
 735err:
 736        dev_dbg(&client->dev, "failed=%d\n", ret);
 737        return ret;
 738}
 739
 740static int si2168_remove(struct i2c_client *client)
 741{
 742        struct si2168_dev *dev = i2c_get_clientdata(client);
 743
 744        dev_dbg(&client->dev, "\n");
 745
 746        i2c_del_mux_adapter(dev->adapter);
 747
 748        dev->fe.ops.release = NULL;
 749        dev->fe.demodulator_priv = NULL;
 750
 751        kfree(dev);
 752
 753        return 0;
 754}
 755
 756static const struct i2c_device_id si2168_id_table[] = {
 757        {"si2168", 0},
 758        {}
 759};
 760MODULE_DEVICE_TABLE(i2c, si2168_id_table);
 761
 762static struct i2c_driver si2168_driver = {
 763        .driver = {
 764                .name   = "si2168",
 765        },
 766        .probe          = si2168_probe,
 767        .remove         = si2168_remove,
 768        .id_table       = si2168_id_table,
 769};
 770
 771module_i2c_driver(si2168_driver);
 772
 773MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 774MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");
 775MODULE_LICENSE("GPL");
 776MODULE_FIRMWARE(SI2168_A20_FIRMWARE);
 777MODULE_FIRMWARE(SI2168_A30_FIRMWARE);
 778MODULE_FIRMWARE(SI2168_B40_FIRMWARE);
 779