Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ALSA SoC TWL6040 codec driver
0004  *
0005  * Author:   Misael Lopez Cruz <x0052729@ti.com>
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/moduleparam.h>
0010 #include <linux/init.h>
0011 #include <linux/delay.h>
0012 #include <linux/pm.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/slab.h>
0015 #include <linux/mfd/twl6040.h>
0016 
0017 #include <sound/core.h>
0018 #include <sound/pcm.h>
0019 #include <sound/pcm_params.h>
0020 #include <sound/soc.h>
0021 #include <sound/soc-dapm.h>
0022 #include <sound/initval.h>
0023 #include <sound/tlv.h>
0024 
0025 #include "twl6040.h"
0026 
0027 enum twl6040_dai_id {
0028     TWL6040_DAI_LEGACY = 0,
0029     TWL6040_DAI_UL,
0030     TWL6040_DAI_DL1,
0031     TWL6040_DAI_DL2,
0032     TWL6040_DAI_VIB,
0033 };
0034 
0035 #define TWL6040_RATES       SNDRV_PCM_RATE_8000_96000
0036 #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
0037 
0038 #define TWL6040_OUTHS_0dB 0x00
0039 #define TWL6040_OUTHS_M30dB 0x0F
0040 #define TWL6040_OUTHF_0dB 0x03
0041 #define TWL6040_OUTHF_M52dB 0x1D
0042 
0043 #define TWL6040_CACHEREGNUM (TWL6040_REG_STATUS + 1)
0044 
0045 struct twl6040_jack_data {
0046     struct snd_soc_jack *jack;
0047     struct delayed_work work;
0048     int report;
0049 };
0050 
0051 /* codec private data */
0052 struct twl6040_data {
0053     int plug_irq;
0054     int codec_powered;
0055     int pll;
0056     int pll_power_mode;
0057     int hs_power_mode;
0058     int hs_power_mode_locked;
0059     bool dl1_unmuted;
0060     bool dl2_unmuted;
0061     u8 dl12_cache[TWL6040_REG_HFRCTL - TWL6040_REG_HSLCTL + 1];
0062     unsigned int clk_in;
0063     unsigned int sysclk;
0064     struct twl6040_jack_data hs_jack;
0065     struct snd_soc_component *component;
0066     struct mutex mutex;
0067 };
0068 
0069 /* set of rates for each pll: low-power and high-performance */
0070 static const unsigned int lp_rates[] = {
0071     8000,
0072     11250,
0073     16000,
0074     22500,
0075     32000,
0076     44100,
0077     48000,
0078     88200,
0079     96000,
0080 };
0081 
0082 static const unsigned int hp_rates[] = {
0083     8000,
0084     16000,
0085     32000,
0086     48000,
0087     96000,
0088 };
0089 
0090 static const struct snd_pcm_hw_constraint_list sysclk_constraints[] = {
0091     { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, },
0092     { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, },
0093 };
0094 
0095 #define to_twl6040(component)   dev_get_drvdata((component)->dev->parent)
0096 
0097 static unsigned int twl6040_read(struct snd_soc_component *component, unsigned int reg)
0098 {
0099     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0100     struct twl6040 *twl6040 = to_twl6040(component);
0101     u8 value;
0102 
0103     if (reg >= TWL6040_CACHEREGNUM)
0104         return -EIO;
0105 
0106     switch (reg) {
0107     case TWL6040_REG_HSLCTL:
0108     case TWL6040_REG_HSRCTL:
0109     case TWL6040_REG_EARCTL:
0110     case TWL6040_REG_HFLCTL:
0111     case TWL6040_REG_HFRCTL:
0112         value = priv->dl12_cache[reg - TWL6040_REG_HSLCTL];
0113         break;
0114     default:
0115         value = twl6040_reg_read(twl6040, reg);
0116         break;
0117     }
0118 
0119     return value;
0120 }
0121 
0122 static bool twl6040_can_write_to_chip(struct snd_soc_component *component,
0123                   unsigned int reg)
0124 {
0125     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0126 
0127     switch (reg) {
0128     case TWL6040_REG_HSLCTL:
0129     case TWL6040_REG_HSRCTL:
0130     case TWL6040_REG_EARCTL:
0131         /* DL1 path */
0132         return priv->dl1_unmuted;
0133     case TWL6040_REG_HFLCTL:
0134     case TWL6040_REG_HFRCTL:
0135         return priv->dl2_unmuted;
0136     default:
0137         return true;
0138     }
0139 }
0140 
0141 static inline void twl6040_update_dl12_cache(struct snd_soc_component *component,
0142                          u8 reg, u8 value)
0143 {
0144     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0145 
0146     switch (reg) {
0147     case TWL6040_REG_HSLCTL:
0148     case TWL6040_REG_HSRCTL:
0149     case TWL6040_REG_EARCTL:
0150     case TWL6040_REG_HFLCTL:
0151     case TWL6040_REG_HFRCTL:
0152         priv->dl12_cache[reg - TWL6040_REG_HSLCTL] = value;
0153         break;
0154     default:
0155         break;
0156     }
0157 }
0158 
0159 static int twl6040_write(struct snd_soc_component *component,
0160             unsigned int reg, unsigned int value)
0161 {
0162     struct twl6040 *twl6040 = to_twl6040(component);
0163 
0164     if (reg >= TWL6040_CACHEREGNUM)
0165         return -EIO;
0166 
0167     twl6040_update_dl12_cache(component, reg, value);
0168     if (twl6040_can_write_to_chip(component, reg))
0169         return twl6040_reg_write(twl6040, reg, value);
0170     else
0171         return 0;
0172 }
0173 
0174 static void twl6040_init_chip(struct snd_soc_component *component)
0175 {
0176     twl6040_read(component, TWL6040_REG_TRIM1);
0177     twl6040_read(component, TWL6040_REG_TRIM2);
0178     twl6040_read(component, TWL6040_REG_TRIM3);
0179     twl6040_read(component, TWL6040_REG_HSOTRIM);
0180     twl6040_read(component, TWL6040_REG_HFOTRIM);
0181 
0182     /* Change chip defaults */
0183     /* No imput selected for microphone amplifiers */
0184     twl6040_write(component, TWL6040_REG_MICLCTL, 0x18);
0185     twl6040_write(component, TWL6040_REG_MICRCTL, 0x18);
0186 
0187     /*
0188      * We need to lower the default gain values, so the ramp code
0189      * can work correctly for the first playback.
0190      * This reduces the pop noise heard at the first playback.
0191      */
0192     twl6040_write(component, TWL6040_REG_HSGAIN, 0xff);
0193     twl6040_write(component, TWL6040_REG_EARCTL, 0x1e);
0194     twl6040_write(component, TWL6040_REG_HFLGAIN, 0x1d);
0195     twl6040_write(component, TWL6040_REG_HFRGAIN, 0x1d);
0196     twl6040_write(component, TWL6040_REG_LINEGAIN, 0);
0197 }
0198 
0199 /* set headset dac and driver power mode */
0200 static int headset_power_mode(struct snd_soc_component *component, int high_perf)
0201 {
0202     int hslctl, hsrctl;
0203     int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
0204 
0205     hslctl = twl6040_read(component, TWL6040_REG_HSLCTL);
0206     hsrctl = twl6040_read(component, TWL6040_REG_HSRCTL);
0207 
0208     if (high_perf) {
0209         hslctl &= ~mask;
0210         hsrctl &= ~mask;
0211     } else {
0212         hslctl |= mask;
0213         hsrctl |= mask;
0214     }
0215 
0216     twl6040_write(component, TWL6040_REG_HSLCTL, hslctl);
0217     twl6040_write(component, TWL6040_REG_HSRCTL, hsrctl);
0218 
0219     return 0;
0220 }
0221 
0222 static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
0223             struct snd_kcontrol *kcontrol, int event)
0224 {
0225     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0226     u8 hslctl, hsrctl;
0227 
0228     /*
0229      * Workaround for Headset DC offset caused pop noise:
0230      * Both HS DAC need to be turned on (before the HS driver) and off at
0231      * the same time.
0232      */
0233     hslctl = twl6040_read(component, TWL6040_REG_HSLCTL);
0234     hsrctl = twl6040_read(component, TWL6040_REG_HSRCTL);
0235     if (SND_SOC_DAPM_EVENT_ON(event)) {
0236         hslctl |= TWL6040_HSDACENA;
0237         hsrctl |= TWL6040_HSDACENA;
0238     } else {
0239         hslctl &= ~TWL6040_HSDACENA;
0240         hsrctl &= ~TWL6040_HSDACENA;
0241     }
0242     twl6040_write(component, TWL6040_REG_HSLCTL, hslctl);
0243     twl6040_write(component, TWL6040_REG_HSRCTL, hsrctl);
0244 
0245     msleep(1);
0246     return 0;
0247 }
0248 
0249 static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w,
0250             struct snd_kcontrol *kcontrol, int event)
0251 {
0252     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0253     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0254     int ret = 0;
0255 
0256     if (SND_SOC_DAPM_EVENT_ON(event)) {
0257         /* Earphone doesn't support low power mode */
0258         priv->hs_power_mode_locked = 1;
0259         ret = headset_power_mode(component, 1);
0260     } else {
0261         priv->hs_power_mode_locked = 0;
0262         ret = headset_power_mode(component, priv->hs_power_mode);
0263     }
0264 
0265     msleep(1);
0266 
0267     return ret;
0268 }
0269 
0270 static void twl6040_hs_jack_report(struct snd_soc_component *component,
0271                    struct snd_soc_jack *jack, int report)
0272 {
0273     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0274     int status;
0275 
0276     mutex_lock(&priv->mutex);
0277 
0278     /* Sync status */
0279     status = twl6040_read(component, TWL6040_REG_STATUS);
0280     if (status & TWL6040_PLUGCOMP)
0281         snd_soc_jack_report(jack, report, report);
0282     else
0283         snd_soc_jack_report(jack, 0, report);
0284 
0285     mutex_unlock(&priv->mutex);
0286 }
0287 
0288 void twl6040_hs_jack_detect(struct snd_soc_component *component,
0289                 struct snd_soc_jack *jack, int report)
0290 {
0291     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0292     struct twl6040_jack_data *hs_jack = &priv->hs_jack;
0293 
0294     hs_jack->jack = jack;
0295     hs_jack->report = report;
0296 
0297     twl6040_hs_jack_report(component, hs_jack->jack, hs_jack->report);
0298 }
0299 EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
0300 
0301 static void twl6040_accessory_work(struct work_struct *work)
0302 {
0303     struct twl6040_data *priv = container_of(work,
0304                     struct twl6040_data, hs_jack.work.work);
0305     struct snd_soc_component *component = priv->component;
0306     struct twl6040_jack_data *hs_jack = &priv->hs_jack;
0307 
0308     twl6040_hs_jack_report(component, hs_jack->jack, hs_jack->report);
0309 }
0310 
0311 /* audio interrupt handler */
0312 static irqreturn_t twl6040_audio_handler(int irq, void *data)
0313 {
0314     struct snd_soc_component *component = data;
0315     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0316 
0317     queue_delayed_work(system_power_efficient_wq,
0318                &priv->hs_jack.work, msecs_to_jiffies(200));
0319 
0320     return IRQ_HANDLED;
0321 }
0322 
0323 static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
0324     struct snd_ctl_elem_value *ucontrol)
0325 {
0326     struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
0327     struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
0328     unsigned int val;
0329 
0330     /* Do not allow changes while Input/FF efect is running */
0331     val = twl6040_read(component, e->reg);
0332     if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
0333         return -EBUSY;
0334 
0335     return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
0336 }
0337 
0338 /*
0339  * MICATT volume control:
0340  * from -6 to 0 dB in 6 dB steps
0341  */
0342 static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0);
0343 
0344 /*
0345  * MICGAIN volume control:
0346  * from 6 to 30 dB in 6 dB steps
0347  */
0348 static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0);
0349 
0350 /*
0351  * AFMGAIN volume control:
0352  * from -18 to 24 dB in 6 dB steps
0353  */
0354 static DECLARE_TLV_DB_SCALE(afm_amp_tlv, -1800, 600, 0);
0355 
0356 /*
0357  * HSGAIN volume control:
0358  * from -30 to 0 dB in 2 dB steps
0359  */
0360 static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
0361 
0362 /*
0363  * HFGAIN volume control:
0364  * from -52 to 6 dB in 2 dB steps
0365  */
0366 static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
0367 
0368 /*
0369  * EPGAIN volume control:
0370  * from -24 to 6 dB in 2 dB steps
0371  */
0372 static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0);
0373 
0374 /* Left analog microphone selection */
0375 static const char *twl6040_amicl_texts[] =
0376     {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
0377 
0378 /* Right analog microphone selection */
0379 static const char *twl6040_amicr_texts[] =
0380     {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"};
0381 
0382 static const struct soc_enum twl6040_enum[] = {
0383     SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3,
0384             ARRAY_SIZE(twl6040_amicl_texts), twl6040_amicl_texts),
0385     SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3,
0386             ARRAY_SIZE(twl6040_amicr_texts), twl6040_amicr_texts),
0387 };
0388 
0389 static const char *twl6040_hs_texts[] = {
0390     "Off", "HS DAC", "Line-In amp"
0391 };
0392 
0393 static const struct soc_enum twl6040_hs_enum[] = {
0394     SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
0395             twl6040_hs_texts),
0396     SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL, 5, ARRAY_SIZE(twl6040_hs_texts),
0397             twl6040_hs_texts),
0398 };
0399 
0400 static const char *twl6040_hf_texts[] = {
0401     "Off", "HF DAC", "Line-In amp"
0402 };
0403 
0404 static const struct soc_enum twl6040_hf_enum[] = {
0405     SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
0406             twl6040_hf_texts),
0407     SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL, 2, ARRAY_SIZE(twl6040_hf_texts),
0408             twl6040_hf_texts),
0409 };
0410 
0411 static const char *twl6040_vibrapath_texts[] = {
0412     "Input FF", "Audio PDM"
0413 };
0414 
0415 static const struct soc_enum twl6040_vibra_enum[] = {
0416     SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1,
0417             ARRAY_SIZE(twl6040_vibrapath_texts),
0418             twl6040_vibrapath_texts),
0419     SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1,
0420             ARRAY_SIZE(twl6040_vibrapath_texts),
0421             twl6040_vibrapath_texts),
0422 };
0423 
0424 static const struct snd_kcontrol_new amicl_control =
0425     SOC_DAPM_ENUM("Route", twl6040_enum[0]);
0426 
0427 static const struct snd_kcontrol_new amicr_control =
0428     SOC_DAPM_ENUM("Route", twl6040_enum[1]);
0429 
0430 /* Headset DAC playback switches */
0431 static const struct snd_kcontrol_new hsl_mux_controls =
0432     SOC_DAPM_ENUM("Route", twl6040_hs_enum[0]);
0433 
0434 static const struct snd_kcontrol_new hsr_mux_controls =
0435     SOC_DAPM_ENUM("Route", twl6040_hs_enum[1]);
0436 
0437 /* Handsfree DAC playback switches */
0438 static const struct snd_kcontrol_new hfl_mux_controls =
0439     SOC_DAPM_ENUM("Route", twl6040_hf_enum[0]);
0440 
0441 static const struct snd_kcontrol_new hfr_mux_controls =
0442     SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
0443 
0444 static const struct snd_kcontrol_new ep_path_enable_control =
0445     SOC_DAPM_SINGLE_VIRT("Switch", 1);
0446 
0447 static const struct snd_kcontrol_new auxl_switch_control =
0448     SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
0449 
0450 static const struct snd_kcontrol_new auxr_switch_control =
0451     SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
0452 
0453 /* Vibra playback switches */
0454 static const struct snd_kcontrol_new vibral_mux_controls =
0455     SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0],
0456         snd_soc_dapm_get_enum_double,
0457         twl6040_soc_dapm_put_vibra_enum);
0458 
0459 static const struct snd_kcontrol_new vibrar_mux_controls =
0460     SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1],
0461         snd_soc_dapm_get_enum_double,
0462         twl6040_soc_dapm_put_vibra_enum);
0463 
0464 /* Headset power mode */
0465 static const char *twl6040_power_mode_texts[] = {
0466     "Low-Power", "High-Performance",
0467 };
0468 
0469 static SOC_ENUM_SINGLE_EXT_DECL(twl6040_power_mode_enum,
0470                 twl6040_power_mode_texts);
0471 
0472 static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol,
0473     struct snd_ctl_elem_value *ucontrol)
0474 {
0475     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0476     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0477 
0478     ucontrol->value.enumerated.item[0] = priv->hs_power_mode;
0479 
0480     return 0;
0481 }
0482 
0483 static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol,
0484     struct snd_ctl_elem_value *ucontrol)
0485 {
0486     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0487     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0488     int high_perf = ucontrol->value.enumerated.item[0];
0489     int ret = 0;
0490 
0491     if (!priv->hs_power_mode_locked)
0492         ret = headset_power_mode(component, high_perf);
0493 
0494     if (!ret)
0495         priv->hs_power_mode = high_perf;
0496 
0497     return ret;
0498 }
0499 
0500 static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol,
0501     struct snd_ctl_elem_value *ucontrol)
0502 {
0503     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0504     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0505 
0506     ucontrol->value.enumerated.item[0] = priv->pll_power_mode;
0507 
0508     return 0;
0509 }
0510 
0511 static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
0512     struct snd_ctl_elem_value *ucontrol)
0513 {
0514     struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
0515     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0516 
0517     priv->pll_power_mode = ucontrol->value.enumerated.item[0];
0518 
0519     return 0;
0520 }
0521 
0522 int twl6040_get_dl1_gain(struct snd_soc_component *component)
0523 {
0524     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
0525 
0526     if (snd_soc_dapm_get_pin_status(dapm, "EP"))
0527         return -1; /* -1dB */
0528 
0529     if (snd_soc_dapm_get_pin_status(dapm, "HSOR") ||
0530         snd_soc_dapm_get_pin_status(dapm, "HSOL")) {
0531 
0532         u8 val = twl6040_read(component, TWL6040_REG_HSLCTL);
0533         if (val & TWL6040_HSDACMODE)
0534             /* HSDACL in LP mode */
0535             return -8; /* -8dB */
0536         else
0537             /* HSDACL in HP mode */
0538             return -1; /* -1dB */
0539     }
0540     return 0; /* 0dB */
0541 }
0542 EXPORT_SYMBOL_GPL(twl6040_get_dl1_gain);
0543 
0544 int twl6040_get_clk_id(struct snd_soc_component *component)
0545 {
0546     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0547 
0548     return priv->pll_power_mode;
0549 }
0550 EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
0551 
0552 int twl6040_get_trim_value(struct snd_soc_component *component, enum twl6040_trim trim)
0553 {
0554     if (unlikely(trim >= TWL6040_TRIM_INVAL))
0555         return -EINVAL;
0556 
0557     return twl6040_read(component, TWL6040_REG_TRIM1 + trim);
0558 }
0559 EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
0560 
0561 int twl6040_get_hs_step_size(struct snd_soc_component *component)
0562 {
0563     struct twl6040 *twl6040 = to_twl6040(component);
0564 
0565     if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_3)
0566         /* For ES under ES_1.3 HS step is 2 mV */
0567         return 2;
0568     else
0569         /* For ES_1.3 HS step is 1 mV */
0570         return 1;
0571 }
0572 EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size);
0573 
0574 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
0575     /* Capture gains */
0576     SOC_DOUBLE_TLV("Capture Preamplifier Volume",
0577         TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv),
0578     SOC_DOUBLE_TLV("Capture Volume",
0579         TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv),
0580 
0581     /* AFM gains */
0582     SOC_DOUBLE_TLV("Aux FM Volume",
0583         TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
0584 
0585     /* Playback gains */
0586     SOC_DOUBLE_TLV("Headset Playback Volume",
0587         TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
0588     SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
0589         TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
0590     SOC_SINGLE_TLV("Earphone Playback Volume",
0591         TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
0592 
0593     SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum,
0594         twl6040_headset_power_get_enum,
0595         twl6040_headset_power_put_enum),
0596 
0597     /* Left HS PDM data routed to Right HSDAC */
0598     SOC_SINGLE("Headset Mono to Stereo Playback Switch",
0599         TWL6040_REG_HSRCTL, 7, 1, 0),
0600 
0601     /* Left HF PDM data routed to Right HFDAC */
0602     SOC_SINGLE("Handsfree Mono to Stereo Playback Switch",
0603         TWL6040_REG_HFRCTL, 5, 1, 0),
0604 
0605     SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum,
0606         twl6040_pll_get_enum, twl6040_pll_put_enum),
0607 };
0608 
0609 static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
0610     /* Inputs */
0611     SND_SOC_DAPM_INPUT("MAINMIC"),
0612     SND_SOC_DAPM_INPUT("HSMIC"),
0613     SND_SOC_DAPM_INPUT("SUBMIC"),
0614     SND_SOC_DAPM_INPUT("AFML"),
0615     SND_SOC_DAPM_INPUT("AFMR"),
0616 
0617     /* Outputs */
0618     SND_SOC_DAPM_OUTPUT("HSOL"),
0619     SND_SOC_DAPM_OUTPUT("HSOR"),
0620     SND_SOC_DAPM_OUTPUT("HFL"),
0621     SND_SOC_DAPM_OUTPUT("HFR"),
0622     SND_SOC_DAPM_OUTPUT("EP"),
0623     SND_SOC_DAPM_OUTPUT("AUXL"),
0624     SND_SOC_DAPM_OUTPUT("AUXR"),
0625     SND_SOC_DAPM_OUTPUT("VIBRAL"),
0626     SND_SOC_DAPM_OUTPUT("VIBRAR"),
0627 
0628     /* Analog input muxes for the capture amplifiers */
0629     SND_SOC_DAPM_MUX("Analog Left Capture Route",
0630             SND_SOC_NOPM, 0, 0, &amicl_control),
0631     SND_SOC_DAPM_MUX("Analog Right Capture Route",
0632             SND_SOC_NOPM, 0, 0, &amicr_control),
0633 
0634     /* Analog capture PGAs */
0635     SND_SOC_DAPM_PGA("MicAmpL",
0636             TWL6040_REG_MICLCTL, 0, 0, NULL, 0),
0637     SND_SOC_DAPM_PGA("MicAmpR",
0638             TWL6040_REG_MICRCTL, 0, 0, NULL, 0),
0639 
0640     /* Auxiliary FM PGAs */
0641     SND_SOC_DAPM_PGA("AFMAmpL",
0642             TWL6040_REG_MICLCTL, 1, 0, NULL, 0),
0643     SND_SOC_DAPM_PGA("AFMAmpR",
0644             TWL6040_REG_MICRCTL, 1, 0, NULL, 0),
0645 
0646     /* ADCs */
0647     SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0),
0648     SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0),
0649 
0650     /* Microphone bias */
0651     SND_SOC_DAPM_SUPPLY("Headset Mic Bias",
0652                 TWL6040_REG_AMICBCTL, 0, 0, NULL, 0),
0653     SND_SOC_DAPM_SUPPLY("Main Mic Bias",
0654                 TWL6040_REG_AMICBCTL, 4, 0, NULL, 0),
0655     SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
0656                 TWL6040_REG_DMICBCTL, 0, 0, NULL, 0),
0657     SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
0658                 TWL6040_REG_DMICBCTL, 4, 0, NULL, 0),
0659 
0660     /* DACs */
0661     SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0),
0662     SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0),
0663     SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0),
0664     SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0),
0665     /* Virtual DAC for vibra path (DL4 channel) */
0666     SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0),
0667 
0668     SND_SOC_DAPM_MUX("Handsfree Left Playback",
0669             SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
0670     SND_SOC_DAPM_MUX("Handsfree Right Playback",
0671             SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
0672     /* Analog playback Muxes */
0673     SND_SOC_DAPM_MUX("Headset Left Playback",
0674             SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
0675     SND_SOC_DAPM_MUX("Headset Right Playback",
0676             SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
0677 
0678     SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0,
0679             &vibral_mux_controls),
0680     SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0,
0681             &vibrar_mux_controls),
0682 
0683     SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
0684             &ep_path_enable_control),
0685     SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
0686             &auxl_switch_control),
0687     SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0,
0688             &auxr_switch_control),
0689 
0690     /* Analog playback drivers */
0691     SND_SOC_DAPM_OUT_DRV("HF Left Driver",
0692             TWL6040_REG_HFLCTL, 4, 0, NULL, 0),
0693     SND_SOC_DAPM_OUT_DRV("HF Right Driver",
0694             TWL6040_REG_HFRCTL, 4, 0, NULL, 0),
0695     SND_SOC_DAPM_OUT_DRV("HS Left Driver",
0696             TWL6040_REG_HSLCTL, 2, 0, NULL, 0),
0697     SND_SOC_DAPM_OUT_DRV("HS Right Driver",
0698             TWL6040_REG_HSRCTL, 2, 0, NULL, 0),
0699     SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
0700             TWL6040_REG_EARCTL, 0, 0, NULL, 0,
0701             twl6040_ep_drv_event,
0702             SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0703     SND_SOC_DAPM_OUT_DRV("Vibra Left Driver",
0704             TWL6040_REG_VIBCTLL, 0, 0, NULL, 0),
0705     SND_SOC_DAPM_OUT_DRV("Vibra Right Driver",
0706             TWL6040_REG_VIBCTLR, 0, 0, NULL, 0),
0707 
0708     SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0,
0709                 NULL, 0),
0710     SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0,
0711                 NULL, 0),
0712     SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0,
0713                   twl6040_hs_dac_event,
0714                   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
0715 
0716     /* Analog playback PGAs */
0717     SND_SOC_DAPM_PGA("HF Left PGA",
0718             TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
0719     SND_SOC_DAPM_PGA("HF Right PGA",
0720             TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
0721 
0722 };
0723 
0724 static const struct snd_soc_dapm_route intercon[] = {
0725     /* Stream -> DAC mapping */
0726     {"HSDAC Left", NULL, "Legacy Playback"},
0727     {"HSDAC Left", NULL, "Headset Playback"},
0728     {"HSDAC Right", NULL, "Legacy Playback"},
0729     {"HSDAC Right", NULL, "Headset Playback"},
0730 
0731     {"HFDAC Left", NULL, "Legacy Playback"},
0732     {"HFDAC Left", NULL, "Handsfree Playback"},
0733     {"HFDAC Right", NULL, "Legacy Playback"},
0734     {"HFDAC Right", NULL, "Handsfree Playback"},
0735 
0736     {"VIBRA DAC", NULL, "Legacy Playback"},
0737     {"VIBRA DAC", NULL, "Vibra Playback"},
0738 
0739     /* ADC -> Stream mapping */
0740     {"Legacy Capture" , NULL, "ADC Left"},
0741     {"Capture", NULL, "ADC Left"},
0742     {"Legacy Capture", NULL, "ADC Right"},
0743     {"Capture" , NULL, "ADC Right"},
0744 
0745     /* Capture path */
0746     {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
0747     {"Analog Left Capture Route", "Main Mic", "MAINMIC"},
0748     {"Analog Left Capture Route", "Aux/FM Left", "AFML"},
0749 
0750     {"Analog Right Capture Route", "Headset Mic", "HSMIC"},
0751     {"Analog Right Capture Route", "Sub Mic", "SUBMIC"},
0752     {"Analog Right Capture Route", "Aux/FM Right", "AFMR"},
0753 
0754     {"MicAmpL", NULL, "Analog Left Capture Route"},
0755     {"MicAmpR", NULL, "Analog Right Capture Route"},
0756 
0757     {"ADC Left", NULL, "MicAmpL"},
0758     {"ADC Right", NULL, "MicAmpR"},
0759 
0760     /* AFM path */
0761     {"AFMAmpL", NULL, "AFML"},
0762     {"AFMAmpR", NULL, "AFMR"},
0763 
0764     {"HSDAC Left", NULL, "HSDAC Power"},
0765     {"HSDAC Right", NULL, "HSDAC Power"},
0766 
0767     {"Headset Left Playback", "HS DAC", "HSDAC Left"},
0768     {"Headset Left Playback", "Line-In amp", "AFMAmpL"},
0769 
0770     {"Headset Right Playback", "HS DAC", "HSDAC Right"},
0771     {"Headset Right Playback", "Line-In amp", "AFMAmpR"},
0772 
0773     {"HS Left Driver", NULL, "Headset Left Playback"},
0774     {"HS Right Driver", NULL, "Headset Right Playback"},
0775 
0776     {"HSOL", NULL, "HS Left Driver"},
0777     {"HSOR", NULL, "HS Right Driver"},
0778 
0779     /* Earphone playback path */
0780     {"Earphone Playback", "Switch", "HSDAC Left"},
0781     {"Earphone Driver", NULL, "Earphone Playback"},
0782     {"EP", NULL, "Earphone Driver"},
0783 
0784     {"Handsfree Left Playback", "HF DAC", "HFDAC Left"},
0785     {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"},
0786 
0787     {"Handsfree Right Playback", "HF DAC", "HFDAC Right"},
0788     {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"},
0789 
0790     {"HF Left PGA", NULL, "Handsfree Left Playback"},
0791     {"HF Right PGA", NULL, "Handsfree Right Playback"},
0792 
0793     {"HF Left Driver", NULL, "HF Left PGA"},
0794     {"HF Right Driver", NULL, "HF Right PGA"},
0795 
0796     {"HFL", NULL, "HF Left Driver"},
0797     {"HFR", NULL, "HF Right Driver"},
0798 
0799     {"AUXL Playback", "Switch", "HF Left PGA"},
0800     {"AUXR Playback", "Switch", "HF Right PGA"},
0801 
0802     {"AUXL", NULL, "AUXL Playback"},
0803     {"AUXR", NULL, "AUXR Playback"},
0804 
0805     /* Vibrator paths */
0806     {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"},
0807     {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"},
0808 
0809     {"Vibra Left Driver", NULL, "Vibra Left Playback"},
0810     {"Vibra Right Driver", NULL, "Vibra Right Playback"},
0811     {"Vibra Left Driver", NULL, "Vibra Left Control"},
0812     {"Vibra Right Driver", NULL, "Vibra Right Control"},
0813 
0814     {"VIBRAL", NULL, "Vibra Left Driver"},
0815     {"VIBRAR", NULL, "Vibra Right Driver"},
0816 };
0817 
0818 static int twl6040_set_bias_level(struct snd_soc_component *component,
0819                 enum snd_soc_bias_level level)
0820 {
0821     struct twl6040 *twl6040 = to_twl6040(component);
0822     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0823     int ret = 0;
0824 
0825     switch (level) {
0826     case SND_SOC_BIAS_ON:
0827         break;
0828     case SND_SOC_BIAS_PREPARE:
0829         break;
0830     case SND_SOC_BIAS_STANDBY:
0831         if (priv->codec_powered) {
0832             /* Select low power PLL in standby */
0833             ret = twl6040_set_pll(twl6040, TWL6040_SYSCLK_SEL_LPPLL,
0834                           32768, 19200000);
0835             break;
0836         }
0837 
0838         ret = twl6040_power(twl6040, 1);
0839         if (ret)
0840             break;
0841 
0842         priv->codec_powered = 1;
0843 
0844         /* Set external boost GPO */
0845         twl6040_write(component, TWL6040_REG_GPOCTL, 0x02);
0846         break;
0847     case SND_SOC_BIAS_OFF:
0848         if (!priv->codec_powered)
0849             break;
0850 
0851         twl6040_power(twl6040, 0);
0852         priv->codec_powered = 0;
0853         break;
0854     }
0855 
0856     return ret;
0857 }
0858 
0859 static int twl6040_startup(struct snd_pcm_substream *substream,
0860             struct snd_soc_dai *dai)
0861 {
0862     struct snd_soc_component *component = dai->component;
0863     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0864 
0865     snd_pcm_hw_constraint_list(substream->runtime, 0,
0866                 SNDRV_PCM_HW_PARAM_RATE,
0867                 &sysclk_constraints[priv->pll_power_mode]);
0868 
0869     return 0;
0870 }
0871 
0872 static int twl6040_hw_params(struct snd_pcm_substream *substream,
0873             struct snd_pcm_hw_params *params,
0874             struct snd_soc_dai *dai)
0875 {
0876     struct snd_soc_component *component = dai->component;
0877     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0878     int rate;
0879 
0880     rate = params_rate(params);
0881     switch (rate) {
0882     case 11250:
0883     case 22500:
0884     case 44100:
0885     case 88200:
0886         /* These rates are not supported when HPPLL is in use */
0887         if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) {
0888             dev_err(component->dev, "HPPLL does not support rate %d\n",
0889                 rate);
0890             return -EINVAL;
0891         }
0892         priv->sysclk = 17640000;
0893         break;
0894     case 8000:
0895     case 16000:
0896     case 32000:
0897     case 48000:
0898     case 96000:
0899         priv->sysclk = 19200000;
0900         break;
0901     default:
0902         dev_err(component->dev, "unsupported rate %d\n", rate);
0903         return -EINVAL;
0904     }
0905 
0906     return 0;
0907 }
0908 
0909 static int twl6040_prepare(struct snd_pcm_substream *substream,
0910             struct snd_soc_dai *dai)
0911 {
0912     struct snd_soc_component *component = dai->component;
0913     struct twl6040 *twl6040 = to_twl6040(component);
0914     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0915     int ret;
0916 
0917     if (!priv->sysclk) {
0918         dev_err(component->dev,
0919             "no mclk configured, call set_sysclk() on init\n");
0920         return -EINVAL;
0921     }
0922 
0923     ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
0924     if (ret) {
0925         dev_err(component->dev, "Can not set PLL (%d)\n", ret);
0926         return -EPERM;
0927     }
0928 
0929     return 0;
0930 }
0931 
0932 static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0933         int clk_id, unsigned int freq, int dir)
0934 {
0935     struct snd_soc_component *component = codec_dai->component;
0936     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0937 
0938     switch (clk_id) {
0939     case TWL6040_SYSCLK_SEL_LPPLL:
0940     case TWL6040_SYSCLK_SEL_HPPLL:
0941         priv->pll = clk_id;
0942         priv->clk_in = freq;
0943         break;
0944     default:
0945         dev_err(component->dev, "unknown clk_id %d\n", clk_id);
0946         return -EINVAL;
0947     }
0948 
0949     return 0;
0950 }
0951 
0952 static void twl6040_mute_path(struct snd_soc_component *component, enum twl6040_dai_id id,
0953                  int mute)
0954 {
0955     struct twl6040 *twl6040 = to_twl6040(component);
0956     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
0957     int hslctl, hsrctl, earctl;
0958     int hflctl, hfrctl;
0959 
0960     switch (id) {
0961     case TWL6040_DAI_DL1:
0962         hslctl = twl6040_read(component, TWL6040_REG_HSLCTL);
0963         hsrctl = twl6040_read(component, TWL6040_REG_HSRCTL);
0964         earctl = twl6040_read(component, TWL6040_REG_EARCTL);
0965 
0966         if (mute) {
0967             /* Power down drivers and DACs */
0968             earctl &= ~0x01;
0969             hslctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA);
0970             hsrctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA);
0971 
0972         }
0973 
0974         twl6040_reg_write(twl6040, TWL6040_REG_EARCTL, earctl);
0975         twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl);
0976         twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl);
0977         priv->dl1_unmuted = !mute;
0978         break;
0979     case TWL6040_DAI_DL2:
0980         hflctl = twl6040_read(component, TWL6040_REG_HFLCTL);
0981         hfrctl = twl6040_read(component, TWL6040_REG_HFRCTL);
0982 
0983         if (mute) {
0984             /* Power down drivers and DACs */
0985             hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA |
0986                     TWL6040_HFDRVENA | TWL6040_HFSWENA);
0987             hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA |
0988                     TWL6040_HFDRVENA | TWL6040_HFSWENA);
0989         }
0990 
0991         twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl);
0992         twl6040_reg_write(twl6040, TWL6040_REG_HFRCTL, hfrctl);
0993         priv->dl2_unmuted = !mute;
0994         break;
0995     default:
0996         break;
0997     }
0998 }
0999 
1000 static int twl6040_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
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 
1018 static 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     .mute_stream    = twl6040_mute_stream,
1024     .no_capture_mute = 1,
1025 };
1026 
1027 static struct snd_soc_dai_driver twl6040_dai[] = {
1028 {
1029     .name = "twl6040-legacy",
1030     .id = TWL6040_DAI_LEGACY,
1031     .playback = {
1032         .stream_name = "Legacy Playback",
1033         .channels_min = 1,
1034         .channels_max = 5,
1035         .rates = TWL6040_RATES,
1036         .formats = TWL6040_FORMATS,
1037     },
1038     .capture = {
1039         .stream_name = "Legacy Capture",
1040         .channels_min = 1,
1041         .channels_max = 2,
1042         .rates = TWL6040_RATES,
1043         .formats = TWL6040_FORMATS,
1044     },
1045     .ops = &twl6040_dai_ops,
1046 },
1047 {
1048     .name = "twl6040-ul",
1049     .id = TWL6040_DAI_UL,
1050     .capture = {
1051         .stream_name = "Capture",
1052         .channels_min = 1,
1053         .channels_max = 2,
1054         .rates = TWL6040_RATES,
1055         .formats = TWL6040_FORMATS,
1056     },
1057     .ops = &twl6040_dai_ops,
1058 },
1059 {
1060     .name = "twl6040-dl1",
1061     .id = TWL6040_DAI_DL1,
1062     .playback = {
1063         .stream_name = "Headset Playback",
1064         .channels_min = 1,
1065         .channels_max = 2,
1066         .rates = TWL6040_RATES,
1067         .formats = TWL6040_FORMATS,
1068     },
1069     .ops = &twl6040_dai_ops,
1070 },
1071 {
1072     .name = "twl6040-dl2",
1073     .id = TWL6040_DAI_DL2,
1074     .playback = {
1075         .stream_name = "Handsfree Playback",
1076         .channels_min = 1,
1077         .channels_max = 2,
1078         .rates = TWL6040_RATES,
1079         .formats = TWL6040_FORMATS,
1080     },
1081     .ops = &twl6040_dai_ops,
1082 },
1083 {
1084     .name = "twl6040-vib",
1085     .id = TWL6040_DAI_VIB,
1086     .playback = {
1087         .stream_name = "Vibra Playback",
1088         .channels_min = 1,
1089         .channels_max = 1,
1090         .rates = SNDRV_PCM_RATE_CONTINUOUS,
1091         .formats = TWL6040_FORMATS,
1092     },
1093     .ops = &twl6040_dai_ops,
1094 },
1095 };
1096 
1097 static int twl6040_probe(struct snd_soc_component *component)
1098 {
1099     struct twl6040_data *priv;
1100     struct platform_device *pdev = to_platform_device(component->dev);
1101     int ret = 0;
1102 
1103     priv = devm_kzalloc(component->dev, sizeof(*priv), GFP_KERNEL);
1104     if (priv == NULL)
1105         return -ENOMEM;
1106 
1107     snd_soc_component_set_drvdata(component, priv);
1108 
1109     priv->component = component;
1110 
1111     priv->plug_irq = platform_get_irq(pdev, 0);
1112     if (priv->plug_irq < 0)
1113         return priv->plug_irq;
1114 
1115     INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
1116 
1117     mutex_init(&priv->mutex);
1118 
1119     ret = request_threaded_irq(priv->plug_irq, NULL,
1120                     twl6040_audio_handler,
1121                     IRQF_NO_SUSPEND | IRQF_ONESHOT,
1122                     "twl6040_irq_plug", component);
1123     if (ret) {
1124         dev_err(component->dev, "PLUG IRQ request failed: %d\n", ret);
1125         return ret;
1126     }
1127 
1128     snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
1129     twl6040_init_chip(component);
1130 
1131     return 0;
1132 }
1133 
1134 static void twl6040_remove(struct snd_soc_component *component)
1135 {
1136     struct twl6040_data *priv = snd_soc_component_get_drvdata(component);
1137 
1138     free_irq(priv->plug_irq, component);
1139 }
1140 
1141 static const struct snd_soc_component_driver soc_component_dev_twl6040 = {
1142     .probe          = twl6040_probe,
1143     .remove         = twl6040_remove,
1144     .read           = twl6040_read,
1145     .write          = twl6040_write,
1146     .set_bias_level     = twl6040_set_bias_level,
1147     .controls       = twl6040_snd_controls,
1148     .num_controls       = ARRAY_SIZE(twl6040_snd_controls),
1149     .dapm_widgets       = twl6040_dapm_widgets,
1150     .num_dapm_widgets   = ARRAY_SIZE(twl6040_dapm_widgets),
1151     .dapm_routes        = intercon,
1152     .num_dapm_routes    = ARRAY_SIZE(intercon),
1153     .suspend_bias_off   = 1,
1154     .idle_bias_on       = 1,
1155     .endianness     = 1,
1156 };
1157 
1158 static 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 
1165 static struct platform_driver twl6040_codec_driver = {
1166     .driver = {
1167         .name = "twl6040-codec",
1168     },
1169     .probe = twl6040_codec_probe,
1170 };
1171 
1172 module_platform_driver(twl6040_codec_driver);
1173 
1174 MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
1175 MODULE_AUTHOR("Misael Lopez Cruz");
1176 MODULE_LICENSE("GPL");