cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

twl6040.c (32198B)


      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_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
   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	.mute_stream	= twl6040_mute_stream,
   1024	.no_capture_mute = 1,
   1025};
   1026
   1027static 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
   1097static 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
   1134static 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
   1141static 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	.non_legacy_dai_naming	= 1,
   1157};
   1158
   1159static int twl6040_codec_probe(struct platform_device *pdev)
   1160{
   1161	return devm_snd_soc_register_component(&pdev->dev,
   1162				      &soc_component_dev_twl6040,
   1163				      twl6040_dai, ARRAY_SIZE(twl6040_dai));
   1164}
   1165
   1166static struct platform_driver twl6040_codec_driver = {
   1167	.driver = {
   1168		.name = "twl6040-codec",
   1169	},
   1170	.probe = twl6040_codec_probe,
   1171};
   1172
   1173module_platform_driver(twl6040_codec_driver);
   1174
   1175MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
   1176MODULE_AUTHOR("Misael Lopez Cruz");
   1177MODULE_LICENSE("GPL");