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