Example #1
0
static int twl6040_mute(struct snd_soc_dai *codec_dai, int mute)
{
#if 0
	struct snd_soc_codec *codec = codec_dai->codec;
	int hs_gain, hfl_gain, hfr_gain;
	struct snd_soc_card *card = codec_dai->card;
	int idx;
	int mute_all;

	hfl_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
	hfr_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
	hs_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);

	if (mute) {
		mute_all = 1;
		for( idx = 0 ; idx < TWL6040_MUTE_DATA_MAX ; idx++ )
		{
			if( s_mute_data[idx].dai == codec_dai )
			{
				s_mute_data[idx].mute = mute;
			}

			if( s_mute_data[idx].dai && s_mute_data[idx].mute == 0 )
			{
				mute_all = 0;
				break;
			}
		}

		if( mute_all )
		{
			twl6040_i2c_write(TWL6040_REG_HFLGAIN, 0x1D);
			twl6040_i2c_write(TWL6040_REG_HFRGAIN, 0x1D);
			twl6040_i2c_write(TWL6040_REG_HSGAIN, 0xFF);
		}
	} else {
		mute_all = 0;
		for( idx = 0 ; idx < TWL6040_MUTE_DATA_MAX ; idx++ )
		{
			if( s_mute_data[idx].dai == codec_dai )
			{
				s_mute_data[idx].mute = mute;
			}

			if( s_mute_data[idx].dai && s_mute_data[idx].mute )
			{
				mute_all = 1;
				break;
			}
		}

		if( mute_all == 0 ){
			twl6040_write(codec, TWL6040_REG_HFLGAIN, hfl_gain);
			twl6040_write(codec, TWL6040_REG_HFRGAIN, hfr_gain);
			twl6040_write(codec, TWL6040_REG_HSGAIN, hs_gain);
		}
	}
#endif
	return 0;
}
Example #2
0
/* set headset dac and driver power mode */
static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
{
	int hslctl, hsrctl;
	int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);

	/* Earphone doesn't support low power mode */
	high_perf |= priv->earpiece_used;

	hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
	hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);

	if (high_perf) {
		hslctl &= ~mask;
		hsrctl &= ~mask;
	} else {
		hslctl |= mask;
		hsrctl |= mask;
	}

	twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
	twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);

	return 0;
}
Example #3
0
/* twl6040 codec manual power-up sequence */
static void twl6040_power_up(struct snd_soc_codec *codec)
{
	u8 ncpctl, ldoctl, lppllctl, accctl;

	ncpctl = twl6040_read_reg_cache(codec, TWL6040_REG_NCPCTL);
	ldoctl = twl6040_read_reg_cache(codec, TWL6040_REG_LDOCTL);
	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);
	accctl = twl6040_read_reg_cache(codec, TWL6040_REG_ACCCTL);

	/* enable reference system */
	ldoctl |= TWL6040_REFENA;
	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
	msleep(10);
	/* enable internal oscillator */
	ldoctl |= TWL6040_OSCENA;
	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
	udelay(10);
	/* enable high-side ldo */
	ldoctl |= TWL6040_HSLDOENA;
	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
	udelay(244);
	/* enable negative charge pump */
	ncpctl |= TWL6040_NCPENA | TWL6040_NCPOPEN;
	twl6040_write(codec, TWL6040_REG_NCPCTL, ncpctl);
	udelay(488);
	/* enable low-side ldo */
	ldoctl |= TWL6040_LSLDOENA;
	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
	udelay(244);
	/* enable low-power pll */
	lppllctl |= TWL6040_LPLLENA;
	twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
	/* reset state machine */
	accctl |= TWL6040_RESETSPLIT;
	twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
	mdelay(5);
	accctl &= ~TWL6040_RESETSPLIT;
	twl6040_write(codec, TWL6040_REG_ACCCTL, accctl);
	/* disable internal oscillator */
	ldoctl &= ~TWL6040_OSCENA;
	twl6040_write(codec, TWL6040_REG_LDOCTL, ldoctl);
}
Example #4
0
/* set headset dac and driver power mode */
static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
{
	int hslctl, hsrctl;
	int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;

	hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
	hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);

	if (high_perf) {
		hslctl &= ~mask;
		hsrctl &= ~mask;
	} else {
		hslctl |= mask;
		hsrctl |= mask;
	}

	twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
	twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);

	return 0;
}
Example #5
0
void set_hook_enable(struct snd_soc_codec *codec, int on)
{
	u8 hkctl1;
	
	hkctl1 = twl6040_read_reg_cache(codec, TWL6040_REG_HKCTL1);
	
	if(on)
		hkctl1 |= TWL6040_HKEN;
	else
		hkctl1 &= ~TWL6040_HKEN;

	twl6040_write(codec, TWL6040_REG_HKCTL1, hkctl1);
}
Example #6
0
void hs_set_bias(struct snd_soc_codec *codec, int on)
{
	u8 hsbias;

	hsbias = twl6040_read_reg_cache(codec, TWL6040_REG_AMICBCTL);
	
	if(on)
		hsbias |= TWL6040_HMICENA;
	else
		hsbias &= ~TWL6040_HMICENA;

	twl6040_write(codec, TWL6040_REG_AMICBCTL, hsbias);
}
Example #7
0
static int twl6040_mute(struct snd_soc_dai *codec_dai, int mute)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);

	if (mute) {
		priv->hfl_gain = twl6040_read_reg_cache(codec,
						TWL6040_REG_HFLGAIN);
		priv->hfr_gain = twl6040_read_reg_cache(codec,
						TWL6040_REG_HFRGAIN);
		priv->hs_gain = twl6040_read_reg_cache(codec,
						TWL6040_REG_HSGAIN);

		twl6040_write(codec, TWL6040_REG_HFLGAIN, 0x1D);
		twl6040_write(codec, TWL6040_REG_HFRGAIN, 0x1D);
		twl6040_write(codec, TWL6040_REG_HSGAIN, 0xFF);
	} else {
		twl6040_write(codec, TWL6040_REG_HFLGAIN, priv->hfl_gain);
		twl6040_write(codec, TWL6040_REG_HFRGAIN, priv->hfr_gain);
		twl6040_write(codec, TWL6040_REG_HSGAIN, priv->hs_gain);
	}

	return 0;
}
Example #8
0
static int twl6040_hw_params(struct snd_pcm_substream *substream,
			struct snd_pcm_hw_params *params,
			struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_codec *codec = rtd->codec;
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
	u8 lppllctl;
	int rate;

	/* nothing to do for high-perf pll, it supports only 48 kHz */
	if (priv->pll == TWL6040_HPPLL_ID)
		return 0;

	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);

	rate = params_rate(params);
	switch (rate) {
	case 11250:
	case 22500:
	case 44100:
	case 88200:
		lppllctl |= TWL6040_LPLLFIN;
		priv->sysclk = 17640000;
		break;
	case 8000:
	case 16000:
	case 32000:
	case 48000:
	case 96000:
		lppllctl &= ~TWL6040_LPLLFIN;
		priv->sysclk = 19200000;
		break;
	default:
		dev_err(codec->dev, "unsupported rate %d\n", rate);
		return -EINVAL;
	}

	twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);

	return 0;
}
Example #9
0
static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
		int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
	u8 hppllctl, lppllctl;

	hppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_HPPLLCTL);
	lppllctl = twl6040_read_reg_cache(codec, TWL6040_REG_LPPLLCTL);

	switch (clk_id) {
	case TWL6040_SYSCLK_SEL_LPPLL:
		switch (freq) {
		case 32768:
			/* headset dac and driver must be in low-power mode */
			headset_power_mode(codec, 0);

			/* clk32k input requires low-power pll */
			lppllctl |= TWL6040_LPLLENA;
			twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
			mdelay(5);
			lppllctl &= ~TWL6040_HPLLSEL;
			twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
			hppllctl &= ~TWL6040_HPLLENA;
			twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
			break;
		default:
			dev_err(codec->dev, "unknown mclk freq %d\n", freq);
			return -EINVAL;
		}

		/* lppll divider */
		switch (priv->sysclk) {
		case 17640000:
			lppllctl |= TWL6040_LPLLFIN;
			break;
		case 19200000:
			lppllctl &= ~TWL6040_LPLLFIN;
			break;
		default:
			/* sysclk not yet configured */
			lppllctl &= ~TWL6040_LPLLFIN;
			priv->sysclk = 19200000;
			break;
		}

		twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);

		priv->pll = TWL6040_LPPLL_ID;
		priv->sysclk_constraints = &lp_constraints;
		break;
	case TWL6040_SYSCLK_SEL_HPPLL:
		hppllctl &= ~TWL6040_MCLK_MSK;

		switch (freq) {
		case 12000000:
			/* mclk input, pll enabled */
			hppllctl |= TWL6040_MCLK_12000KHZ |
				    TWL6040_HPLLSQRBP |
				    TWL6040_HPLLENA;
			break;
		case 19200000:
			/* mclk input, pll disabled */
			hppllctl |= TWL6040_MCLK_19200KHZ |
				    TWL6040_HPLLSQRENA |
				    TWL6040_HPLLBP;
			break;
		case 26000000:
			/* mclk input, pll enabled */
			hppllctl |= TWL6040_MCLK_26000KHZ |
				    TWL6040_HPLLSQRBP |
				    TWL6040_HPLLENA;
			break;
		case 38400000:
			/* clk slicer, pll disabled */
			hppllctl |= TWL6040_MCLK_38400KHZ |
				    TWL6040_HPLLSQRENA |
				    TWL6040_HPLLBP;
			break;
		default:
			dev_err(codec->dev, "unknown mclk freq %d\n", freq);
			return -EINVAL;
		}

		/* headset dac and driver must be in high-performance mode */
		headset_power_mode(codec, 1);

		twl6040_write(codec, TWL6040_REG_HPPLLCTL, hppllctl);
		udelay(500);
		lppllctl |= TWL6040_HPLLSEL;
		twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);
		lppllctl &= ~TWL6040_LPLLENA;
		twl6040_write(codec, TWL6040_REG_LPPLLCTL, lppllctl);

		/* high-performance pll can provide only 19.2 MHz */
		priv->pll = TWL6040_HPPLL_ID;
		priv->sysclk = 19200000;
		priv->sysclk_constraints = &hp_constraints;
		break;
	default:
		dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
		return -EINVAL;
	}

	return 0;
}
Example #10
0
static int twl6040_probe(struct snd_soc_codec *codec)
{
	struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
	struct twl6040_data *priv;
	struct twl6040_jack_data *jack;
	int ret = 0;

	codec->control_data = dev_get_drvdata(codec->dev->parent);

	priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
	if (priv == NULL)
		return -ENOMEM;

	snd_soc_codec_set_drvdata(codec, priv);
	priv->codec = codec;
	priv->workqueue = create_singlethread_workqueue("twl6040-codec");
	if (!priv->workqueue)
		goto work_err;

#if TWL6040_DEBUG
///////////////////////////////////////////////////////////////////////////////////////////////////
{
	codec_twl6040 = codec->control_data;
	ret = device_create_file(codec->dev, &dev_attr_reg);
	if (ret < 0)
		printk(KERN_WARNING "twl6040: failed to add entries\n");
	ret = device_create_file(codec->dev, &dev_attr_val);
	if (ret < 0)
		printk(KERN_WARNING "twl6040: failed to add entries\n");
	ret = device_create_file(codec->dev, &dev_attr_prt);
	if (ret < 0)
		printk(KERN_WARNING "twl6040: failed to add entries\n");
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#endif

	priv->hfl_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
	priv->hfr_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
	priv->hs_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);

	INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
	mutex_init(&priv->mutex);

	priv->vddhf_reg = regulator_get(codec->dev, "vddhf");
	if (IS_ERR(priv->vddhf_reg)) {
		ret = PTR_ERR(priv->vddhf_reg);
		dev_warn(codec->dev, "couldn't get VDDHF regulator %d\n",
			 ret);
		priv->vddhf_reg = NULL;
	}

	if (priv->vddhf_reg) {
		ret = regulator_set_voltage(priv->vddhf_reg,
					    pdata->vddhf_uV, pdata->vddhf_uV);
		if (ret) {
			dev_warn(codec->dev, "failed to set VDDHF voltage %d\n",
				 ret);
			goto reg_err;
		}
	}

	/* switch-class based headset detection */
	jack = &priv->hs_jack;
	jack->sdev.name = "h2w";
	ret = switch_dev_register(&jack->sdev);
	if (ret) {
		dev_err(codec->dev, "error registering switch device %d\n", ret);
		goto reg_err;
	}

	wake_lock_init(&priv->wake_lock, WAKE_LOCK_SUSPEND, "twl6040");

	ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_PLUG,
				  twl6040_audio_handler, IRQF_NO_SUSPEND,
				  "twl6040_irq_plug", codec);
	if (ret) {
		dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
		goto irq_err;
	}

	/* init vio registers */
	twl6040_init_vio_regs(codec);

	/* power on device */
	ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	if (ret)
		goto bias_err;

	snd_soc_add_controls(codec, twl6040_snd_controls,
				ARRAY_SIZE(twl6040_snd_controls));
	twl6040_add_widgets(codec);

	/* TODO: read HS jack insertion status */

	return 0;

bias_err:
	twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec);
irq_err:
	wake_lock_destroy(&priv->wake_lock);
	switch_dev_unregister(&jack->sdev);
reg_err:
	if (priv->vddhf_reg)
		regulator_put(priv->vddhf_reg);
	destroy_workqueue(priv->workqueue);
work_err:
	kfree(priv);
	return ret;
}
Example #11
0
static void twl6040_hs_jack_detect_dwork(struct work_struct *dwork)
{
	struct twl6040_data *priv;
	struct snd_soc_codec *codec;
	struct twl6040_jack_data *jack;
	int status = 0;

	priv = container_of(dwork, struct twl6040_data, hsdet_dwork.work);
	codec = priv->codec;
	jack = &priv->hs_jack;

	/*
	 * Early interrupt, CODEC driver cannot report jack status
	 * since jack is not registered yet. MACHINE driver will
	 * register jack and report status through twl6040_hs_jack_detect
	 */
	if (jack->jack) {
#if defined(CONFIG_MACH_LGE_COSMO_REV_A)
		if(gpio_get_value(priv->hsjack_gpio))
#else 
		if(jack->state)
#endif
		{		
			u8 val = 0;
			if( twl6040_i2c_read(TWL6040_REG_AMICBCTL, &val) == 0 ){
				if( val != twl6040_read_reg_cache(codec, TWL6040_REG_AMICBCTL) )
					twl6040_i2c_write(TWL6040_REG_AMICBCTL, twl6040_read_reg_cache(codec, TWL6040_REG_AMICBCTL)); 
			}

			hs_set_bias(codec, 1);
			set_hook_enable(codec, 1);
			mdelay(200);

			if( twl6040_i2c_read(TWL6040_REG_MICLCTL, &val) == 0 ){
				if( val != twl6040_read_reg_cache(codec, TWL6040_REG_MICLCTL) )
					twl6040_i2c_write(TWL6040_REG_MICLCTL, twl6040_read_reg_cache(codec, TWL6040_REG_MICLCTL)); 
			}
			if( twl6040_i2c_read(TWL6040_REG_MICRCTL, &val) == 0 ){
				if( val != twl6040_read_reg_cache(codec, TWL6040_REG_MICRCTL) )
					twl6040_i2c_write(TWL6040_REG_MICRCTL, twl6040_read_reg_cache(codec, TWL6040_REG_MICRCTL)); 
			}

			if(is_without_mic()){
				set_hook_enable(codec, 0);
				hs_set_bias(codec, 0);
				jack->state = WIRED_HEADPHONE;//wired headset without MIC
				status = SND_JACK_HEADPHONE;
			}
			else{
				if(priv->intmask & TWL6040_HOOKMSK){
					priv->intmask &= ~TWL6040_HOOKMSK;
					twl6040_write(codec, TWL6040_REG_INTMR, priv->intmask);
				}
				status = jack->report;//SND_JACK_HEADSET
			}
		}
		else{
			if(!(priv->intmask & TWL6040_HOOKMSK)) {
				priv->intmask |= TWL6040_HOOKMSK;
				twl6040_write(codec, TWL6040_REG_INTMR, priv->intmask);
			}
			hs_set_bias(codec, 0);
			status = 0;
		}
		snd_soc_jack_report(jack->jack, status, jack->report);
	}
	switch_set_state(&jack->sdev, jack->state);
}
Example #12
0
static int twl6040_set_bias_level(struct snd_soc_codec *codec,
				enum snd_soc_bias_level level)
{
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
	int audpwron = priv->audpwron;
	int naudint = priv->naudint;
	int ret;

	switch (level) {
	case SND_SOC_BIAS_ON:
		break;
	case SND_SOC_BIAS_PREPARE:
		break;
	case SND_SOC_BIAS_STANDBY:
		if (priv->codec_powered)
			break;

		if (gpio_is_valid(audpwron)) {
			/* use AUDPWRON line */
			gpio_set_value(audpwron, 1);

#if defined(CONFIG_MACH_LGE_COSMO_REV_C)
			mdelay(50);
#endif

			/* wait for power-up completion */
			ret = twl6040_power_up_completion(codec, naudint);
			if (ret)
				return ret;

			/* sync registers updated during power-up sequence */
			twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
			twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
			twl6040_read_reg_volatile(codec, TWL6040_REG_LPPLLCTL);
		} else {
			/* use manual power-up sequence */
			twl6040_power_up(codec);
			priv->codec_powered = 1;
		}

		/* initialize vdd/vss registers with reg_cache */
		twl6040_init_vdd_regs(codec);
		break;
	case SND_SOC_BIAS_OFF:
		if (!priv->codec_powered)
			break;

		if (gpio_is_valid(audpwron)) {			
			// Headset Left Driver make pop-noise when twl6040 enter into sleep mode.
			u8 val;
			val = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
			if( val & 0x04 )	// temp disableed. It will be recovered when power-on.
			{
				twl6040_i2c_write(TWL6040_REG_HSLCTL, (val & (~0x04)));
				msleep(1);	// delay;;
			}

			/* use AUDPWRON line */
			gpio_set_value(audpwron, 0);

			/* power-down sequence latency */
			mdelay(1);	// more more...

			/* sync registers updated during power-down sequence */
			twl6040_read_reg_volatile(codec, TWL6040_REG_NCPCTL);
			twl6040_read_reg_volatile(codec, TWL6040_REG_LDOCTL);
			twl6040_write_reg_cache(codec, TWL6040_REG_LPPLLCTL,
						0x00);
		} else {
			/* use manual power-down sequence */
			twl6040_power_down(codec);
		}

		priv->codec_powered = 0;
		break;
	}

	codec->dapm->bias_level = level;

	return 0;
}
Example #13
0
static int twl6040_probe(struct snd_soc_codec *codec)
{
	struct twl6040_data *priv;
	struct twl6040_jack_data *jack;
	int ret = 0;

	codec->control_data = dev_get_drvdata(codec->dev->parent);

	priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
	if (priv == NULL)
		return -ENOMEM;

	snd_soc_codec_set_drvdata(codec, priv);
	priv->codec = codec;
	priv->workqueue = create_singlethread_workqueue("twl6040-codec");
	if (!priv->workqueue)
		goto work_err;

	priv->hfl_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
	priv->hfr_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
	priv->hs_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);

	INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
	mutex_init(&priv->mutex);

	/* switch-class based headset detection */
	jack = &priv->hs_jack;
	jack->sdev.name = "h2w";
	ret = switch_dev_register(&jack->sdev);
	if (ret) {
		dev_err(codec->dev, "error registering switch device %d\n", ret);
		goto switch_err;
	}

//--[[ LGE_UBIQUIX_MODIFIED_START : [email protected] : add from DCM_GB
	wake_lock_init(&priv->wake_lock, WAKE_LOCK_SUSPEND, "twl6040");

	ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_PLUG,
				  twl6040_audio_handler, IRQF_NO_SUSPEND,
				  "twl6040_irq_plug", codec);
//--[[ LGE_UBIQUIX_MODIFIED_END : [email protected] : add from DCM_GB
	if (ret) {
		dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret);
		goto irq_err;
	}

	/* init vio registers */
	twl6040_init_vio_regs(codec);

	/* power on device */
	ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	if (ret)
		goto bias_err;

	snd_soc_add_controls(codec, twl6040_snd_controls,
				ARRAY_SIZE(twl6040_snd_controls));
	twl6040_add_widgets(codec);

	/* TODO: read HS jack insertion status */

	return 0;

bias_err:
	twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec);
irq_err:
//--[[ LGE_UBIQUIX_MODIFIED_START : [email protected] : add from DCM_GB
	wake_lock_destroy(&priv->wake_lock);
//--[[ LGE_UBIQUIX_MODIFIED_END : [email protected] : add from DCM_GB
	switch_dev_unregister(&jack->sdev);
switch_err:
	destroy_workqueue(priv->workqueue);
work_err:
	kfree(priv);
	return ret;
}