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