linux/drivers/mfd/twl6040.c
<<
>>
Prefs
   1/*
   2 * MFD driver for TWL6040 audio device
   3 *
   4 * Authors:     Misael Lopez Cruz <misael.lopez@ti.com>
   5 *              Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
   6 *              Peter Ujfalusi <peter.ujfalusi@ti.com>
   7 *
   8 * Copyright:   (C) 2011 Texas Instruments, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  22 * 02110-1301 USA
  23 *
  24 */
  25
  26#include <linux/module.h>
  27#include <linux/types.h>
  28#include <linux/slab.h>
  29#include <linux/kernel.h>
  30#include <linux/err.h>
  31#include <linux/platform_device.h>
  32#include <linux/of.h>
  33#include <linux/of_irq.h>
  34#include <linux/of_gpio.h>
  35#include <linux/of_platform.h>
  36#include <linux/gpio.h>
  37#include <linux/delay.h>
  38#include <linux/i2c.h>
  39#include <linux/regmap.h>
  40#include <linux/mfd/core.h>
  41#include <linux/mfd/twl6040.h>
  42#include <linux/regulator/consumer.h>
  43
  44#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
  45#define TWL6040_NUM_SUPPLIES    (2)
  46
  47static bool twl6040_has_vibra(struct twl6040_platform_data *pdata,
  48                              struct device_node *node)
  49{
  50        if (pdata && pdata->vibra)
  51                return true;
  52
  53#ifdef CONFIG_OF
  54        if (of_find_node_by_name(node, "vibra"))
  55                return true;
  56#endif
  57
  58        return false;
  59}
  60
  61int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
  62{
  63        int ret;
  64        unsigned int val;
  65
  66        /* Vibra control registers from cache */
  67        if (unlikely(reg == TWL6040_REG_VIBCTLL ||
  68                     reg == TWL6040_REG_VIBCTLR)) {
  69                val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
  70        } else {
  71                ret = regmap_read(twl6040->regmap, reg, &val);
  72                if (ret < 0)
  73                        return ret;
  74        }
  75
  76        return val;
  77}
  78EXPORT_SYMBOL(twl6040_reg_read);
  79
  80int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
  81{
  82        int ret;
  83
  84        ret = regmap_write(twl6040->regmap, reg, val);
  85        /* Cache the vibra control registers */
  86        if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
  87                twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
  88
  89        return ret;
  90}
  91EXPORT_SYMBOL(twl6040_reg_write);
  92
  93int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
  94{
  95        return regmap_update_bits(twl6040->regmap, reg, mask, mask);
  96}
  97EXPORT_SYMBOL(twl6040_set_bits);
  98
  99int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
 100{
 101        return regmap_update_bits(twl6040->regmap, reg, mask, 0);
 102}
 103EXPORT_SYMBOL(twl6040_clear_bits);
 104
 105/* twl6040 codec manual power-up sequence */
 106static int twl6040_power_up_manual(struct twl6040 *twl6040)
 107{
 108        u8 ldoctl, ncpctl, lppllctl;
 109        int ret;
 110
 111        /* enable high-side LDO, reference system and internal oscillator */
 112        ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
 113        ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 114        if (ret)
 115                return ret;
 116        usleep_range(10000, 10500);
 117
 118        /* enable negative charge pump */
 119        ncpctl = TWL6040_NCPENA;
 120        ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
 121        if (ret)
 122                goto ncp_err;
 123        usleep_range(1000, 1500);
 124
 125        /* enable low-side LDO */
 126        ldoctl |= TWL6040_LSLDOENA;
 127        ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 128        if (ret)
 129                goto lsldo_err;
 130        usleep_range(1000, 1500);
 131
 132        /* enable low-power PLL */
 133        lppllctl = TWL6040_LPLLENA;
 134        ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
 135        if (ret)
 136                goto lppll_err;
 137        usleep_range(5000, 5500);
 138
 139        /* disable internal oscillator */
 140        ldoctl &= ~TWL6040_OSCENA;
 141        ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 142        if (ret)
 143                goto osc_err;
 144
 145        return 0;
 146
 147osc_err:
 148        lppllctl &= ~TWL6040_LPLLENA;
 149        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
 150lppll_err:
 151        ldoctl &= ~TWL6040_LSLDOENA;
 152        twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 153lsldo_err:
 154        ncpctl &= ~TWL6040_NCPENA;
 155        twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
 156ncp_err:
 157        ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
 158        twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 159
 160        dev_err(twl6040->dev, "manual power-up failed\n");
 161        return ret;
 162}
 163
 164/* twl6040 manual power-down sequence */
 165static void twl6040_power_down_manual(struct twl6040 *twl6040)
 166{
 167        u8 ncpctl, ldoctl, lppllctl;
 168
 169        ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
 170        ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
 171        lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
 172
 173        /* enable internal oscillator */
 174        ldoctl |= TWL6040_OSCENA;
 175        twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 176        usleep_range(1000, 1500);
 177
 178        /* disable low-power PLL */
 179        lppllctl &= ~TWL6040_LPLLENA;
 180        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
 181
 182        /* disable low-side LDO */
 183        ldoctl &= ~TWL6040_LSLDOENA;
 184        twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 185
 186        /* disable negative charge pump */
 187        ncpctl &= ~TWL6040_NCPENA;
 188        twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
 189
 190        /* disable high-side LDO, reference system and internal oscillator */
 191        ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
 192        twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
 193}
 194
 195static irqreturn_t twl6040_readyint_handler(int irq, void *data)
 196{
 197        struct twl6040 *twl6040 = data;
 198
 199        complete(&twl6040->ready);
 200
 201        return IRQ_HANDLED;
 202}
 203
 204static irqreturn_t twl6040_thint_handler(int irq, void *data)
 205{
 206        struct twl6040 *twl6040 = data;
 207        u8 status;
 208
 209        status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
 210        if (status & TWL6040_TSHUTDET) {
 211                dev_warn(twl6040->dev, "Thermal shutdown, powering-off");
 212                twl6040_power(twl6040, 0);
 213        } else {
 214                dev_warn(twl6040->dev, "Leaving thermal shutdown, powering-on");
 215                twl6040_power(twl6040, 1);
 216        }
 217
 218        return IRQ_HANDLED;
 219}
 220
 221static int twl6040_power_up_automatic(struct twl6040 *twl6040)
 222{
 223        int time_left;
 224
 225        gpio_set_value(twl6040->audpwron, 1);
 226
 227        time_left = wait_for_completion_timeout(&twl6040->ready,
 228                                                msecs_to_jiffies(144));
 229        if (!time_left) {
 230                u8 intid;
 231
 232                dev_warn(twl6040->dev, "timeout waiting for READYINT\n");
 233                intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
 234                if (!(intid & TWL6040_READYINT)) {
 235                        dev_err(twl6040->dev, "automatic power-up failed\n");
 236                        gpio_set_value(twl6040->audpwron, 0);
 237                        return -ETIMEDOUT;
 238                }
 239        }
 240
 241        return 0;
 242}
 243
 244int twl6040_power(struct twl6040 *twl6040, int on)
 245{
 246        int ret = 0;
 247
 248        mutex_lock(&twl6040->mutex);
 249
 250        if (on) {
 251                /* already powered-up */
 252                if (twl6040->power_count++)
 253                        goto out;
 254
 255                if (gpio_is_valid(twl6040->audpwron)) {
 256                        /* use automatic power-up sequence */
 257                        ret = twl6040_power_up_automatic(twl6040);
 258                        if (ret) {
 259                                twl6040->power_count = 0;
 260                                goto out;
 261                        }
 262                } else {
 263                        /* use manual power-up sequence */
 264                        ret = twl6040_power_up_manual(twl6040);
 265                        if (ret) {
 266                                twl6040->power_count = 0;
 267                                goto out;
 268                        }
 269                }
 270                /* Default PLL configuration after power up */
 271                twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
 272                twl6040->sysclk = 19200000;
 273                twl6040->mclk = 32768;
 274        } else {
 275                /* already powered-down */
 276                if (!twl6040->power_count) {
 277                        dev_err(twl6040->dev,
 278                                "device is already powered-off\n");
 279                        ret = -EPERM;
 280                        goto out;
 281                }
 282
 283                if (--twl6040->power_count)
 284                        goto out;
 285
 286                if (gpio_is_valid(twl6040->audpwron)) {
 287                        /* use AUDPWRON line */
 288                        gpio_set_value(twl6040->audpwron, 0);
 289
 290                        /* power-down sequence latency */
 291                        usleep_range(500, 700);
 292                } else {
 293                        /* use manual power-down sequence */
 294                        twl6040_power_down_manual(twl6040);
 295                }
 296                twl6040->sysclk = 0;
 297                twl6040->mclk = 0;
 298        }
 299
 300out:
 301        mutex_unlock(&twl6040->mutex);
 302        return ret;
 303}
 304EXPORT_SYMBOL(twl6040_power);
 305
 306int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
 307                    unsigned int freq_in, unsigned int freq_out)
 308{
 309        u8 hppllctl, lppllctl;
 310        int ret = 0;
 311
 312        mutex_lock(&twl6040->mutex);
 313
 314        hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
 315        lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
 316
 317        /* Force full reconfiguration when switching between PLL */
 318        if (pll_id != twl6040->pll) {
 319                twl6040->sysclk = 0;
 320                twl6040->mclk = 0;
 321        }
 322
 323        switch (pll_id) {
 324        case TWL6040_SYSCLK_SEL_LPPLL:
 325                /* low-power PLL divider */
 326                /* Change the sysclk configuration only if it has been canged */
 327                if (twl6040->sysclk != freq_out) {
 328                        switch (freq_out) {
 329                        case 17640000:
 330                                lppllctl |= TWL6040_LPLLFIN;
 331                                break;
 332                        case 19200000:
 333                                lppllctl &= ~TWL6040_LPLLFIN;
 334                                break;
 335                        default:
 336                                dev_err(twl6040->dev,
 337                                        "freq_out %d not supported\n",
 338                                        freq_out);
 339                                ret = -EINVAL;
 340                                goto pll_out;
 341                        }
 342                        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
 343                                          lppllctl);
 344                }
 345
 346                /* The PLL in use has not been change, we can exit */
 347                if (twl6040->pll == pll_id)
 348                        break;
 349
 350                switch (freq_in) {
 351                case 32768:
 352                        lppllctl |= TWL6040_LPLLENA;
 353                        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
 354                                          lppllctl);
 355                        mdelay(5);
 356                        lppllctl &= ~TWL6040_HPLLSEL;
 357                        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
 358                                          lppllctl);
 359                        hppllctl &= ~TWL6040_HPLLENA;
 360                        twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
 361                                          hppllctl);
 362                        break;
 363                default:
 364                        dev_err(twl6040->dev,
 365                                "freq_in %d not supported\n", freq_in);
 366                        ret = -EINVAL;
 367                        goto pll_out;
 368                }
 369                break;
 370        case TWL6040_SYSCLK_SEL_HPPLL:
 371                /* high-performance PLL can provide only 19.2 MHz */
 372                if (freq_out != 19200000) {
 373                        dev_err(twl6040->dev,
 374                                "freq_out %d not supported\n", freq_out);
 375                        ret = -EINVAL;
 376                        goto pll_out;
 377                }
 378
 379                if (twl6040->mclk != freq_in) {
 380                        hppllctl &= ~TWL6040_MCLK_MSK;
 381
 382                        switch (freq_in) {
 383                        case 12000000:
 384                                /* PLL enabled, active mode */
 385                                hppllctl |= TWL6040_MCLK_12000KHZ |
 386                                            TWL6040_HPLLENA;
 387                                break;
 388                        case 19200000:
 389                                /*
 390                                * PLL disabled
 391                                * (enable PLL if MCLK jitter quality
 392                                *  doesn't meet specification)
 393                                */
 394                                hppllctl |= TWL6040_MCLK_19200KHZ;
 395                                break;
 396                        case 26000000:
 397                                /* PLL enabled, active mode */
 398                                hppllctl |= TWL6040_MCLK_26000KHZ |
 399                                            TWL6040_HPLLENA;
 400                                break;
 401                        case 38400000:
 402                                /* PLL enabled, active mode */
 403                                hppllctl |= TWL6040_MCLK_38400KHZ |
 404                                            TWL6040_HPLLENA;
 405                                break;
 406                        default:
 407                                dev_err(twl6040->dev,
 408                                        "freq_in %d not supported\n", freq_in);
 409                                ret = -EINVAL;
 410                                goto pll_out;
 411                        }
 412
 413                        /*
 414                         * enable clock slicer to ensure input waveform is
 415                         * square
 416                         */
 417                        hppllctl |= TWL6040_HPLLSQRENA;
 418
 419                        twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
 420                                          hppllctl);
 421                        usleep_range(500, 700);
 422                        lppllctl |= TWL6040_HPLLSEL;
 423                        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
 424                                          lppllctl);
 425                        lppllctl &= ~TWL6040_LPLLENA;
 426                        twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
 427                                          lppllctl);
 428                }
 429                break;
 430        default:
 431                dev_err(twl6040->dev, "unknown pll id %d\n", pll_id);
 432                ret = -EINVAL;
 433                goto pll_out;
 434        }
 435
 436        twl6040->sysclk = freq_out;
 437        twl6040->mclk = freq_in;
 438        twl6040->pll = pll_id;
 439
 440pll_out:
 441        mutex_unlock(&twl6040->mutex);
 442        return ret;
 443}
 444EXPORT_SYMBOL(twl6040_set_pll);
 445
 446int twl6040_get_pll(struct twl6040 *twl6040)
 447{
 448        if (twl6040->power_count)
 449                return twl6040->pll;
 450        else
 451                return -ENODEV;
 452}
 453EXPORT_SYMBOL(twl6040_get_pll);
 454
 455unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
 456{
 457        return twl6040->sysclk;
 458}
 459EXPORT_SYMBOL(twl6040_get_sysclk);
 460
 461/* Get the combined status of the vibra control register */
 462int twl6040_get_vibralr_status(struct twl6040 *twl6040)
 463{
 464        u8 status;
 465
 466        status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
 467        status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
 468
 469        return status;
 470}
 471EXPORT_SYMBOL(twl6040_get_vibralr_status);
 472
 473static struct resource twl6040_vibra_rsrc[] = {
 474        {
 475                .flags = IORESOURCE_IRQ,
 476        },
 477};
 478
 479static struct resource twl6040_codec_rsrc[] = {
 480        {
 481                .flags = IORESOURCE_IRQ,
 482        },
 483};
 484
 485static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
 486{
 487        /* Register 0 is not readable */
 488        if (!reg)
 489                return false;
 490        return true;
 491}
 492
 493static struct regmap_config twl6040_regmap_config = {
 494        .reg_bits = 8,
 495        .val_bits = 8,
 496        .max_register = TWL6040_REG_STATUS, /* 0x2e */
 497
 498        .readable_reg = twl6040_readable_reg,
 499};
 500
 501static const struct regmap_irq twl6040_irqs[] = {
 502        { .reg_offset = 0, .mask = TWL6040_THINT, },
 503        { .reg_offset = 0, .mask = TWL6040_PLUGINT | TWL6040_UNPLUGINT, },
 504        { .reg_offset = 0, .mask = TWL6040_HOOKINT, },
 505        { .reg_offset = 0, .mask = TWL6040_HFINT, },
 506        { .reg_offset = 0, .mask = TWL6040_VIBINT, },
 507        { .reg_offset = 0, .mask = TWL6040_READYINT, },
 508};
 509
 510static struct regmap_irq_chip twl6040_irq_chip = {
 511        .name = "twl6040",
 512        .irqs = twl6040_irqs,
 513        .num_irqs = ARRAY_SIZE(twl6040_irqs),
 514
 515        .num_regs = 1,
 516        .status_base = TWL6040_REG_INTID,
 517        .mask_base = TWL6040_REG_INTMR,
 518};
 519
 520static int twl6040_probe(struct i2c_client *client,
 521                         const struct i2c_device_id *id)
 522{
 523        struct twl6040_platform_data *pdata = client->dev.platform_data;
 524        struct device_node *node = client->dev.of_node;
 525        struct twl6040 *twl6040;
 526        struct mfd_cell *cell = NULL;
 527        int irq, ret, children = 0;
 528
 529        if (!pdata && !node) {
 530                dev_err(&client->dev, "Platform data is missing\n");
 531                return -EINVAL;
 532        }
 533
 534        /* In order to operate correctly we need valid interrupt config */
 535        if (!client->irq) {
 536                dev_err(&client->dev, "Invalid IRQ configuration\n");
 537                return -EINVAL;
 538        }
 539
 540        twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
 541                               GFP_KERNEL);
 542        if (!twl6040) {
 543                ret = -ENOMEM;
 544                goto err;
 545        }
 546
 547        twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config);
 548        if (IS_ERR(twl6040->regmap)) {
 549                ret = PTR_ERR(twl6040->regmap);
 550                goto err;
 551        }
 552
 553        i2c_set_clientdata(client, twl6040);
 554
 555        twl6040->supplies[0].supply = "vio";
 556        twl6040->supplies[1].supply = "v2v1";
 557        ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
 558                                 twl6040->supplies);
 559        if (ret != 0) {
 560                dev_err(&client->dev, "Failed to get supplies: %d\n", ret);
 561                goto regulator_get_err;
 562        }
 563
 564        ret = regulator_bulk_enable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
 565        if (ret != 0) {
 566                dev_err(&client->dev, "Failed to enable supplies: %d\n", ret);
 567                goto regulator_get_err;
 568        }
 569
 570        twl6040->dev = &client->dev;
 571        twl6040->irq = client->irq;
 572
 573        mutex_init(&twl6040->mutex);
 574        init_completion(&twl6040->ready);
 575
 576        twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
 577
 578        /* ERRATA: Automatic power-up is not possible in ES1.0 */
 579        if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
 580                if (pdata)
 581                        twl6040->audpwron = pdata->audpwron_gpio;
 582                else
 583                        twl6040->audpwron = of_get_named_gpio(node,
 584                                                "ti,audpwron-gpio", 0);
 585        } else
 586                twl6040->audpwron = -EINVAL;
 587
 588        if (gpio_is_valid(twl6040->audpwron)) {
 589                ret = devm_gpio_request_one(&client->dev, twl6040->audpwron,
 590                                        GPIOF_OUT_INIT_LOW, "audpwron");
 591                if (ret)
 592                        goto gpio_err;
 593        }
 594
 595        ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq,
 596                        IRQF_ONESHOT, 0, &twl6040_irq_chip,
 597                        &twl6040->irq_data);
 598        if (ret < 0)
 599                goto gpio_err;
 600
 601        twl6040->irq_ready = regmap_irq_get_virq(twl6040->irq_data,
 602                                               TWL6040_IRQ_READY);
 603        twl6040->irq_th = regmap_irq_get_virq(twl6040->irq_data,
 604                                               TWL6040_IRQ_TH);
 605
 606        ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_ready, NULL,
 607                                   twl6040_readyint_handler, IRQF_ONESHOT,
 608                                   "twl6040_irq_ready", twl6040);
 609        if (ret) {
 610                dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret);
 611                goto readyirq_err;
 612        }
 613
 614        ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_th, NULL,
 615                                   twl6040_thint_handler, IRQF_ONESHOT,
 616                                   "twl6040_irq_th", twl6040);
 617        if (ret) {
 618                dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret);
 619                goto thirq_err;
 620        }
 621
 622        /* dual-access registers controlled by I2C only */
 623        twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
 624
 625        /*
 626         * The main functionality of twl6040 to provide audio on OMAP4+ systems.
 627         * We can add the ASoC codec child whenever this driver has been loaded.
 628         * The ASoC codec can work without pdata, pass the platform_data only if
 629         * it has been provided.
 630         */
 631        irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_PLUG);
 632        cell = &twl6040->cells[children];
 633        cell->name = "twl6040-codec";
 634        twl6040_codec_rsrc[0].start = irq;
 635        twl6040_codec_rsrc[0].end = irq;
 636        cell->resources = twl6040_codec_rsrc;
 637        cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
 638        if (pdata && pdata->codec) {
 639                cell->platform_data = pdata->codec;
 640                cell->pdata_size = sizeof(*pdata->codec);
 641        }
 642        children++;
 643
 644        if (twl6040_has_vibra(pdata, node)) {
 645                irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_VIB);
 646
 647                cell = &twl6040->cells[children];
 648                cell->name = "twl6040-vibra";
 649                twl6040_vibra_rsrc[0].start = irq;
 650                twl6040_vibra_rsrc[0].end = irq;
 651                cell->resources = twl6040_vibra_rsrc;
 652                cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
 653
 654                if (pdata && pdata->vibra) {
 655                        cell->platform_data = pdata->vibra;
 656                        cell->pdata_size = sizeof(*pdata->vibra);
 657                }
 658                children++;
 659        }
 660
 661        /*
 662         * Enable the GPO driver in the following cases:
 663         * DT booted kernel or legacy boot with valid gpo platform_data
 664         */
 665        if (!pdata || (pdata && pdata->gpo)) {
 666                cell = &twl6040->cells[children];
 667                cell->name = "twl6040-gpo";
 668
 669                if (pdata) {
 670                        cell->platform_data = pdata->gpo;
 671                        cell->pdata_size = sizeof(*pdata->gpo);
 672                }
 673                children++;
 674        }
 675
 676        ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
 677                              NULL, 0, NULL);
 678        if (ret)
 679                goto mfd_err;
 680
 681        return 0;
 682
 683mfd_err:
 684        devm_free_irq(&client->dev, twl6040->irq_th, twl6040);
 685thirq_err:
 686        devm_free_irq(&client->dev, twl6040->irq_ready, twl6040);
 687readyirq_err:
 688        regmap_del_irq_chip(twl6040->irq, twl6040->irq_data);
 689gpio_err:
 690        regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
 691regulator_get_err:
 692        i2c_set_clientdata(client, NULL);
 693err:
 694        return ret;
 695}
 696
 697static int twl6040_remove(struct i2c_client *client)
 698{
 699        struct twl6040 *twl6040 = i2c_get_clientdata(client);
 700
 701        if (twl6040->power_count)
 702                twl6040_power(twl6040, 0);
 703
 704        devm_free_irq(&client->dev, twl6040->irq_ready, twl6040);
 705        devm_free_irq(&client->dev, twl6040->irq_th, twl6040);
 706        regmap_del_irq_chip(twl6040->irq, twl6040->irq_data);
 707
 708        mfd_remove_devices(&client->dev);
 709        i2c_set_clientdata(client, NULL);
 710
 711        regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
 712
 713        return 0;
 714}
 715
 716static const struct i2c_device_id twl6040_i2c_id[] = {
 717        { "twl6040", 0, },
 718        { "twl6041", 0, },
 719        { },
 720};
 721MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id);
 722
 723static struct i2c_driver twl6040_driver = {
 724        .driver = {
 725                .name = "twl6040",
 726                .owner = THIS_MODULE,
 727        },
 728        .probe          = twl6040_probe,
 729        .remove         = twl6040_remove,
 730        .id_table       = twl6040_i2c_id,
 731};
 732
 733module_i2c_driver(twl6040_driver);
 734
 735MODULE_DESCRIPTION("TWL6040 MFD");
 736MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 737MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
 738MODULE_LICENSE("GPL");
 739MODULE_ALIAS("platform:twl6040");
 740
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.