linux/drivers/mfd/si476x-i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * drivers/mfd/si476x-i2c.c -- Core device driver for si476x MFD
   4 * device
   5 *
   6 * Copyright (C) 2012 Innovative Converged Devices(ICD)
   7 * Copyright (C) 2013 Andrey Smirnov
   8 *
   9 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
  10 */
  11#include <linux/module.h>
  12
  13#include <linux/slab.h>
  14#include <linux/interrupt.h>
  15#include <linux/delay.h>
  16#include <linux/gpio.h>
  17#include <linux/regulator/consumer.h>
  18#include <linux/i2c.h>
  19#include <linux/err.h>
  20
  21#include <linux/mfd/si476x-core.h>
  22
  23#define SI476X_MAX_IO_ERRORS            10
  24#define SI476X_DRIVER_RDS_FIFO_DEPTH    128
  25
  26/**
  27 * si476x_core_config_pinmux() - pin function configuration function
  28 *
  29 * @core: Core device structure
  30 *
  31 * Configure the functions of the pins of the radio chip.
  32 *
  33 * The function returns zero in case of succes or negative error code
  34 * otherwise.
  35 */
  36static int si476x_core_config_pinmux(struct si476x_core *core)
  37{
  38        int err;
  39        dev_dbg(&core->client->dev, "Configuring pinmux\n");
  40        err = si476x_core_cmd_dig_audio_pin_cfg(core,
  41                                                core->pinmux.dclk,
  42                                                core->pinmux.dfs,
  43                                                core->pinmux.dout,
  44                                                core->pinmux.xout);
  45        if (err < 0) {
  46                dev_err(&core->client->dev,
  47                        "Failed to configure digital audio pins(err = %d)\n",
  48                        err);
  49                return err;
  50        }
  51
  52        err = si476x_core_cmd_zif_pin_cfg(core,
  53                                          core->pinmux.iqclk,
  54                                          core->pinmux.iqfs,
  55                                          core->pinmux.iout,
  56                                          core->pinmux.qout);
  57        if (err < 0) {
  58                dev_err(&core->client->dev,
  59                        "Failed to configure ZIF pins(err = %d)\n",
  60                        err);
  61                return err;
  62        }
  63
  64        err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core,
  65                                                      core->pinmux.icin,
  66                                                      core->pinmux.icip,
  67                                                      core->pinmux.icon,
  68                                                      core->pinmux.icop);
  69        if (err < 0) {
  70                dev_err(&core->client->dev,
  71                        "Failed to configure IC-Link/GPO pins(err = %d)\n",
  72                        err);
  73                return err;
  74        }
  75
  76        err = si476x_core_cmd_ana_audio_pin_cfg(core,
  77                                                core->pinmux.lrout);
  78        if (err < 0) {
  79                dev_err(&core->client->dev,
  80                        "Failed to configure analog audio pins(err = %d)\n",
  81                        err);
  82                return err;
  83        }
  84
  85        err = si476x_core_cmd_intb_pin_cfg(core,
  86                                           core->pinmux.intb,
  87                                           core->pinmux.a1);
  88        if (err < 0) {
  89                dev_err(&core->client->dev,
  90                        "Failed to configure interrupt pins(err = %d)\n",
  91                        err);
  92                return err;
  93        }
  94
  95        return 0;
  96}
  97
  98static inline void si476x_core_schedule_polling_work(struct si476x_core *core)
  99{
 100        schedule_delayed_work(&core->status_monitor,
 101                              usecs_to_jiffies(SI476X_STATUS_POLL_US));
 102}
 103
 104/**
 105 * si476x_core_start() - early chip startup function
 106 * @core: Core device structure
 107 * @soft: When set, this flag forces "soft" startup, where "soft"
 108 * power down is the one done by sending appropriate command instead
 109 * of using reset pin of the tuner
 110 *
 111 * Perform required startup sequence to correctly power
 112 * up the chip and perform initial configuration. It does the
 113 * following sequence of actions:
 114 *       1. Claims and enables the power supplies VD and VIO1 required
 115 *          for I2C interface of the chip operation.
 116 *       2. Waits for 100us, pulls the reset line up, enables irq,
 117 *          waits for another 100us as it is specified by the
 118 *          datasheet.
 119 *       3. Sends 'POWER_UP' command to the device with all provided
 120 *          information about power-up parameters.
 121 *       4. Configures, pin multiplexor, disables digital audio and
 122 *          configures interrupt sources.
 123 *
 124 * The function returns zero in case of succes or negative error code
 125 * otherwise.
 126 */
 127int si476x_core_start(struct si476x_core *core, bool soft)
 128{
 129        struct i2c_client *client = core->client;
 130        int err;
 131
 132        if (!soft) {
 133                if (gpio_is_valid(core->gpio_reset))
 134                        gpio_set_value_cansleep(core->gpio_reset, 1);
 135
 136                if (client->irq)
 137                        enable_irq(client->irq);
 138
 139                udelay(100);
 140
 141                if (!client->irq) {
 142                        atomic_set(&core->is_alive, 1);
 143                        si476x_core_schedule_polling_work(core);
 144                }
 145        } else {
 146                if (client->irq)
 147                        enable_irq(client->irq);
 148                else {
 149                        atomic_set(&core->is_alive, 1);
 150                        si476x_core_schedule_polling_work(core);
 151                }
 152        }
 153
 154        err = si476x_core_cmd_power_up(core,
 155                                       &core->power_up_parameters);
 156
 157        if (err < 0) {
 158                dev_err(&core->client->dev,
 159                        "Power up failure(err = %d)\n",
 160                        err);
 161                goto disable_irq;
 162        }
 163
 164        if (client->irq)
 165                atomic_set(&core->is_alive, 1);
 166
 167        err = si476x_core_config_pinmux(core);
 168        if (err < 0) {
 169                dev_err(&core->client->dev,
 170                        "Failed to configure pinmux(err = %d)\n",
 171                        err);
 172                goto disable_irq;
 173        }
 174
 175        if (client->irq) {
 176                err = regmap_write(core->regmap,
 177                                   SI476X_PROP_INT_CTL_ENABLE,
 178                                   SI476X_RDSIEN |
 179                                   SI476X_STCIEN |
 180                                   SI476X_CTSIEN);
 181                if (err < 0) {
 182                        dev_err(&core->client->dev,
 183                                "Failed to configure interrupt sources"
 184                                "(err = %d)\n", err);
 185                        goto disable_irq;
 186                }
 187        }
 188
 189        return 0;
 190
 191disable_irq:
 192        if (err == -ENODEV)
 193                atomic_set(&core->is_alive, 0);
 194
 195        if (client->irq)
 196                disable_irq(client->irq);
 197        else
 198                cancel_delayed_work_sync(&core->status_monitor);
 199
 200        if (gpio_is_valid(core->gpio_reset))
 201                gpio_set_value_cansleep(core->gpio_reset, 0);
 202
 203        return err;
 204}
 205EXPORT_SYMBOL_GPL(si476x_core_start);
 206
 207/**
 208 * si476x_core_stop() - chip power-down function
 209 * @core: Core device structure
 210 * @soft: When set, function sends a POWER_DOWN command instead of
 211 * bringing reset line low
 212 *
 213 * Power down the chip by performing following actions:
 214 * 1. Disable IRQ or stop the polling worker
 215 * 2. Send the POWER_DOWN command if the power down is soft or bring
 216 *    reset line low if not.
 217 *
 218 * The function returns zero in case of succes or negative error code
 219 * otherwise.
 220 */
 221int si476x_core_stop(struct si476x_core *core, bool soft)
 222{
 223        int err = 0;
 224        atomic_set(&core->is_alive, 0);
 225
 226        if (soft) {
 227                /* TODO: This probably shoud be a configurable option,
 228                 * so it is possible to have the chips keep their
 229                 * oscillators running
 230                 */
 231                struct si476x_power_down_args args = {
 232                        .xosc = false,
 233                };
 234                err = si476x_core_cmd_power_down(core, &args);
 235        }
 236
 237        /* We couldn't disable those before
 238         * 'si476x_core_cmd_power_down' since we expect to get CTS
 239         * interrupt */
 240        if (core->client->irq)
 241                disable_irq(core->client->irq);
 242        else
 243                cancel_delayed_work_sync(&core->status_monitor);
 244
 245        if (!soft) {
 246                if (gpio_is_valid(core->gpio_reset))
 247                        gpio_set_value_cansleep(core->gpio_reset, 0);
 248        }
 249        return err;
 250}
 251EXPORT_SYMBOL_GPL(si476x_core_stop);
 252
 253/**
 254 * si476x_core_set_power_state() - set the level at which the power is
 255 * supplied for the chip.
 256 * @core: Core device structure
 257 * @next_state: enum si476x_power_state describing power state to
 258 *              switch to.
 259 *
 260 * Switch on all the required power supplies
 261 *
 262 * This function returns 0 in case of suvccess and negative error code
 263 * otherwise.
 264 */
 265int si476x_core_set_power_state(struct si476x_core *core,
 266                                enum si476x_power_state next_state)
 267{
 268        /*
 269           It is not clear form the datasheet if it is possible to
 270           work with device if not all power domains are operational.
 271           So for now the power-up policy is "power-up all the things!"
 272         */
 273        int err = 0;
 274
 275        if (core->power_state == SI476X_POWER_INCONSISTENT) {
 276                dev_err(&core->client->dev,
 277                        "The device in inconsistent power state\n");
 278                return -EINVAL;
 279        }
 280
 281        if (next_state != core->power_state) {
 282                switch (next_state) {
 283                case SI476X_POWER_UP_FULL:
 284                        err = regulator_bulk_enable(ARRAY_SIZE(core->supplies),
 285                                                    core->supplies);
 286                        if (err < 0) {
 287                                core->power_state = SI476X_POWER_INCONSISTENT;
 288                                break;
 289                        }
 290                        /*
 291                         * Startup timing diagram recommends to have a
 292                         * 100 us delay between enabling of the power
 293                         * supplies and turning the tuner on.
 294                         */
 295                        udelay(100);
 296
 297                        err = si476x_core_start(core, false);
 298                        if (err < 0)
 299                                goto disable_regulators;
 300
 301                        core->power_state = next_state;
 302                        break;
 303
 304                case SI476X_POWER_DOWN:
 305                        core->power_state = next_state;
 306                        err = si476x_core_stop(core, false);
 307                        if (err < 0)
 308                                core->power_state = SI476X_POWER_INCONSISTENT;
 309disable_regulators:
 310                        err = regulator_bulk_disable(ARRAY_SIZE(core->supplies),
 311                                                     core->supplies);
 312                        if (err < 0)
 313                                core->power_state = SI476X_POWER_INCONSISTENT;
 314                        break;
 315                default:
 316                        BUG();
 317                }
 318        }
 319
 320        return err;
 321}
 322EXPORT_SYMBOL_GPL(si476x_core_set_power_state);
 323
 324/**
 325 * si476x_core_report_drainer_stop() - mark the completion of the RDS
 326 * buffer drain porcess by the worker.
 327 *
 328 * @core: Core device structure
 329 */
 330static inline void si476x_core_report_drainer_stop(struct si476x_core *core)
 331{
 332        mutex_lock(&core->rds_drainer_status_lock);
 333        core->rds_drainer_is_working = false;
 334        mutex_unlock(&core->rds_drainer_status_lock);
 335}
 336
 337/**
 338 * si476x_core_start_rds_drainer_once() - start RDS drainer worker if
 339 * ther is none working, do nothing otherwise
 340 *
 341 * @core: Datastructure corresponding to the chip.
 342 */
 343static inline void si476x_core_start_rds_drainer_once(struct si476x_core *core)
 344{
 345        mutex_lock(&core->rds_drainer_status_lock);
 346        if (!core->rds_drainer_is_working) {
 347                core->rds_drainer_is_working = true;
 348                schedule_work(&core->rds_fifo_drainer);
 349        }
 350        mutex_unlock(&core->rds_drainer_status_lock);
 351}
 352/**
 353 * si476x_core_drain_rds_fifo() - RDS buffer drainer.
 354 * @work: struct work_struct being ppassed to the function by the
 355 * kernel.
 356 *
 357 * Drain the contents of the RDS FIFO of
 358 */
 359static void si476x_core_drain_rds_fifo(struct work_struct *work)
 360{
 361        int err;
 362
 363        struct si476x_core *core = container_of(work, struct si476x_core,
 364                                                rds_fifo_drainer);
 365
 366        struct si476x_rds_status_report report;
 367
 368        si476x_core_lock(core);
 369        err = si476x_core_cmd_fm_rds_status(core, true, false, false, &report);
 370        if (!err) {
 371                int i = report.rdsfifoused;
 372                dev_dbg(&core->client->dev,
 373                        "%d elements in RDS FIFO. Draining.\n", i);
 374                for (; i > 0; --i) {
 375                        err = si476x_core_cmd_fm_rds_status(core, false, false,
 376                                                            (i == 1), &report);
 377                        if (err < 0)
 378                                goto unlock;
 379
 380                        kfifo_in(&core->rds_fifo, report.rds,
 381                                 sizeof(report.rds));
 382                        dev_dbg(&core->client->dev, "RDS data:\n %*ph\n",
 383                                (int)sizeof(report.rds), report.rds);
 384                }
 385                dev_dbg(&core->client->dev, "Drrrrained!\n");
 386                wake_up_interruptible(&core->rds_read_queue);
 387        }
 388
 389unlock:
 390        si476x_core_unlock(core);
 391        si476x_core_report_drainer_stop(core);
 392}
 393
 394/**
 395 * si476x_core_pronounce_dead()
 396 *
 397 * @core: Core device structure
 398 *
 399 * Mark the device as being dead and wake up all potentially waiting
 400 * threads of execution.
 401 *
 402 */
 403static void si476x_core_pronounce_dead(struct si476x_core *core)
 404{
 405        dev_info(&core->client->dev, "Core device is dead.\n");
 406
 407        atomic_set(&core->is_alive, 0);
 408
 409        /* Wake up al possible waiting processes */
 410        wake_up_interruptible(&core->rds_read_queue);
 411
 412        atomic_set(&core->cts, 1);
 413        wake_up(&core->command);
 414
 415        atomic_set(&core->stc, 1);
 416        wake_up(&core->tuning);
 417}
 418
 419/**
 420 * si476x_core_i2c_xfer()
 421 *
 422 * @core: Core device structure
 423 * @type: Transfer type
 424 * @buf: Transfer buffer for/with data
 425 * @count: Transfer buffer size
 426 *
 427 * Perfrom and I2C transfer(either read or write) and keep a counter
 428 * of I/O errors. If the error counter rises above the threshold
 429 * pronounce device dead.
 430 *
 431 * The function returns zero on succes or negative error code on
 432 * failure.
 433 */
 434int si476x_core_i2c_xfer(struct si476x_core *core,
 435                    enum si476x_i2c_type type,
 436                    char *buf, int count)
 437{
 438        static int io_errors_count;
 439        int err;
 440        if (type == SI476X_I2C_SEND)
 441                err = i2c_master_send(core->client, buf, count);
 442        else
 443                err = i2c_master_recv(core->client, buf, count);
 444
 445        if (err < 0) {
 446                if (io_errors_count++ > SI476X_MAX_IO_ERRORS)
 447                        si476x_core_pronounce_dead(core);
 448        } else {
 449                io_errors_count = 0;
 450        }
 451
 452        return err;
 453}
 454EXPORT_SYMBOL_GPL(si476x_core_i2c_xfer);
 455
 456/**
 457 * si476x_core_get_status()
 458 * @core: Core device structure
 459 *
 460 * Get the status byte of the core device by berforming one byte I2C
 461 * read.
 462 *
 463 * The function returns a status value or a negative error code on
 464 * error.
 465 */
 466static int si476x_core_get_status(struct si476x_core *core)
 467{
 468        u8 response;
 469        int err = si476x_core_i2c_xfer(core, SI476X_I2C_RECV,
 470                                  &response, sizeof(response));
 471
 472        return (err < 0) ? err : response;
 473}
 474
 475/**
 476 * si476x_core_get_and_signal_status() - IRQ dispatcher
 477 * @core: Core device structure
 478 *
 479 * Dispatch the arrived interrupt request based on the value of the
 480 * status byte reported by the tuner.
 481 *
 482 */
 483static void si476x_core_get_and_signal_status(struct si476x_core *core)
 484{
 485        int status = si476x_core_get_status(core);
 486        if (status < 0) {
 487                dev_err(&core->client->dev, "Failed to get status\n");
 488                return;
 489        }
 490
 491        if (status & SI476X_CTS) {
 492                /* Unfortunately completions could not be used for
 493                 * signalling CTS since this flag cannot be cleared
 494                 * in status byte, and therefore once it becomes true
 495                 * multiple calls to 'complete' would cause the
 496                 * commands following the current one to be completed
 497                 * before they actually are */
 498                dev_dbg(&core->client->dev, "[interrupt] CTSINT\n");
 499                atomic_set(&core->cts, 1);
 500                wake_up(&core->command);
 501        }
 502
 503        if (status & SI476X_FM_RDS_INT) {
 504                dev_dbg(&core->client->dev, "[interrupt] RDSINT\n");
 505                si476x_core_start_rds_drainer_once(core);
 506        }
 507
 508        if (status & SI476X_STC_INT) {
 509                dev_dbg(&core->client->dev, "[interrupt] STCINT\n");
 510                atomic_set(&core->stc, 1);
 511                wake_up(&core->tuning);
 512        }
 513}
 514
 515static void si476x_core_poll_loop(struct work_struct *work)
 516{
 517        struct si476x_core *core = SI476X_WORK_TO_CORE(work);
 518
 519        si476x_core_get_and_signal_status(core);
 520
 521        if (atomic_read(&core->is_alive))
 522                si476x_core_schedule_polling_work(core);
 523}
 524
 525static irqreturn_t si476x_core_interrupt(int irq, void *dev)
 526{
 527        struct si476x_core *core = dev;
 528
 529        si476x_core_get_and_signal_status(core);
 530
 531        return IRQ_HANDLED;
 532}
 533
 534/**
 535 * si476x_core_fwver_to_revision()
 536 * @core: Core device structure
 537 * @func: Selects the boot function of the device:
 538 *         *_BOOTLOADER  - Boot loader
 539 *         *_FM_RECEIVER - FM receiver
 540 *         *_AM_RECEIVER - AM receiver
 541 *         *_WB_RECEIVER - Weatherband receiver
 542 * @major:  Firmware major number
 543 * @minor1: Firmware first minor number
 544 * @minor2: Firmware second minor number
 545 *
 546 * Convert a chip's firmware version number into an offset that later
 547 * will be used to as offset in "vtable" of tuner functions
 548 *
 549 * This function returns a positive offset in case of success and a -1
 550 * in case of failure.
 551 */
 552static int si476x_core_fwver_to_revision(struct si476x_core *core,
 553                                         int func, int major,
 554                                         int minor1, int minor2)
 555{
 556        switch (func) {
 557        case SI476X_FUNC_FM_RECEIVER:
 558                switch (major) {
 559                case 5:
 560                        return SI476X_REVISION_A10;
 561                case 8:
 562                        return SI476X_REVISION_A20;
 563                case 10:
 564                        return SI476X_REVISION_A30;
 565                default:
 566                        goto unknown_revision;
 567                }
 568        case SI476X_FUNC_AM_RECEIVER:
 569                switch (major) {
 570                case 5:
 571                        return SI476X_REVISION_A10;
 572                case 7:
 573                        return SI476X_REVISION_A20;
 574                case 9:
 575                        return SI476X_REVISION_A30;
 576                default:
 577                        goto unknown_revision;
 578                }
 579        case SI476X_FUNC_WB_RECEIVER:
 580                switch (major) {
 581                case 3:
 582                        return SI476X_REVISION_A10;
 583                case 5:
 584                        return SI476X_REVISION_A20;
 585                case 7:
 586                        return SI476X_REVISION_A30;
 587                default:
 588                        goto unknown_revision;
 589                }
 590        case SI476X_FUNC_BOOTLOADER:
 591        default:                /* FALLTHROUGH */
 592                BUG();
 593                return -1;
 594        }
 595
 596unknown_revision:
 597        dev_err(&core->client->dev,
 598                "Unsupported version of the firmware: %d.%d.%d, "
 599                "reverting to A10 compatible functions\n",
 600                major, minor1, minor2);
 601
 602        return SI476X_REVISION_A10;
 603}
 604
 605/**
 606 * si476x_core_get_revision_info()
 607 * @core: Core device structure
 608 *
 609 * Get the firmware version number of the device. It is done in
 610 * following three steps:
 611 *    1. Power-up the device
 612 *    2. Send the 'FUNC_INFO' command
 613 *    3. Powering the device down.
 614 *
 615 * The function return zero on success and a negative error code on
 616 * failure.
 617 */
 618static int si476x_core_get_revision_info(struct si476x_core *core)
 619{
 620        int rval;
 621        struct si476x_func_info info;
 622
 623        si476x_core_lock(core);
 624        rval = si476x_core_set_power_state(core, SI476X_POWER_UP_FULL);
 625        if (rval < 0)
 626                goto exit;
 627
 628        rval = si476x_core_cmd_func_info(core, &info);
 629        if (rval < 0)
 630                goto power_down;
 631
 632        core->revision = si476x_core_fwver_to_revision(core, info.func,
 633                                                       info.firmware.major,
 634                                                       info.firmware.minor[0],
 635                                                       info.firmware.minor[1]);
 636power_down:
 637        si476x_core_set_power_state(core, SI476X_POWER_DOWN);
 638exit:
 639        si476x_core_unlock(core);
 640
 641        return rval;
 642}
 643
 644bool si476x_core_has_am(struct si476x_core *core)
 645{
 646        return core->chip_id == SI476X_CHIP_SI4761 ||
 647                core->chip_id == SI476X_CHIP_SI4764;
 648}
 649EXPORT_SYMBOL_GPL(si476x_core_has_am);
 650
 651bool si476x_core_has_diversity(struct si476x_core *core)
 652{
 653        return core->chip_id == SI476X_CHIP_SI4764;
 654}
 655EXPORT_SYMBOL_GPL(si476x_core_has_diversity);
 656
 657bool si476x_core_is_a_secondary_tuner(struct si476x_core *core)
 658{
 659        return si476x_core_has_diversity(core) &&
 660                (core->diversity_mode == SI476X_PHDIV_SECONDARY_ANTENNA ||
 661                 core->diversity_mode == SI476X_PHDIV_SECONDARY_COMBINING);
 662}
 663EXPORT_SYMBOL_GPL(si476x_core_is_a_secondary_tuner);
 664
 665bool si476x_core_is_a_primary_tuner(struct si476x_core *core)
 666{
 667        return si476x_core_has_diversity(core) &&
 668                (core->diversity_mode == SI476X_PHDIV_PRIMARY_ANTENNA ||
 669                 core->diversity_mode == SI476X_PHDIV_PRIMARY_COMBINING);
 670}
 671EXPORT_SYMBOL_GPL(si476x_core_is_a_primary_tuner);
 672
 673bool si476x_core_is_in_am_receiver_mode(struct si476x_core *core)
 674{
 675        return si476x_core_has_am(core) &&
 676                (core->power_up_parameters.func == SI476X_FUNC_AM_RECEIVER);
 677}
 678EXPORT_SYMBOL_GPL(si476x_core_is_in_am_receiver_mode);
 679
 680bool si476x_core_is_powered_up(struct si476x_core *core)
 681{
 682        return core->power_state == SI476X_POWER_UP_FULL;
 683}
 684EXPORT_SYMBOL_GPL(si476x_core_is_powered_up);
 685
 686static int si476x_core_probe(struct i2c_client *client,
 687                             const struct i2c_device_id *id)
 688{
 689        int rval;
 690        struct si476x_core          *core;
 691        struct si476x_platform_data *pdata;
 692        struct mfd_cell *cell;
 693        int              cell_num;
 694
 695        core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
 696        if (!core)
 697                return -ENOMEM;
 698
 699        core->client = client;
 700
 701        core->regmap = devm_regmap_init_si476x(core);
 702        if (IS_ERR(core->regmap)) {
 703                rval = PTR_ERR(core->regmap);
 704                dev_err(&client->dev,
 705                        "Failed to allocate register map: %d\n",
 706                        rval);
 707                return rval;
 708        }
 709
 710        i2c_set_clientdata(client, core);
 711
 712        atomic_set(&core->is_alive, 0);
 713        core->power_state = SI476X_POWER_DOWN;
 714
 715        pdata = dev_get_platdata(&client->dev);
 716        if (pdata) {
 717                memcpy(&core->power_up_parameters,
 718                       &pdata->power_up_parameters,
 719                       sizeof(core->power_up_parameters));
 720
 721                core->gpio_reset = -1;
 722                if (gpio_is_valid(pdata->gpio_reset)) {
 723                        rval = gpio_request(pdata->gpio_reset, "si476x reset");
 724                        if (rval) {
 725                                dev_err(&client->dev,
 726                                        "Failed to request gpio: %d\n", rval);
 727                                return rval;
 728                        }
 729                        core->gpio_reset = pdata->gpio_reset;
 730                        gpio_direction_output(core->gpio_reset, 0);
 731                }
 732
 733                core->diversity_mode = pdata->diversity_mode;
 734                memcpy(&core->pinmux, &pdata->pinmux,
 735                       sizeof(struct si476x_pinmux));
 736        } else {
 737                dev_err(&client->dev, "No platform data provided\n");
 738                return -EINVAL;
 739        }
 740
 741        core->supplies[0].supply = "vd";
 742        core->supplies[1].supply = "va";
 743        core->supplies[2].supply = "vio1";
 744        core->supplies[3].supply = "vio2";
 745
 746        rval = devm_regulator_bulk_get(&client->dev,
 747                                       ARRAY_SIZE(core->supplies),
 748                                       core->supplies);
 749        if (rval) {
 750                dev_err(&client->dev, "Failed to get all of the regulators\n");
 751                goto free_gpio;
 752        }
 753
 754        mutex_init(&core->cmd_lock);
 755        init_waitqueue_head(&core->command);
 756        init_waitqueue_head(&core->tuning);
 757
 758        rval = kfifo_alloc(&core->rds_fifo,
 759                           SI476X_DRIVER_RDS_FIFO_DEPTH *
 760                           sizeof(struct v4l2_rds_data),
 761                           GFP_KERNEL);
 762        if (rval) {
 763                dev_err(&client->dev, "Could not allocate the FIFO\n");
 764                goto free_gpio;
 765        }
 766        mutex_init(&core->rds_drainer_status_lock);
 767        init_waitqueue_head(&core->rds_read_queue);
 768        INIT_WORK(&core->rds_fifo_drainer, si476x_core_drain_rds_fifo);
 769
 770        if (client->irq) {
 771                rval = devm_request_threaded_irq(&client->dev,
 772                                                 client->irq, NULL,
 773                                                 si476x_core_interrupt,
 774                                                 IRQF_TRIGGER_FALLING |
 775                                                 IRQF_ONESHOT,
 776                                                 client->name, core);
 777                if (rval < 0) {
 778                        dev_err(&client->dev, "Could not request IRQ %d\n",
 779                                client->irq);
 780                        goto free_kfifo;
 781                }
 782                disable_irq(client->irq);
 783                dev_dbg(&client->dev, "IRQ requested.\n");
 784
 785                core->rds_fifo_depth = 20;
 786        } else {
 787                INIT_DELAYED_WORK(&core->status_monitor,
 788                                  si476x_core_poll_loop);
 789                dev_info(&client->dev,
 790                         "No IRQ number specified, will use polling\n");
 791
 792                core->rds_fifo_depth = 5;
 793        }
 794
 795        core->chip_id = id->driver_data;
 796
 797        rval = si476x_core_get_revision_info(core);
 798        if (rval < 0) {
 799                rval = -ENODEV;
 800                goto free_kfifo;
 801        }
 802
 803        cell_num = 0;
 804
 805        cell = &core->cells[SI476X_RADIO_CELL];
 806        cell->name = "si476x-radio";
 807        cell_num++;
 808
 809#ifdef CONFIG_SND_SOC_SI476X
 810        if ((core->chip_id == SI476X_CHIP_SI4761 ||
 811             core->chip_id == SI476X_CHIP_SI4764)       &&
 812            core->pinmux.dclk == SI476X_DCLK_DAUDIO     &&
 813            core->pinmux.dfs  == SI476X_DFS_DAUDIO      &&
 814            core->pinmux.dout == SI476X_DOUT_I2S_OUTPUT &&
 815            core->pinmux.xout == SI476X_XOUT_TRISTATE) {
 816                cell = &core->cells[SI476X_CODEC_CELL];
 817                cell->name          = "si476x-codec";
 818                cell_num++;
 819        }
 820#endif
 821        rval = mfd_add_devices(&client->dev,
 822                               (client->adapter->nr << 8) + client->addr,
 823                               core->cells, cell_num,
 824                               NULL, 0, NULL);
 825        if (!rval)
 826                return 0;
 827
 828free_kfifo:
 829        kfifo_free(&core->rds_fifo);
 830
 831free_gpio:
 832        if (gpio_is_valid(core->gpio_reset))
 833                gpio_free(core->gpio_reset);
 834
 835        return rval;
 836}
 837
 838static int si476x_core_remove(struct i2c_client *client)
 839{
 840        struct si476x_core *core = i2c_get_clientdata(client);
 841
 842        si476x_core_pronounce_dead(core);
 843        mfd_remove_devices(&client->dev);
 844
 845        if (client->irq)
 846                disable_irq(client->irq);
 847        else
 848                cancel_delayed_work_sync(&core->status_monitor);
 849
 850        kfifo_free(&core->rds_fifo);
 851
 852        if (gpio_is_valid(core->gpio_reset))
 853                gpio_free(core->gpio_reset);
 854
 855        return 0;
 856}
 857
 858
 859static const struct i2c_device_id si476x_id[] = {
 860        { "si4761", SI476X_CHIP_SI4761 },
 861        { "si4764", SI476X_CHIP_SI4764 },
 862        { "si4768", SI476X_CHIP_SI4768 },
 863        { },
 864};
 865MODULE_DEVICE_TABLE(i2c, si476x_id);
 866
 867static struct i2c_driver si476x_core_driver = {
 868        .driver         = {
 869                .name   = "si476x-core",
 870        },
 871        .probe          = si476x_core_probe,
 872        .remove         = si476x_core_remove,
 873        .id_table       = si476x_id,
 874};
 875module_i2c_driver(si476x_core_driver);
 876
 877
 878MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
 879MODULE_DESCRIPTION("Si4761/64/68 AM/FM MFD core device driver");
 880MODULE_LICENSE("GPL");
 881