linux/sound/soc/codecs/twl6040.c
<<
>>
Prefs
   1/*
   2 * ALSA SoC TWL6040 codec driver
   3 *
   4 * Author:       Misael Lopez Cruz <x0052729@ti.com>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * version 2 as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  18 * 02110-1301 USA
  19 *
  20 */
  21
  22#include <linux/module.h>
  23#include <linux/moduleparam.h>
  24#include <linux/init.h>
  25#include <linux/delay.h>
  26#include <linux/pm.h>
  27#include <linux/platform_device.h>
  28#include <linux/slab.h>
  29#include <linux/mfd/twl6040.h>
  30
  31#include <sound/core.h>
  32#include <sound/pcm.h>
  33#include <sound/pcm_params.h>
  34#include <sound/soc.h>
  35#include <sound/soc-dapm.h>
  36#include <sound/initval.h>
  37#include <sound/tlv.h>
  38
  39#include "twl6040.h"
  40
  41enum twl6040_dai_id {
  42        TWL6040_DAI_LEGACY = 0,
  43        TWL6040_DAI_UL,
  44        TWL6040_DAI_DL1,
  45        TWL6040_DAI_DL2,
  46        TWL6040_DAI_VIB,
  47};
  48
  49#define TWL6040_RATES           SNDRV_PCM_RATE_8000_96000
  50#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
  51
  52#define TWL6040_OUTHS_0dB 0x00
  53#define TWL6040_OUTHS_M30dB 0x0F
  54#define TWL6040_OUTHF_0dB 0x03
  55#define TWL6040_OUTHF_M52dB 0x1D
  56
  57#define TWL6040_CACHEREGNUM     (TWL6040_REG_STATUS + 1)
  58
  59struct twl6040_jack_data {
  60        struct snd_soc_jack *jack;
  61        struct delayed_work work;
  62        int report;
  63};
  64
  65/* codec private data */
  66struct twl6040_data {
  67        int plug_irq;
  68        int codec_powered;
  69        int pll;
  70        int pll_power_mode;
  71        int hs_power_mode;
  72        int hs_power_mode_locked;
  73        bool dl1_unmuted;
  74        bool dl2_unmuted;
  75        u8 dl12_cache[TWL6040_REG_HFRCTL - TWL6040_REG_HSLCTL + 1];
  76        unsigned int clk_in;
  77        unsigned int sysclk;
  78        struct twl6040_jack_data hs_jack;
  79        struct snd_soc_codec *codec;
  80        struct mutex mutex;
  81};
  82
  83/* set of rates for each pll: low-power and high-performance */
  84static const unsigned int lp_rates[] = {
  85        8000,
  86        11250,
  87        16000,
  88        22500,
  89        32000,
  90        44100,
  91        48000,
  92        88200,
  93        96000,
  94};
  95
  96static const unsigned int hp_rates[] = {
  97        8000,
  98        16000,
  99        32000,
 100        48000,
 101        96000,
 102};
 103
 104static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
 105        { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, },
 106        { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
 107};
 108
 109static unsigned int twl6040_read(struct snd_soc_codec *codec, unsigned int reg)
 110{
 111        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 112        struct twl6040 *twl6040 = codec->control_data;
 113        u8 value;
 114
 115        if (reg >= TWL6040_CACHEREGNUM)
 116                return -EIO;
 117
 118        switch (reg) {
 119        case TWL6040_REG_HSLCTL:
 120        case TWL6040_REG_HSRCTL:
 121        case TWL6040_REG_EARCTL:
 122        case TWL6040_REG_HFLCTL:
 123        case TWL6040_REG_HFRCTL:
 124                value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL];
 125                break;
 126        default:
 127                value = twl6040_reg_read(twl6040, reg);
 128                break;
 129        }
 130
 131        return value;
 132}
 133
 134static bool twl6040_can_write_to_chip(struct snd_soc_codec *codec,
 135                                  unsigned int reg)
 136{
 137        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 138
 139        switch (reg) {
 140        case TWL6040_REG_HSLCTL:
 141        case TWL6040_REG_HSRCTL:
 142        case TWL6040_REG_EARCTL:
 143                /* DL1 path */
 144                return priv->dl1_unmuted;
 145        case TWL6040_REG_HFLCTL:
 146        case TWL6040_REG_HFRCTL:
 147                return priv->dl2_unmuted;
 148        default:
 149                return 1;
 150        }
 151}
 152
 153static inline void twl6040_update_dl12_cache(struct snd_soc_codec *codec,
 154                                             u8 reg, u8 value)
 155{
 156        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 157
 158        switch (reg) {
 159        case TWL6040_REG_HSLCTL:
 160        case TWL6040_REG_HSRCTL:
 161        case TWL6040_REG_EARCTL:
 162        case TWL6040_REG_HFLCTL:
 163        case TWL6040_REG_HFRCTL:
 164                priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value;
 165                break;
 166        default:
 167                break;
 168        }
 169}
 170
 171static int twl6040_write(struct snd_soc_codec *codec,
 172                        unsigned int reg, unsigned int value)
 173{
 174        struct twl6040 *twl6040 = codec->control_data;
 175
 176        if (reg >= TWL6040_CACHEREGNUM)
 177                return -EIO;
 178
 179        twl6040_update_dl12_cache(codec, reg, value);
 180        if (twl6040_can_write_to_chip(codec, reg))
 181                return twl6040_reg_write(twl6040, reg, value);
 182        else
 183                return 0;
 184}
 185
 186static void twl6040_init_chip(struct snd_soc_codec *codec)
 187{
 188        twl6040_read(codec, TWL6040_REG_TRIM1);
 189        twl6040_read(codec, TWL6040_REG_TRIM2);
 190        twl6040_read(codec, TWL6040_REG_TRIM3);
 191        twl6040_read(codec, TWL6040_REG_HSOTRIM);
 192        twl6040_read(codec, TWL6040_REG_HFOTRIM);
 193
 194        /* Change chip defaults */
 195        /* No imput selected for microphone amplifiers */
 196        twl6040_write(codec, TWL6040_REG_MICLCTL, 0x18);
 197        twl6040_write(codec, TWL6040_REG_MICRCTL, 0x18);
 198
 199        /*
 200         * We need to lower the default gain values, so the ramp code
 201         * can work correctly for the first playback.
 202         * This reduces the pop noise heard at the first playback.
 203         */
 204        twl6040_write(codec, TWL6040_REG_HSGAIN, 0xff);
 205        twl6040_write(codec, TWL6040_REG_EARCTL, 0x1e);
 206        twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1d);
 207        twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1d);
 208        twl6040_write(codec, TWL6040_REG_LINEGAIN, 0);
 209}
 210
 211/* set headset dac and driver power mode */
 212static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 213{
 214        int hslctl, hsrctl;
 215        int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
 216
 217        hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
 218        hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
 219
 220        if (high_perf) {
 221                hslctl &= ~mask;
 222                hsrctl &= ~mask;
 223        } else {
 224                hslctl |= mask;
 225                hsrctl |= mask;
 226        }
 227
 228        twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
 229        twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
 230
 231        return 0;
 232}
 233
 234static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
 235                        struct snd_kcontrol *kcontrol, int event)
 236{
 237        struct snd_soc_codec *codec = w->codec;
 238        u8 hslctl, hsrctl;
 239
 240        /*
 241         * Workaround for Headset DC offset caused pop noise:
 242         * Both HS DAC need to be turned on (before the HS driver) and off at
 243         * the same time.
 244         */
 245        hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
 246        hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
 247        if (SND_SOC_DAPM_EVENT_ON(event)) {
 248                hslctl |= TWL6040_HSDACENA;
 249                hsrctl |= TWL6040_HSDACENA;
 250        } else {
 251                hslctl &= ~TWL6040_HSDACENA;
 252                hsrctl &= ~TWL6040_HSDACENA;
 253        }
 254        twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
 255        twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
 256
 257        msleep(1);
 258        return 0;
 259}
 260
 261static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w,
 262                        struct snd_kcontrol *kcontrol, int event)
 263{
 264        struct snd_soc_codec *codec = w->codec;
 265        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 266        int ret = 0;
 267
 268        if (SND_SOC_DAPM_EVENT_ON(event)) {
 269                /* Earphone doesn't support low power mode */
 270                priv->hs_power_mode_locked = 1;
 271                ret = headset_power_mode(codec, 1);
 272        } else {
 273                priv->hs_power_mode_locked = 0;
 274                ret = headset_power_mode(codec, priv->hs_power_mode);
 275        }
 276
 277        msleep(1);
 278
 279        return ret;
 280}
 281
 282static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
 283                                   struct snd_soc_jack *jack, int report)
 284{
 285        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 286        int status;
 287
 288        mutex_lock(&priv->mutex);
 289
 290        /* Sync status */
 291        status = twl6040_read(codec, TWL6040_REG_STATUS);
 292        if (status & TWL6040_PLUGCOMP)
 293                snd_soc_jack_report(jack, report, report);
 294        else
 295                snd_soc_jack_report(jack, 0, report);
 296
 297        mutex_unlock(&priv->mutex);
 298}
 299
 300void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
 301                                struct snd_soc_jack *jack, int report)
 302{
 303        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 304        struct twl6040_jack_data *hs_jack = &priv->hs_jack;
 305
 306        hs_jack->jack = jack;
 307        hs_jack->report = report;
 308
 309        twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
 310}
 311EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
 312
 313static void twl6040_accessory_work(struct work_struct *work)
 314{
 315        struct twl6040_data *priv = container_of(work,
 316                                        struct twl6040_data, hs_jack.work.work);
 317        struct snd_soc_codec *codec = priv->codec;
 318        struct twl6040_jack_data *hs_jack = &priv->hs_jack;
 319
 320        twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
 321}
 322
 323/* audio interrupt handler */
 324static irqreturn_t twl6040_audio_handler(int irq, void *data)
 325{
 326        struct snd_soc_codec *codec = data;
 327        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 328
 329        queue_delayed_work(system_power_efficient_wq,
 330                           &priv->hs_jack.work, msecs_to_jiffies(200));
 331
 332        return IRQ_HANDLED;
 333}
 334
 335static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
 336        struct snd_ctl_elem_value *ucontrol)
 337{
 338        struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 339        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 340        unsigned int val;
 341
 342        /* Do not allow changes while Input/FF efect is running */
 343        val = twl6040_read(codec, e->reg);
 344        if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
 345                return -EBUSY;
 346
 347        return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
 348}
 349
 350/*
 351 * MICATT volume control:
 352 * from -6 to 0 dB in 6 dB steps
 353 */
 354static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
 355
 356/*
 357 * MICGAIN volume control:
 358 * from 6 to 30 dB in 6 dB steps
 359 */
 360static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
 361
 362/*
 363 * AFMGAIN volume control:
 364 * from -18 to 24 dB in 6 dB steps
 365 */
 366static DECLARE_TLV_DB_SCALE(afm_amp_tlv, -1800, 600, 0);
 367
 368/*
 369 * HSGAIN volume control:
 370 * from -30 to 0 dB in 2 dB steps
 371 */
 372static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
 373
 374/*
 375 * HFGAIN volume control:
 376 * from -52 to 6 dB in 2 dB steps
 377 */
 378static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
 379
 380/*
 381 * EPGAIN volume control:
 382 * from -24 to 6 dB in 2 dB steps
 383 */
 384static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0);
 385
 386/* Left analog microphone selection */
 387static const char *twl6040_amicl_texts[] =
 388        {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
 389
 390/* Right analog microphone selection */
 391static const char *twl6040_amicr_texts[] =
 392        {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
 393
 394static const struct soc_enum twl6040_enum[] = {
 395        SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3,
 396                        ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts),
 397        SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3,
 398                        ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts),
 399};
 400
 401static const char *twl6040_hs_texts[] = {
 402        "Off", "HS DAC", "Line-In amp"
 403};
 404
 405static const struct soc_enum twl6040_hs_enum[] = {
 406        SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
 407                        twl6040_hs_texts),
 408        SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
 409                        twl6040_hs_texts),
 410};
 411
 412static const char *twl6040_hf_texts[] = {
 413        "Off", "HF DAC", "Line-In amp"
 414};
 415
 416static const struct soc_enum twl6040_hf_enum[] = {
 417        SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
 418                        twl6040_hf_texts),
 419        SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
 420                        twl6040_hf_texts),
 421};
 422
 423static const char *twl6040_vibrapath_texts[] = {
 424        "Input FF", "Audio PDM"
 425};
 426
 427static const struct soc_enum twl6040_vibra_enum[] = {
 428        SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1,
 429                        ARRAY_SIZE(twl6040_vibrapath_texts),
 430                        twl6040_vibrapath_texts),
 431        SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1,
 432                        ARRAY_SIZE(twl6040_vibrapath_texts),
 433                        twl6040_vibrapath_texts),
 434};
 435
 436static const struct snd_kcontrol_new amicl_control =
 437        SOC_DAPM_ENUM("Route", twl6040_enum[0]);
 438
 439static const struct snd_kcontrol_new amicr_control =
 440        SOC_DAPM_ENUM("Route", twl6040_enum[1]);
 441
 442/* Headset DAC playback switches */
 443static const struct snd_kcontrol_new hsl_mux_controls =
 444        SOC_DAPM_ENUM("Route", twl6040_hs_enum[0]);
 445
 446static const struct snd_kcontrol_new hsr_mux_controls =
 447        SOC_DAPM_ENUM("Route", twl6040_hs_enum[1]);
 448
 449/* Handsfree DAC playback switches */
 450static const struct snd_kcontrol_new hfl_mux_controls =
 451        SOC_DAPM_ENUM("Route", twl6040_hf_enum[0]);
 452
 453static const struct snd_kcontrol_new hfr_mux_controls =
 454        SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
 455
 456static const struct snd_kcontrol_new ep_path_enable_control =
 457        SOC_DAPM_SINGLE_VIRT("Switch", 1);
 458
 459static const struct snd_kcontrol_new auxl_switch_control =
 460        SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
 461
 462static const struct snd_kcontrol_new auxr_switch_control =
 463        SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
 464
 465/* Vibra playback switches */
 466static const struct snd_kcontrol_new vibral_mux_controls =
 467        SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0],
 468                snd_soc_dapm_get_enum_double,
 469                twl6040_soc_dapm_put_vibra_enum);
 470
 471static const struct snd_kcontrol_new vibrar_mux_controls =
 472        SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1],
 473                snd_soc_dapm_get_enum_double,
 474                twl6040_soc_dapm_put_vibra_enum);
 475
 476/* Headset power mode */
 477static const char *twl6040_power_mode_texts[] = {
 478        "Low-Power", "High-Performance",
 479};
 480
 481static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum,
 482                                twl6040_power_mode_texts);
 483
 484static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
 485        struct snd_ctl_elem_value *ucontrol)
 486{
 487        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 488        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 489
 490        ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
 491
 492        return 0;
 493}
 494
 495static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
 496        struct snd_ctl_elem_value *ucontrol)
 497{
 498        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 499        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 500        int high_perf = ucontrol->value.enumerated.item[0];
 501        int ret = 0;
 502
 503        if (!priv->hs_power_mode_locked)
 504                ret = headset_power_mode(codec, high_perf);
 505
 506        if (!ret)
 507                priv->hs_power_mode = high_perf;
 508
 509        return ret;
 510}
 511
 512static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
 513        struct snd_ctl_elem_value *ucontrol)
 514{
 515        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 516        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 517
 518        ucontrol->value.enumerated.item[0] = priv->pll_power_mode;
 519
 520        return 0;
 521}
 522
 523static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
 524        struct snd_ctl_elem_value *ucontrol)
 525{
 526        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 527        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 528
 529        priv->pll_power_mode = ucontrol->value.enumerated.item[0];
 530
 531        return 0;
 532}
 533
 534int twl6040_get_dl1_gain(struct snd_soc_codec *codec)
 535{
 536        struct snd_soc_dapm_context *dapm = &codec->dapm;
 537
 538        if (snd_soc_dapm_get_pin_status(dapm, "EP"))
 539                return -1; /* -1dB */
 540
 541        if (snd_soc_dapm_get_pin_status(dapm, "HSOR") ||
 542                snd_soc_dapm_get_pin_status(dapm, "HSOL")) {
 543
 544                u8 val = snd_soc_read(codec, TWL6040_REG_HSLCTL);
 545                if (val & TWL6040_HSDACMODE)
 546                        /* HSDACL in LP mode */
 547                        return -8; /* -8dB */
 548                else
 549                        /* HSDACL in HP mode */
 550                        return -1; /* -1dB */
 551        }
 552        return 0; /* 0dB */
 553}
 554EXPORT_SYMBOL_GPL(twl6040_get_dl1_gain);
 555
 556int twl6040_get_clk_id(struct snd_soc_codec *codec)
 557{
 558        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 559
 560        return priv->pll_power_mode;
 561}
 562EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
 563
 564int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
 565{
 566        if (unlikely(trim >= TWL6040_TRIM_INVAL))
 567                return -EINVAL;
 568
 569        return twl6040_read(codec, TWL6040_REG_TRIM1 + trim);
 570}
 571EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
 572
 573int twl6040_get_hs_step_size(struct snd_soc_codec *codec)
 574{
 575        struct twl6040 *twl6040 = codec->control_data;
 576
 577        if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_3)
 578                /* For ES under ES_1.3 HS step is 2 mV */
 579                return 2;
 580        else
 581                /* For ES_1.3 HS step is 1 mV */
 582                return 1;
 583}
 584EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size);
 585
 586static const struct snd_kcontrol_new twl6040_snd_controls[] = {
 587        /* Capture gains */
 588        SOC_DOUBLE_TLV("Capture Preamplifier Volume",
 589                TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
 590        SOC_DOUBLE_TLV("Capture Volume",
 591                TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
 592
 593        /* AFM gains */
 594        SOC_DOUBLE_TLV("Aux FM Volume",
 595                TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
 596
 597        /* Playback gains */
 598        SOC_DOUBLE_TLV("Headset Playback Volume",
 599                TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
 600        SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
 601                TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
 602        SOC_SINGLE_TLV("Earphone Playback Volume",
 603                TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
 604
 605        SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum,
 606                twl6040_headset_power_get_enum,
 607                twl6040_headset_power_put_enum),
 608
 609        SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum,
 610                twl6040_pll_get_enum, twl6040_pll_put_enum),
 611};
 612
 613static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
 614        /* Inputs */
 615        SND_SOC_DAPM_INPUT("MAINMIC"),
 616        SND_SOC_DAPM_INPUT("HSMIC"),
 617        SND_SOC_DAPM_INPUT("SUBMIC"),
 618        SND_SOC_DAPM_INPUT("AFML"),
 619        SND_SOC_DAPM_INPUT("AFMR"),
 620
 621        /* Outputs */
 622        SND_SOC_DAPM_OUTPUT("HSOL"),
 623        SND_SOC_DAPM_OUTPUT("HSOR"),
 624        SND_SOC_DAPM_OUTPUT("HFL"),
 625        SND_SOC_DAPM_OUTPUT("HFR"),
 626        SND_SOC_DAPM_OUTPUT("EP"),
 627        SND_SOC_DAPM_OUTPUT("AUXL"),
 628        SND_SOC_DAPM_OUTPUT("AUXR"),
 629        SND_SOC_DAPM_OUTPUT("VIBRAL"),
 630        SND_SOC_DAPM_OUTPUT("VIBRAR"),
 631
 632        /* Analog input muxes for the capture amplifiers */
 633        SND_SOC_DAPM_MUX("Analog Left Capture Route",
 634                        SND_SOC_NOPM, 0, 0, &amicl_control),
 635        SND_SOC_DAPM_MUX("Analog Right Capture Route",
 636                        SND_SOC_NOPM, 0, 0, &amicr_control),
 637
 638        /* Analog capture PGAs */
 639        SND_SOC_DAPM_PGA("MicAmpL",
 640                        TWL6040_REG_MICLCTL, 0, 0, NULL, 0),
 641        SND_SOC_DAPM_PGA("MicAmpR",
 642                        TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
 643
 644        /* Auxiliary FM PGAs */
 645        SND_SOC_DAPM_PGA("AFMAmpL",
 646                        TWL6040_REG_MICLCTL, 1, 0, NULL, 0),
 647        SND_SOC_DAPM_PGA("AFMAmpR",
 648                        TWL6040_REG_MICRCTL, 1, 0, NULL, 0),
 649
 650        /* ADCs */
 651        SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0),
 652        SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0),
 653
 654        /* Microphone bias */
 655        SND_SOC_DAPM_SUPPLY("Headset Mic Bias",
 656                            TWL6040_REG_AMICBCTL, 0, 0, NULL, 0),
 657        SND_SOC_DAPM_SUPPLY("Main Mic Bias",
 658                            TWL6040_REG_AMICBCTL, 4, 0, NULL, 0),
 659        SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
 660                            TWL6040_REG_DMICBCTL, 0, 0, NULL, 0),
 661        SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
 662                            TWL6040_REG_DMICBCTL, 4, 0, NULL, 0),
 663
 664        /* DACs */
 665        SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0),
 666        SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0),
 667        SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0),
 668        SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0),
 669        /* Virtual DAC for vibra path (DL4 channel) */
 670        SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0),
 671
 672        SND_SOC_DAPM_MUX("Handsfree Left Playback",
 673                        SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
 674        SND_SOC_DAPM_MUX("Handsfree Right Playback",
 675                        SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
 676        /* Analog playback Muxes */
 677        SND_SOC_DAPM_MUX("Headset Left Playback",
 678                        SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
 679        SND_SOC_DAPM_MUX("Headset Right Playback",
 680                        SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
 681
 682        SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0,
 683                        &vibral_mux_controls),
 684        SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0,
 685                        &vibrar_mux_controls),
 686
 687        SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
 688                        &ep_path_enable_control),
 689        SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
 690                        &auxl_switch_control),
 691        SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0,
 692                        &auxr_switch_control),
 693
 694        /* Analog playback drivers */
 695        SND_SOC_DAPM_OUT_DRV("HF Left Driver",
 696                        TWL6040_REG_HFLCTL, 4, 0, NULL, 0),
 697        SND_SOC_DAPM_OUT_DRV("HF Right Driver",
 698                        TWL6040_REG_HFRCTL, 4, 0, NULL, 0),
 699        SND_SOC_DAPM_OUT_DRV("HS Left Driver",
 700                        TWL6040_REG_HSLCTL, 2, 0, NULL, 0),
 701        SND_SOC_DAPM_OUT_DRV("HS Right Driver",
 702                        TWL6040_REG_HSRCTL, 2, 0, NULL, 0),
 703        SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
 704                        TWL6040_REG_EARCTL, 0, 0, NULL, 0,
 705                        twl6040_ep_drv_event,
 706                        SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 707        SND_SOC_DAPM_OUT_DRV("Vibra Left Driver",
 708                        TWL6040_REG_VIBCTLL, 0, 0, NULL, 0),
 709        SND_SOC_DAPM_OUT_DRV("Vibra Right Driver",
 710                        TWL6040_REG_VIBCTLR, 0, 0, NULL, 0),
 711
 712        SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0,
 713                            NULL, 0),
 714        SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0,
 715                            NULL, 0),
 716        SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0,
 717                              twl6040_hs_dac_event,
 718                              SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 719
 720        /* Analog playback PGAs */
 721        SND_SOC_DAPM_PGA("HF Left PGA",
 722                        TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
 723        SND_SOC_DAPM_PGA("HF Right PGA",
 724                        TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
 725
 726};
 727
 728static const struct snd_soc_dapm_route intercon[] = {
 729        /* Stream -> DAC mapping */
 730        {"HSDAC Left", NULL, "Legacy Playback"},
 731        {"HSDAC Left", NULL, "Headset Playback"},
 732        {"HSDAC Right", NULL, "Legacy Playback"},
 733        {"HSDAC Right", NULL, "Headset Playback"},
 734
 735        {"HFDAC Left", NULL, "Legacy Playback"},
 736        {"HFDAC Left", NULL, "Handsfree Playback"},
 737        {"HFDAC Right", NULL, "Legacy Playback"},
 738        {"HFDAC Right", NULL, "Handsfree Playback"},
 739
 740        {"VIBRA DAC", NULL, "Legacy Playback"},
 741        {"VIBRA DAC", NULL, "Vibra Playback"},
 742
 743        /* ADC -> Stream mapping */
 744        {"Legacy Capture" , NULL, "ADC Left"},
 745        {"Capture", NULL, "ADC Left"},
 746        {"Legacy Capture", NULL, "ADC Right"},
 747        {"Capture" , NULL, "ADC Right"},
 748
 749        /* Capture path */
 750        {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
 751        {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
 752        {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
 753
 754        {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
 755        {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
 756        {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
 757
 758        {"MicAmpL", NULL, "Analog Left Capture Route"},
 759        {"MicAmpR", NULL, "Analog Right Capture Route"},
 760
 761        {"ADC Left", NULL, "MicAmpL"},
 762        {"ADC Right", NULL, "MicAmpR"},
 763
 764        /* AFM path */
 765        {"AFMAmpL", NULL, "AFML"},
 766        {"AFMAmpR", NULL, "AFMR"},
 767
 768        {"HSDAC Left", NULL, "HSDAC Power"},
 769        {"HSDAC Right", NULL, "HSDAC Power"},
 770
 771        {"Headset Left Playback", "HS DAC", "HSDAC Left"},
 772        {"Headset Left Playback", "Line-In amp", "AFMAmpL"},
 773
 774        {"Headset Right Playback", "HS DAC", "HSDAC Right"},
 775        {"Headset Right Playback", "Line-In amp", "AFMAmpR"},
 776
 777        {"HS Left Driver", NULL, "Headset Left Playback"},
 778        {"HS Right Driver", NULL, "Headset Right Playback"},
 779
 780        {"HSOL", NULL, "HS Left Driver"},
 781        {"HSOR", NULL, "HS Right Driver"},
 782
 783        /* Earphone playback path */
 784        {"Earphone Playback", "Switch", "HSDAC Left"},
 785        {"Earphone Driver", NULL, "Earphone Playback"},
 786        {"EP", NULL, "Earphone Driver"},
 787
 788        {"Handsfree Left Playback", "HF DAC", "HFDAC Left"},
 789        {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"},
 790
 791        {"Handsfree Right Playback", "HF DAC", "HFDAC Right"},
 792        {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"},
 793
 794        {"HF Left PGA", NULL, "Handsfree Left Playback"},
 795        {"HF Right PGA", NULL, "Handsfree Right Playback"},
 796
 797        {"HF Left Driver", NULL, "HF Left PGA"},
 798        {"HF Right Driver", NULL, "HF Right PGA"},
 799
 800        {"HFL", NULL, "HF Left Driver"},
 801        {"HFR", NULL, "HF Right Driver"},
 802
 803        {"AUXL Playback", "Switch", "HF Left PGA"},
 804        {"AUXR Playback", "Switch", "HF Right PGA"},
 805
 806        {"AUXL", NULL, "AUXL Playback"},
 807        {"AUXR", NULL, "AUXR Playback"},
 808
 809        /* Vibrator paths */
 810        {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"},
 811        {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"},
 812
 813        {"Vibra Left Driver", NULL, "Vibra Left Playback"},
 814        {"Vibra Right Driver", NULL, "Vibra Right Playback"},
 815        {"Vibra Left Driver", NULL, "Vibra Left Control"},
 816        {"Vibra Right Driver", NULL, "Vibra Right Control"},
 817
 818        {"VIBRAL", NULL, "Vibra Left Driver"},
 819        {"VIBRAR", NULL, "Vibra Right Driver"},
 820};
 821
 822static int twl6040_set_bias_level(struct snd_soc_codec *codec,
 823                                enum snd_soc_bias_level level)
 824{
 825        struct twl6040 *twl6040 = codec->control_data;
 826        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 827        int ret;
 828
 829        switch (level) {
 830        case SND_SOC_BIAS_ON:
 831                break;
 832        case SND_SOC_BIAS_PREPARE:
 833                break;
 834        case SND_SOC_BIAS_STANDBY:
 835                if (priv->codec_powered)
 836                        break;
 837
 838                ret = twl6040_power(twl6040, 1);
 839                if (ret)
 840                        return ret;
 841
 842                priv->codec_powered = 1;
 843
 844                /* Set external boost GPO */
 845                twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
 846                break;
 847        case SND_SOC_BIAS_OFF:
 848                if (!priv->codec_powered)
 849                        break;
 850
 851                twl6040_power(twl6040, 0);
 852                priv->codec_powered = 0;
 853                break;
 854        }
 855
 856        codec->dapm.bias_level = level;
 857
 858        return 0;
 859}
 860
 861static int twl6040_startup(struct snd_pcm_substream *substream,
 862                        struct snd_soc_dai *dai)
 863{
 864        struct snd_soc_codec *codec = dai->codec;
 865        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 866
 867        snd_pcm_hw_constraint_list(substream->runtime, 0,
 868                                SNDRV_PCM_HW_PARAM_RATE,
 869                                &sysclk_constraints[priv->pll_power_mode]);
 870
 871        return 0;
 872}
 873
 874static int twl6040_hw_params(struct snd_pcm_substream *substream,
 875                        struct snd_pcm_hw_params *params,
 876                        struct snd_soc_dai *dai)
 877{
 878        struct snd_soc_codec *codec = dai->codec;
 879        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 880        int rate;
 881
 882        rate = params_rate(params);
 883        switch (rate) {
 884        case 11250:
 885        case 22500:
 886        case 44100:
 887        case 88200:
 888                /* These rates are not supported when HPPLL is in use */
 889                if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) {
 890                        dev_err(codec->dev, "HPPLL does not support rate %d\n",
 891                                rate);
 892                        return -EINVAL;
 893                }
 894                priv->sysclk = 17640000;
 895                break;
 896        case 8000:
 897        case 16000:
 898        case 32000:
 899        case 48000:
 900        case 96000:
 901                priv->sysclk = 19200000;
 902                break;
 903        default:
 904                dev_err(codec->dev, "unsupported rate %d\n", rate);
 905                return -EINVAL;
 906        }
 907
 908        return 0;
 909}
 910
 911static int twl6040_prepare(struct snd_pcm_substream *substream,
 912                        struct snd_soc_dai *dai)
 913{
 914        struct snd_soc_codec *codec = dai->codec;
 915        struct twl6040 *twl6040 = codec->control_data;
 916        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 917        int ret;
 918
 919        if (!priv->sysclk) {
 920                dev_err(codec->dev,
 921                        "no mclk configured, call set_sysclk() on init\n");
 922                return -EINVAL;
 923        }
 924
 925        ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
 926        if (ret) {
 927                dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
 928                return -EPERM;
 929        }
 930
 931        return 0;
 932}
 933
 934static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 935                int clk_id, unsigned int freq, int dir)
 936{
 937        struct snd_soc_codec *codec = codec_dai->codec;
 938        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 939
 940        switch (clk_id) {
 941        case TWL6040_SYSCLK_SEL_LPPLL:
 942        case TWL6040_SYSCLK_SEL_HPPLL:
 943                priv->pll = clk_id;
 944                priv->clk_in = freq;
 945                break;
 946        default:
 947                dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
 948                return -EINVAL;
 949        }
 950
 951        return 0;
 952}
 953
 954static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id id,
 955                             int mute)
 956{
 957        struct twl6040 *twl6040 = codec->control_data;
 958        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 959        int hslctl, hsrctl, earctl;
 960        int hflctl, hfrctl;
 961
 962        switch (id) {
 963        case TWL6040_DAI_DL1:
 964                hslctl = twl6040_read(codec, TWL6040_REG_HSLCTL);
 965                hsrctl = twl6040_read(codec, TWL6040_REG_HSRCTL);
 966                earctl = twl6040_read(codec, TWL6040_REG_EARCTL);
 967
 968                if (mute) {
 969                        /* Power down drivers and DACs */
 970                        earctl &= ~0x01;
 971                        hslctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA);
 972                        hsrctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA);
 973
 974                }
 975
 976                twl6040_reg_write(twl6040, TWL6040_REG_EARCTL, earctl);
 977                twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl);
 978                twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl);
 979                priv->dl1_unmuted = !mute;
 980                break;
 981        case TWL6040_DAI_DL2:
 982                hflctl = twl6040_read(codec, TWL6040_REG_HFLCTL);
 983                hfrctl = twl6040_read(codec, TWL6040_REG_HFRCTL);
 984
 985                if (mute) {
 986                        /* Power down drivers and DACs */
 987                        hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA |
 988                                    TWL6040_HFDRVENA);
 989                        hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA |
 990                                    TWL6040_HFDRVENA);
 991                }
 992
 993                twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl);
 994                twl6040_reg_write(twl6040, TWL6040_REG_HFRCTL, hfrctl);
 995                priv->dl2_unmuted = !mute;
 996                break;
 997        default:
 998                break;
 999        }
1000}
1001
1002static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute)
1003{
1004        switch (dai->id) {
1005        case TWL6040_DAI_LEGACY:
1006                twl6040_mute_path(dai->codec, TWL6040_DAI_DL1, mute);
1007                twl6040_mute_path(dai->codec, TWL6040_DAI_DL2, mute);
1008                break;
1009        case TWL6040_DAI_DL1:
1010        case TWL6040_DAI_DL2:
1011                twl6040_mute_path(dai->codec, dai->id, mute);
1012                break;
1013        default:
1014                break;
1015        }
1016
1017        return 0;
1018}
1019
1020static const struct snd_soc_dai_ops twl6040_dai_ops = {
1021        .startup        = twl6040_startup,
1022        .hw_params      = twl6040_hw_params,
1023        .prepare        = twl6040_prepare,
1024        .set_sysclk     = twl6040_set_dai_sysclk,
1025        .digital_mute   = twl6040_digital_mute,
1026};
1027
1028static struct snd_soc_dai_driver twl6040_dai[] = {
1029{
1030        .name = "twl6040-legacy",
1031        .id = TWL6040_DAI_LEGACY,
1032        .playback = {
1033                .stream_name = "Legacy Playback",
1034                .channels_min = 1,
1035                .channels_max = 5,
1036                .rates = TWL6040_RATES,
1037                .formats = TWL6040_FORMATS,
1038        },
1039        .capture = {
1040                .stream_name = "Legacy Capture",
1041                .channels_min = 1,
1042                .channels_max = 2,
1043                .rates = TWL6040_RATES,
1044                .formats = TWL6040_FORMATS,
1045        },
1046        .ops = &twl6040_dai_ops,
1047},
1048{
1049        .name = "twl6040-ul",
1050        .id = TWL6040_DAI_UL,
1051        .capture = {
1052                .stream_name = "Capture",
1053                .channels_min = 1,
1054                .channels_max = 2,
1055                .rates = TWL6040_RATES,
1056                .formats = TWL6040_FORMATS,
1057        },
1058        .ops = &twl6040_dai_ops,
1059},
1060{
1061        .name = "twl6040-dl1",
1062        .id = TWL6040_DAI_DL1,
1063        .playback = {
1064                .stream_name = "Headset Playback",
1065                .channels_min = 1,
1066                .channels_max = 2,
1067                .rates = TWL6040_RATES,
1068                .formats = TWL6040_FORMATS,
1069        },
1070        .ops = &twl6040_dai_ops,
1071},
1072{
1073        .name = "twl6040-dl2",
1074        .id = TWL6040_DAI_DL2,
1075        .playback = {
1076                .stream_name = "Handsfree Playback",
1077                .channels_min = 1,
1078                .channels_max = 2,
1079                .rates = TWL6040_RATES,
1080                .formats = TWL6040_FORMATS,
1081        },
1082        .ops = &twl6040_dai_ops,
1083},
1084{
1085        .name = "twl6040-vib",
1086        .id = TWL6040_DAI_VIB,
1087        .playback = {
1088                .stream_name = "Vibra Playback",
1089                .channels_min = 1,
1090                .channels_max = 1,
1091                .rates = SNDRV_PCM_RATE_CONTINUOUS,
1092                .formats = TWL6040_FORMATS,
1093        },
1094        .ops = &twl6040_dai_ops,
1095},
1096};
1097
1098static int twl6040_probe(struct snd_soc_codec *codec)
1099{
1100        struct twl6040_data *priv;
1101        struct twl6040 *twl6040 = dev_get_drvdata(codec->dev->parent);
1102        struct platform_device *pdev = container_of(codec->dev,
1103                                                   struct platform_device, dev);
1104        int ret = 0;
1105
1106        priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL);
1107        if (priv == NULL)
1108                return -ENOMEM;
1109
1110        snd_soc_codec_set_drvdata(codec, priv);
1111
1112        priv->codec = codec;
1113        codec->control_data = twl6040;
1114
1115        priv->plug_irq = platform_get_irq(pdev, 0);
1116        if (priv->plug_irq < 0) {
1117                dev_err(codec->dev, "invalid irq\n");
1118                return -EINVAL;
1119        }
1120
1121        INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
1122
1123        mutex_init(&priv->mutex);
1124
1125        ret = request_threaded_irq(priv->plug_irq, NULL,
1126                                        twl6040_audio_handler, IRQF_NO_SUSPEND,
1127                                        "twl6040_irq_plug", codec);
1128        if (ret) {
1129                dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
1130                return ret;
1131        }
1132
1133        twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1134        twl6040_init_chip(codec);
1135
1136        return 0;
1137}
1138
1139static int twl6040_remove(struct snd_soc_codec *codec)
1140{
1141        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1142
1143        free_irq(priv->plug_irq, codec);
1144
1145        return 0;
1146}
1147
1148static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
1149        .probe = twl6040_probe,
1150        .remove = twl6040_remove,
1151        .read = twl6040_read,
1152        .write = twl6040_write,
1153        .set_bias_level = twl6040_set_bias_level,
1154        .suspend_bias_off = true,
1155        .ignore_pmdown_time = true,
1156
1157        .controls = twl6040_snd_controls,
1158        .num_controls = ARRAY_SIZE(twl6040_snd_controls),
1159        .dapm_widgets = twl6040_dapm_widgets,
1160        .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
1161        .dapm_routes = intercon,
1162        .num_dapm_routes = ARRAY_SIZE(intercon),
1163};
1164
1165static int twl6040_codec_probe(struct platform_device *pdev)
1166{
1167        return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040,
1168                                      twl6040_dai, ARRAY_SIZE(twl6040_dai));
1169}
1170
1171static int twl6040_codec_remove(struct platform_device *pdev)
1172{
1173        snd_soc_unregister_codec(&pdev->dev);
1174        return 0;
1175}
1176
1177static struct platform_driver twl6040_codec_driver = {
1178        .driver = {
1179                .name = "twl6040-codec",
1180        },
1181        .probe = twl6040_codec_probe,
1182        .remove = twl6040_codec_remove,
1183};
1184
1185module_platform_driver(twl6040_codec_driver);
1186
1187MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1188MODULE_AUTHOR("Misael Lopez Cruz");
1189MODULE_LICENSE("GPL");
1190