Exemple #1
0
static int hdmi_audio_codec_probe(struct snd_soc_codec *codec)
{
	struct hdmi_ip_data *priv = &hdmi.ip_data;

	snd_soc_codec_set_drvdata(codec, priv);
	return 0;
}
Exemple #2
0
static int timpani_codec_probe(struct platform_device *pdev)
{
	struct snd_soc_codec *codec;
	struct timpani_drv_data *priv;

	pr_info("%s()\n", __func__);
	priv = kzalloc(sizeof(struct timpani_drv_data), GFP_KERNEL);
	if (priv == NULL)
		return -ENOMEM;

	codec = &priv->codec;
	snd_soc_codec_set_drvdata(codec, priv);
	priv->codec_pdata = pdev->dev.platform_data;

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	codec->name = "TIMPANI";
	codec->owner = THIS_MODULE;
	codec->read = timpani_codec_read;
	codec->write = timpani_codec_write;
	codec->dai = timpani_codec_dai;
	codec->num_dai = ARRAY_SIZE(timpani_codec_dai);
	codec->control_data = platform_get_drvdata(pdev);
	timpani_codec = codec;

	snd_soc_register_dais(timpani_codec_dai, ARRAY_SIZE(timpani_codec_dai));
	snd_soc_register_codec(codec);

	return 0;
}
static int pm8916_wcd_analog_probe(struct snd_soc_codec *codec)
{
	struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(codec->dev);
	int err, reg;

	err = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
	if (err != 0) {
		dev_err(codec->dev, "failed to enable regulators (%d)\n", err);
		return err;
	}

	snd_soc_codec_set_drvdata(codec, priv);
	priv->pmic_rev = snd_soc_read(codec, CDC_D_REVISION1);
	priv->codec_version = snd_soc_read(codec, CDC_D_PERPH_SUBTYPE);

	dev_info(codec->dev, "PMIC REV: %d\t CODEC Version: %d\n",
		 priv->pmic_rev, priv->codec_version);

	snd_soc_write(codec, CDC_D_PERPH_RESET_CTL4, 0x01);
	snd_soc_write(codec, CDC_A_PERPH_RESET_CTL4, 0x01);

	for (reg = 0; reg < ARRAY_SIZE(wcd_reg_defaults_2_0); reg++)
		snd_soc_write(codec, wcd_reg_defaults_2_0[reg].reg,
			      wcd_reg_defaults_2_0[reg].def);

	return 0;
}
Exemple #4
0
static int stac9766_codec_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	int ret = 0;

	ac97 = snd_soc_new_ac97_codec(codec);
	if (IS_ERR(ac97))
		return PTR_ERR(ac97);

	snd_soc_codec_set_drvdata(codec, ac97);

	/* do a cold reset for the controller and then try
	 * a warm reset followed by an optional cold reset for codec */
	stac9766_reset(codec, 0);
	ret = stac9766_reset(codec, 1);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to reset: AC97 link error\n");
		goto codec_err;
	}

	return 0;

codec_err:
	snd_soc_free_ac97_codec(ac97);
	return ret;
}
Exemple #5
0
static int wl1273_probe(struct snd_soc_codec *codec)
{
	struct wl1273_core **core = codec->dev->platform_data;
	struct wl1273_priv *wl1273;
	int r;

	dev_dbg(codec->dev, "%s.\n", __func__);

	if (!core) {
		dev_err(codec->dev, "Platform data is missing.\n");
		return -EINVAL;
	}

	wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
	if (wl1273 == NULL) {
		dev_err(codec->dev, "Cannot allocate memory.\n");
		return -ENOMEM;
	}

	wl1273->mode = WL1273_MODE_BT;
	wl1273->core = *core;

	snd_soc_codec_set_drvdata(codec, wl1273);

	r = snd_soc_add_controls(codec, wl1273_controls,
				 ARRAY_SIZE(wl1273_controls));
	if (r)
		kfree(wl1273);

	return r;
}
Exemple #6
0
static int aml_pmu4_audio_probe(struct snd_soc_codec *codec)
{
    struct aml_pmu4_audio_priv *pmu4_audio = NULL;

    printk("enter %s\n",__func__);
	pmu4_audio = kzalloc(sizeof(struct aml_pmu4_audio_priv), GFP_KERNEL);
    if (NULL == pmu4_audio)
        return -ENOMEM;
	snd_soc_codec_set_drvdata(codec,pmu4_audio);
#if 0
    ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
    if (ret != 0) {
        dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
        return ret;
    }
#endif
	
	//enable LDO1V8 for audio
	aml_pmu4_audio_power_init();  

	//reset audio codec register
    aml_pmu4_audio_reset(codec);
	aml_pmu4_audio_start_up(codec);

    aml_pmu4_audio_reg_init(codec);

    codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;

    pmu4_audio->codec = codec;



    return 0;
}
Exemple #7
0
static int hdmi_probe(struct snd_soc_codec *codec)
{
	struct platform_device *pdev = to_platform_device(codec->dev);
	struct resource *hdmi_rsrc;
	int ret = 0;

	snd_soc_codec_set_drvdata(codec, &hdmi_data);

	hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	if (!hdmi_rsrc) {
		dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
		ret = -EINVAL;
		goto res_err;
	}


	hdmi_data.oh = omap_hwmod_lookup("dss_hdmi");

	if (!hdmi_data.oh) {
		dev_err(&pdev->dev, "can't find omap_hwmod for hdmi\n");
		ret = -ENODEV;
		goto res_err;
	}

	/* Base address taken from platform */
	hdmi_data.ip_data.base_wp = ioremap(hdmi_rsrc->start,
					resource_size(hdmi_rsrc));

	if (!hdmi_data.ip_data.base_wp) {
		dev_err(&pdev->dev, "can't ioremap WP\n");
		ret = -ENOMEM;
		goto res_err;
	}

	hdmi_data.ip_data.hdmi_core_sys_offset = HDMI_CORE_SYS;
	hdmi_data.ip_data.hdmi_core_av_offset = HDMI_CORE_AV;
	hdmi_data.ip_data.hdmi_pll_offset = HDMI_PLLCTRL;
	hdmi_data.ip_data.hdmi_phy_offset = HDMI_PHY;

	hdmi_data.dssdev = omap_dss_find_device(NULL, hdmi_audio_match);

	if (!hdmi_data.dssdev) {
		dev_err(&pdev->dev, "can't find HDMI device\n");
		ret = -ENODEV;
		goto dssdev_err;
	}

	hdmi_data.notifier.notifier_call = hdmi_audio_notifier_callback;
	blocking_notifier_chain_register(&hdmi_data.dssdev->state_notifiers,
			&hdmi_data.notifier);

	return 0;

dssdev_err:
	iounmap(hdmi_data.ip_data.base_wp);
res_err:
	return ret;

}
static int msm8916_wcd_digital_codec_probe(struct snd_soc_codec *codec)
{
	struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(codec->dev);

	snd_soc_codec_set_drvdata(codec, priv);

	return 0;
}
Exemple #9
0
static int ak4671_register(struct ak4671_priv *ak4671,
		enum snd_soc_control_type control)
{
	int ret;
	struct snd_soc_codec *codec = &ak4671->codec;

	if (ak4671_codec) {
		dev_err(codec->dev, "Another AK4671 is registered\n");
		ret = -EINVAL;
		goto err;
	}

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	snd_soc_codec_set_drvdata(codec,  ak4671);
	codec->name = "AK4671";
	codec->owner = THIS_MODULE;
	codec->bias_level = SND_SOC_BIAS_OFF;
	codec->set_bias_level = ak4671_set_bias_level;
	codec->dai = &ak4671_dai;
	codec->num_dai = 1;
	codec->reg_cache_size = AK4671_CACHEREGNUM;
	codec->reg_cache = &ak4671->reg_cache;

	memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));

	ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
		goto err;
	}

	ak4671_dai.dev = codec->dev;
	ak4671_codec = codec;

	ret = snd_soc_register_codec(codec);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
		goto err;
	}

	ret = snd_soc_register_dai(&ak4671_dai);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
		goto err_codec;
	}

	return 0;

err_codec:
	snd_soc_unregister_codec(codec);
err:
	kfree(ak4671);
	return ret;
}
Exemple #10
0
static int snddaudio_soc_probe(struct snd_soc_codec *codec)
{
	struct snddaudio_priv *snddaudio;

	snddaudio = kzalloc(sizeof(struct snddaudio_priv), GFP_KERNEL);
	if(snddaudio == NULL){		
		return -ENOMEM;
	}		
	snd_soc_codec_set_drvdata(codec, snddaudio);

	return 0;
}
static int sndspdif_soc_probe(struct snd_soc_codec *codec)
{
	struct sndspdif_priv *sndspdif;	
	
	sndspdif = kzalloc(sizeof(struct sndspdif_priv), GFP_KERNEL);
	if(sndspdif == NULL){
		printk("%s,%d\n",__func__,__LINE__);
		return -ENOMEM;
	}		
	snd_soc_codec_set_drvdata(codec, sndspdif);
	
	return 0;
}
Exemple #12
0
static int sndhdmi_soc_probe(struct snd_soc_codec *codec)
{
	struct sndhdmi_priv *sndhdmi;
	
	sndhdmi = kzalloc(sizeof(struct sndhdmi_priv), GFP_KERNEL);
	if(sndhdmi == NULL){
		printk("error at:%s,%d\n",__func__,__LINE__);
		return -ENOMEM;
	}		
	snd_soc_codec_set_drvdata(codec, sndhdmi);

	return 0;
}
Exemple #13
0
static int cx20442_codec_probe(struct snd_soc_codec *codec)
{
	struct cx20442_priv *cx20442;

	cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
	if (cx20442 == NULL)
		return -ENOMEM;
	snd_soc_codec_set_drvdata(codec, cx20442);

	cx20442->control_data = NULL;
	codec->hw_write = NULL;
	codec->card->pop_time = 0;

	return 0;
}
Exemple #14
0
static int cx20442_register(struct cx20442_priv *cx20442)
{
	struct snd_soc_codec *codec = &cx20442->codec;
	int ret;

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	codec->name = "CX20442";
	codec->owner = THIS_MODULE;
	snd_soc_codec_set_drvdata(codec, cx20442);

	codec->dai = &cx20442_dai;
	codec->num_dai = 1;

	codec->reg_cache = &cx20442->reg_cache;
	codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache);
	codec->read = cx20442_read_reg_cache;
	codec->write = cx20442_write;

	codec->bias_level = SND_SOC_BIAS_OFF;

	cx20442_dai.dev = codec->dev;

	cx20442_codec = codec;

	ret = snd_soc_register_codec(codec);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
		goto err;
	}

	ret = snd_soc_register_dai(&cx20442_dai);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
		goto err_codec;
	}

	return 0;

err_codec:
	snd_soc_unregister_codec(codec);
err:
	cx20442_codec = NULL;
	kfree(cx20442);
	return ret;
}
/* power down chip */
static int cx20442_codec_remove(struct snd_soc_codec *codec)
{
	struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);

	if (cx20442->control_data) {
			struct tty_struct *tty = cx20442->control_data;
			tty_hangup(tty);
	}

	if (!IS_ERR(cx20442->por)) {
		/* should be already in STANDBY, hence disabled */
		regulator_put(cx20442->por);
	}

	snd_soc_codec_set_drvdata(codec, NULL);
	kfree(cx20442);
	return 0;
}
static int cx20442_codec_probe(struct snd_soc_codec *codec)
{
	struct cx20442_priv *cx20442;

	cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
	if (cx20442 == NULL)
		return -ENOMEM;

	cx20442->por = regulator_get(codec->dev, "POR");
	if (IS_ERR(cx20442->por))
		dev_warn(codec->dev, "failed to get the regulator");
	cx20442->control_data = NULL;

	snd_soc_codec_set_drvdata(codec, cx20442);
	codec->hw_write = NULL;
	codec->card->pop_time = 0;

	return 0;
}
Exemple #17
0
static int ak4535_probe(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct ak4535_setup_data *setup;
	struct snd_soc_codec *codec;
	struct ak4535_priv *ak4535;
	int ret;

	printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);

	setup = socdev->codec_data;
	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
	if (codec == NULL)
		return -ENOMEM;

	ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
	if (ak4535 == NULL) {
		kfree(codec);
		return -ENOMEM;
	}

	snd_soc_codec_set_drvdata(codec, ak4535);
	socdev->card->codec = codec;
	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	ak4535_socdev = socdev;
	ret = -ENODEV;

#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
	if (setup->i2c_address) {
		codec->hw_write = (hw_write_t)i2c_master_send;
		ret = ak4535_add_i2c_device(pdev, setup);
	}
#endif

	if (ret != 0) {
		kfree(snd_soc_codec_get_drvdata(codec));
		kfree(codec);
	}
	return ret;
}
Exemple #18
0
static int mxc_hdmi_codec_soc_probe(struct snd_soc_codec *codec)
{
	struct mxc_hdmi_priv *hdmi_priv;
	int ret = 0;

	if (!hdmi_get_registered())
		return -ENOMEM;

	hdmi_priv = kzalloc(sizeof(struct mxc_hdmi_priv), GFP_KERNEL);
	if (hdmi_priv == NULL)
		return -ENOMEM;

	hdmi_priv->isfr_clk = clk_get(NULL, "hdmi_isfr_clk");
	if (IS_ERR(hdmi_priv->isfr_clk)) {
		ret = PTR_ERR(hdmi_priv->isfr_clk);
		pr_err("%s Unable to get HDMI isfr clk: %d\n", __func__, ret);
		goto e_clk_get1;
	}

	hdmi_priv->iahb_clk = clk_get(NULL, "hdmi_iahb_clk");
	if (IS_ERR(hdmi_priv->iahb_clk)) {
		ret = PTR_ERR(hdmi_priv->iahb_clk);
		pr_err("%s Unable to get HDMI iahb clk: %d\n", __func__, ret);
		goto e_clk_get2;
	}

	ret = snd_soc_add_controls(codec, mxc_hdmi_ctrls,
			     ARRAY_SIZE(mxc_hdmi_ctrls));
	if (ret)
		goto e_add_ctrls;

	snd_soc_codec_set_drvdata(codec, hdmi_priv);

	return 0;

e_add_ctrls:
	clk_put(hdmi_priv->iahb_clk);
e_clk_get2:
	clk_put(hdmi_priv->isfr_clk);
e_clk_get1:
	kfree(hdmi_priv);
	return ret;
}
static int sndhdmi_soc_probe(struct snd_soc_codec *codec)
{
	struct sndhdmi_priv *sndhdmi = NULL;

	atomic_set(&pcm_count_num, 0);
	if (!codec) {
		pr_err("error:%s,line:%d\n", __func__, __LINE__);
		return -EAGAIN;
	}

	sndhdmi = kzalloc(sizeof(struct sndhdmi_priv), GFP_KERNEL);
	if (sndhdmi == NULL) {
		pr_err("error at:%s,%d\n",__func__,__LINE__);
		return -ENOMEM;
	}

	snd_soc_codec_set_drvdata(codec, sndhdmi);

	return 0;
}
Exemple #20
0
static int ac97_soc_probe(struct snd_soc_codec *codec)
{
	struct snd_ac97 *ac97;
	struct snd_ac97_bus *ac97_bus;
	struct snd_ac97_template ac97_template;
	int ret;

	/* add codec as bus device for standard ac97 */
	ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
			   NULL, &ac97_bus);
	if (ret < 0)
		return ret;

	memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
	if (ret < 0)
		return ret;

	snd_soc_codec_set_drvdata(codec, ac97);

	return 0;
}
Exemple #21
0
static int wl1273_probe(struct snd_soc_codec *codec)
{
	struct wl1273_core **core = codec->dev->platform_data;
	struct wl1273_priv *wl1273;

	dev_dbg(codec->dev, "%s.\n", __func__);

	if (!core) {
		dev_err(codec->dev, "Platform data is missing.\n");
		return -EINVAL;
	}

	wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
	if (!wl1273)
		return -ENOMEM;

	wl1273->mode = WL1273_MODE_BT;
	wl1273->core = *core;

	snd_soc_codec_set_drvdata(codec, wl1273);

	return 0;
}
Exemple #22
0
static int dmic_probe(struct snd_soc_codec *codec)
{
//	struct dmic_platform_data *dmic_pdata = codec->dev->platform_data;
	struct dmic_data *priv;
//	int ret = 0;

	priv = kzalloc(sizeof(struct dmic_data), GFP_KERNEL);
	if (priv == NULL)
		return -ENOMEM;
	snd_soc_codec_set_drvdata(codec, priv);

#if 0
	/* power on device */
	ret = dmic_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	if (ret)
		goto irq_err;

	snd_soc_add_controls(codec, dmic_snd_controls,
				ARRAY_SIZE(dmic_snd_controls));
	dmic_add_widgets(codec);
#endif
	return 0;
}
Exemple #23
0
static int da7210_init(struct da7210_priv *da7210)
{
	struct snd_soc_codec *codec = &da7210->codec;
	int ret = 0;

	if (da7210_codec) {
		dev_err(codec->dev, "Another da7210 is registered\n");
		return -EINVAL;
	}

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	snd_soc_codec_set_drvdata(codec, da7210);
	codec->name		= "DA7210";
	codec->owner		= THIS_MODULE;
	codec->read		= da7210_read;
	codec->write		= da7210_write;
	codec->dai		= &da7210_dai;
	codec->num_dai		= 1;
	codec->hw_write		= (hw_write_t)i2c_master_send;
	codec->reg_cache_size	= ARRAY_SIZE(da7210_reg);
	codec->reg_cache	= kmemdup(da7210_reg,
					  sizeof(da7210_reg), GFP_KERNEL);

	if (!codec->reg_cache)
		return -ENOMEM;

	da7210_dai.dev = codec->dev;
	da7210_codec = codec;

	ret = snd_soc_register_codec(codec);
	if (ret) {
		dev_err(codec->dev, "Failed to register CODEC: %d\n", ret);
		goto init_err;
	}

	ret = snd_soc_register_dai(&da7210_dai);
	if (ret) {
		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
		goto init_err;
	}

	/* FIXME
	 *
	 * This driver use fixed value here
	 * And below settings expects MCLK = 12.288MHz
	 *
	 * When you select different MCLK, please check...
	 *      DA7210_PLL_DIV1 val
	 *      DA7210_PLL_DIV2 val
	 *      DA7210_PLL_DIV3 val
	 *      DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx
	 */

	/*
	 * make sure that DA7210 use bypass mode before start up
	 */
	da7210_write(codec, DA7210_STARTUP1, 0);
	da7210_write(codec, DA7210_PLL_DIV3,
		     DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);

	/*
	 * ADC settings
	 */

	/* Enable Left & Right MIC PGA and Mic Bias */
	da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
	da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);

	/* Enable Left and Right input PGA */
	da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
	da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);

	/* Enable Left and Right ADC */
	da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);

	/*
	 * DAC settings
	 */

	/* Enable Left and Right DAC */
	da7210_write(codec, DA7210_DAC_SEL,
		     DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN |
		     DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN);

	/* Enable Left and Right out PGA */
	da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
	da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);

	/* Enable Left and Right HeadPhone PGA */
	da7210_write(codec, DA7210_HP_CFG,
		     DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN |
		     DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN);

	/* Diable PLL and bypass it */
	da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);

	/*
	 * If 48kHz sound came, it use bypass mode,
	 * and when it is 44.1kHz, it use PLL.
	 *
	 * This time, this driver sets PLL always ON
	 * and controls bypass/PLL mode by switching
	 * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
	 *   see da7210_hw_params
	 */
	da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
	da7210_write(codec, DA7210_PLL_DIV2, 0x99);
	da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
		     DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
	snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);

	/* As suggested by Dialog */
	da7210_write(codec, DA7210_A_HID_UNLOCK,	0x8B); /* unlock */
	da7210_write(codec, DA7210_A_TEST_UNLOCK,	0xB4);
	da7210_write(codec, DA7210_A_PLL1,		0x01);
	da7210_write(codec, DA7210_A_CP_MODE,		0x7C);
	da7210_write(codec, DA7210_A_HID_UNLOCK,	0x00); /* re-lock */
	da7210_write(codec, DA7210_A_TEST_UNLOCK,	0x00);

	/* Activate all enabled subsystem */
	da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);

	return ret;

init_err:
	kfree(codec->reg_cache);
	codec->reg_cache = NULL;

	return ret;

}
Exemple #24
0
static int __devinit twl6040_codec_probe(struct platform_device *pdev)
{
	struct twl4030_codec_data *twl_codec = pdev->dev.platform_data;
	struct snd_soc_codec *codec;
	struct twl6040_data *priv;
	int audpwron, naudint;
	int ret = 0;

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

	if (twl_codec) {
		audpwron = twl_codec->audpwron_gpio;
		naudint = twl_codec->naudint_irq;
	} else {
		audpwron = -EINVAL;
		naudint = 0;
	}

	priv->audpwron = audpwron;
	priv->naudint = naudint;

	codec = &priv->codec;
	codec->dev = &pdev->dev;
	twl6040_dai.dev = &pdev->dev;

	codec->name = "twl6040";
	codec->owner = THIS_MODULE;
	codec->read = twl6040_read_reg_cache;
	codec->write = twl6040_write;
	codec->set_bias_level = twl6040_set_bias_level;
	snd_soc_codec_set_drvdata(codec, priv);
	codec->dai = &twl6040_dai;
	codec->num_dai = 1;
	codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
	codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
					GFP_KERNEL);
	if (codec->reg_cache == NULL) {
		ret = -ENOMEM;
		goto cache_err;
	}

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);
	init_completion(&priv->ready);

	if (gpio_is_valid(audpwron)) {
		ret = gpio_request(audpwron, "audpwron");
		if (ret)
			goto gpio1_err;

		ret = gpio_direction_output(audpwron, 0);
		if (ret)
			goto gpio2_err;

		priv->codec_powered = 0;
	}

	if (naudint) {
		/* audio interrupt */
		ret = request_threaded_irq(naudint, NULL,
				twl6040_naudint_handler,
				IRQF_TRIGGER_LOW | IRQF_ONESHOT,
				"twl6040_codec", codec);
		if (ret)
			goto gpio2_err;
	} else {
		if (gpio_is_valid(audpwron)) {
			/* enable only codec ready interrupt */
			twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
					~TWL6040_READYMSK & TWL6040_ALLINT_MSK);
		} else {
			/* no interrupts at all */
			twl6040_write_reg_cache(codec, TWL6040_REG_INTMR,
						TWL6040_ALLINT_MSK);
		}
	}

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

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

	ret = snd_soc_register_codec(codec);
	if (ret)
		goto reg_err;

	twl6040_codec = codec;

	ret = snd_soc_register_dai(&twl6040_dai);
	if (ret)
		goto dai_err;

	return 0;

dai_err:
	snd_soc_unregister_codec(codec);
	twl6040_codec = NULL;
reg_err:
	twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
irq_err:
	if (naudint)
		free_irq(naudint, codec);
gpio2_err:
	if (gpio_is_valid(audpwron))
		gpio_free(audpwron);
gpio1_err:
	kfree(codec->reg_cache);
cache_err:
	kfree(priv);
	return ret;
}
Exemple #25
0
static int ad1980_soc_probe(struct snd_soc_codec *codec)
{
    struct snd_ac97 *ac97;
    struct regmap *regmap;
    int ret;
    u16 vendor_id2;
    u16 ext_status;

    ac97 = snd_soc_new_ac97_codec(codec);
    if (IS_ERR(ac97)) {
        ret = PTR_ERR(ac97);
        dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret);
        return ret;
    }

    regmap = regmap_init_ac97(ac97, &ad1980_regmap_config);
    if (IS_ERR(regmap)) {
        ret = PTR_ERR(regmap);
        goto err_free_ac97;
    }

    snd_soc_codec_init_regmap(codec, regmap);
    snd_soc_codec_set_drvdata(codec, ac97);

    ret = ad1980_reset(codec, 0);
    if (ret < 0)
        goto reset_err;

    /* Read out vendor ID to make sure it is ad1980 */
    if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) {
        ret = -ENODEV;
        goto reset_err;
    }

    vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2);

    if (vendor_id2 != 0x5370) {
        if (vendor_id2 != 0x5374) {
            ret = -ENODEV;
            goto reset_err;
        } else {
            dev_warn(codec->dev,
                     "Found AD1981 - only 2/2 IN/OUT Channels supported\n");
        }
    }

    /* unmute captures and playbacks volume */
    snd_soc_write(codec, AC97_MASTER, 0x0000);
    snd_soc_write(codec, AC97_PCM, 0x0000);
    snd_soc_write(codec, AC97_REC_GAIN, 0x0000);
    snd_soc_write(codec, AC97_CENTER_LFE_MASTER, 0x0000);
    snd_soc_write(codec, AC97_SURROUND_MASTER, 0x0000);

    /*power on LFE/CENTER/Surround DACs*/
    ext_status = snd_soc_read(codec, AC97_EXTENDED_STATUS);
    snd_soc_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);

    return 0;

reset_err:
    snd_soc_codec_exit_regmap(codec);
err_free_ac97:
    snd_soc_free_ac97_codec(ac97);
    return ret;
}
static int uda134x_soc_probe(struct snd_soc_codec *codec)
{
	struct uda134x_priv *uda134x;
	struct uda134x_platform_data *pd = codec->card->dev->platform_data;
	const struct snd_soc_dapm_widget *widgets;
	unsigned num_widgets;

	int ret;

	printk(KERN_INFO "UDA134X SoC Audio Codec\n");

	if (!pd) {
		printk(KERN_ERR "UDA134X SoC codec: "
		       "missing L3 bitbang function\n");
		return -ENODEV;
	}

	switch (pd->model) {
	case UDA134X_UDA1340:
	case UDA134X_UDA1341:
	case UDA134X_UDA1344:
	case UDA134X_UDA1345:
		break;
	default:
		printk(KERN_ERR "UDA134X SoC codec: "
		       "unsupported model %d\n",
			pd->model);
		return -EINVAL;
	}

	uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
	if (uda134x == NULL)
		return -ENOMEM;
	snd_soc_codec_set_drvdata(codec, uda134x);

	codec->control_data = pd;

	if (pd->power)
		pd->power(1);

	uda134x_reset(codec);

	if (pd->is_powered_on_standby)
		uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
	else
		uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	if (pd->model == UDA134X_UDA1341) {
		widgets = uda1341_dapm_widgets;
		num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
	} else {
		widgets = uda1340_dapm_widgets;
		num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
	}

	ret = snd_soc_dapm_new_controls(&codec->dapm, widgets, num_widgets);
	if (ret) {
		printk(KERN_ERR "%s failed to register dapm controls: %d",
			__func__, ret);
		kfree(uda134x);
		return ret;
	}

	switch (pd->model) {
	case UDA134X_UDA1340:
	case UDA134X_UDA1344:
		ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
					ARRAY_SIZE(uda1340_snd_controls));
	break;
	case UDA134X_UDA1341:
		ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
					ARRAY_SIZE(uda1341_snd_controls));
	break;
	case UDA134X_UDA1345:
		ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
					ARRAY_SIZE(uda1345_snd_controls));
	break;
	default:
		printk(KERN_ERR "%s unknown codec type: %d",
			__func__, pd->model);
		kfree(uda134x);
		return -EINVAL;
	}

	if (ret < 0) {
		printk(KERN_ERR "UDA134X: failed to register controls\n");
		kfree(uda134x);
		return ret;
	}

	return 0;
}
Exemple #27
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;
}
Exemple #28
0
static int wm8961_register(struct wm8961_priv *wm8961)
{
	struct snd_soc_codec *codec = &wm8961->codec;
	int ret;
	u16 reg;

	if (wm8961_codec) {
		dev_err(codec->dev, "Another WM8961 is registered\n");
		ret = -EINVAL;
		goto err;
	}

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	snd_soc_codec_set_drvdata(codec, wm8961);
	codec->name = "WM8961";
	codec->owner = THIS_MODULE;
	codec->dai = &wm8961_dai;
	codec->num_dai = 1;
	codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
	codec->reg_cache = &wm8961->reg_cache;
	codec->bias_level = SND_SOC_BIAS_OFF;
	codec->set_bias_level = wm8961_set_bias_level;
	codec->volatile_register = wm8961_volatile_register;

	memcpy(codec->reg_cache, wm8961_reg_defaults,
	       sizeof(wm8961_reg_defaults));

	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
		goto err;
	}

	reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
	if (reg != 0x1801) {
		dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
		ret = -EINVAL;
		goto err;
	}

	/* This isn't volatile - readback doesn't correspond to write */
	reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
	dev_info(codec->dev, "WM8961 family %d revision %c\n",
		 (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
		 ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
		 + 'A');

	ret = wm8961_reset(codec);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to issue reset\n");
		return ret;
	}

	/* Enable class W */
	reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B);
	reg |= WM8961_CP_DYN_PWR_MASK;
	snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg);

	/* Latch volume update bits (right channel only, we always
	 * write both out) and default ZC on. */
	reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME);
	snd_soc_write(codec, WM8961_ROUT1_VOLUME,
		     reg | WM8961_LO1ZC | WM8961_OUT1VU);
	snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC);
	reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME);
	snd_soc_write(codec, WM8961_ROUT2_VOLUME,
		     reg | WM8961_SPKRZC | WM8961_SPKVU);
	snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC);

	reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME);
	snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU);
	reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
	snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU);

	/* Use soft mute by default */
	reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
	reg |= WM8961_DACSMM;
	snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);

	/* Use automatic clocking mode by default; for now this is all
	 * we support.
	 */
	reg = snd_soc_read(codec, WM8961_CLOCKING_3);
	reg &= ~WM8961_MANUAL_MODE;
	snd_soc_write(codec, WM8961_CLOCKING_3, reg);

	wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	wm8961_dai.dev = codec->dev;

	wm8961_codec = codec;

	ret = snd_soc_register_codec(codec);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
		return ret;
	}

	ret = snd_soc_register_dai(&wm8961_dai);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
		snd_soc_unregister_codec(codec);
		return ret;
	}

	return 0;

err:
	kfree(wm8961);
	return ret;
}
Exemple #29
0
static int wm8523_register(struct wm8523_priv *wm8523,
			   enum snd_soc_control_type control)
{
	int ret;
	struct snd_soc_codec *codec = &wm8523->codec;
	int i;

	if (wm8523_codec) {
		dev_err(codec->dev, "Another WM8523 is registered\n");
		return -EINVAL;
	}

	mutex_init(&codec->mutex);
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	snd_soc_codec_set_drvdata(codec, wm8523);
	codec->name = "WM8523";
	codec->owner = THIS_MODULE;
	codec->bias_level = SND_SOC_BIAS_OFF;
	codec->set_bias_level = wm8523_set_bias_level;
	codec->dai = &wm8523_dai;
	codec->num_dai = 1;
	codec->reg_cache_size = WM8523_REGISTER_COUNT;
	codec->reg_cache = &wm8523->reg_cache;
	codec->volatile_register = wm8523_volatile_register;

	wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
	wm8523->rate_constraint.count =
		ARRAY_SIZE(wm8523->rate_constraint_list);

	memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));

	ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
		goto err;
	}

	for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
		wm8523->supplies[i].supply = wm8523_supply_names[i];

	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies),
				 wm8523->supplies);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
		goto err;
	}

	ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
				    wm8523->supplies);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
		goto err_get;
	}

	ret = snd_soc_read(codec, WM8523_DEVICE_ID);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to read ID register\n");
		goto err_enable;
	}
	if (ret != wm8523_reg[WM8523_DEVICE_ID]) {
		dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret);
		ret = -EINVAL;
		goto err_enable;
	}

	ret = snd_soc_read(codec, WM8523_REVISION);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to read revision register\n");
		goto err_enable;
	}
	dev_info(codec->dev, "revision %c\n",
		 (ret & WM8523_CHIP_REV_MASK) + 'A');

	ret = wm8523_reset(codec);
	if (ret < 0) {
		dev_err(codec->dev, "Failed to issue reset\n");
		goto err_enable;
	}

	wm8523_dai.dev = codec->dev;

	/* Change some default settings - latch VU and enable ZC */
	wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
	wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;

	wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	/* Bias level configuration will have done an extra enable */
	regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);

	wm8523_codec = codec;

	ret = snd_soc_register_codec(codec);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register codec: %d\n", ret);
		return ret;
	}

	ret = snd_soc_register_dai(&wm8523_dai);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
		snd_soc_unregister_codec(codec);
		return ret;
	}

	return 0;

err_enable:
	regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
err_get:
	regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
err:
	kfree(wm8523);
	return ret;
}
Exemple #30
0
static int twl6040_probe(struct snd_soc_codec *codec)
{
	struct twl4030_codec_audio_data *twl_codec = codec->dev->platform_data;
	struct twl6040_data *priv;
	struct twl6040_jack_data *jack;
	int audpwron, naudint;
	struct input_dev *ip_dev;

#if defined(CONFIG_MACH_LGE_COSMO_REV_A)
	unsigned hsjack_gpio, hsjack_irq;
	int err;
#endif
	int ret = 0;
	u8 icrev = 0, intmr = TWL6040_ALLINT_MSK;
	int idx;

	for( idx = 0 ; idx < TWL6040_MUTE_DATA_MAX ; idx++ )
	{
		s_mute_data[idx].dai = 0;
		s_mute_data[idx].mute = 0;
	}
	
	priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
	if (priv == NULL)
		return -ENOMEM;
	snd_soc_codec_set_drvdata(codec, priv);

	priv->codec = codec;
	priv->dl_active = 0;
	priv->ul_active = 0;

	twl6040_i2c_read(TWL6040_REG_ASICREV, &icrev);

	if (twl_codec && (icrev > 0))
		audpwron = twl_codec->audpwron_gpio;
	else
		audpwron = -EINVAL;

#if defined(CONFIG_MACH_LGE_COSMO_REV_A)
	if (twl_codec){
		naudint = twl_codec->naudint_irq;
		hsjack_gpio = twl_codec->hsjack_gpio;
		hsjack_irq = twl_codec->hsjack_irq;
	}
	else {
		naudint = 0;
		hsjack_gpio = 0;
		hsjack_irq = 0;
	}
#else
	if (twl_codec)
		naudint = twl_codec->naudint_irq;
	else
		naudint = 0;
#endif

	priv->audpwron = audpwron;
	priv->naudint = naudint;
	
#if defined(CONFIG_MACH_LGE_COSMO_REV_A)
	priv->hsjack_gpio = hsjack_gpio;
	priv->hsjack_irq = hsjack_irq;
#endif
	init_completion(&priv->ready);

	/* Disable safe mode in SYS_NIRQ PAD */
//	omap_writew(0x0118, 0x4A1001A0);

	INIT_DELAYED_WORK(&priv->hsdet_dwork, twl6040_hs_jack_detect_dwork);
	INIT_DELAYED_WORK(&priv->hook_work, twl6040_hs_hook_detect_work);

#ifndef CONFIG_MACH_LGE_COSMOPOLITAN
	INIT_WORK(&priv->audint_work, twl6040_audint_work);
#endif

	ip_dev	= input_allocate_device();
	if(!ip_dev){
		dev_err(codec->dev, "failed to allocation hook input device");
		goto switch_err;
	}
	__set_bit(EV_KEY, ip_dev->evbit);
	__set_bit(EV_SYN, ip_dev->evbit);
	__set_bit(KEY_HOOK, ip_dev->keybit);
	ip_dev->name = "headset_hook";
	ip_dev->phys = "headset_hook/input0";
	priv->hs_jack.headset_input = ip_dev;
	input_register_device(priv->hs_jack.headset_input);

	/* 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;
	}
#if defined(CONFIG_MACH_LGE_COSMO_REV_A)
	/* GPIO request and direction set */
	if(gpio_is_valid(hsjack_gpio)) {
		err = gpio_request(hsjack_gpio, "ear_sense");
		if (err) {
			printk(KERN_ERR "%s: failed to request GPIO_%d\n",
				   __func__, hsjack_gpio);
			goto err_hs_gpio_request;
		}
		err = gpio_direction_input(hsjack_gpio);
		if (err) {
			printk(KERN_ERR "%s: failed to set direction GPIO_%d\n",
				   __func__, hsjack_gpio);
			goto err_hs_gpio_direction;
		}
	}

	/* IRQ request */
	err = request_irq(hsjack_irq,
					  hsjack_irq_handler,
					  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
					  "headset_detect",
					  codec);
	if (err) {
		printk(KERN_ERR "%s: failed to request irq (%d)\n",
			   __func__, hsjack_irq);
		goto err_hs_request_irq;
	}
#endif

	if (gpio_is_valid(audpwron)) {
		ret = gpio_request(audpwron, "audpwron");
		if (ret)
			goto gpio1_err;

		ret = gpio_direction_output(audpwron, 0);
		if (ret)
			goto gpio2_err;

		priv->codec_powered = 0;

		/* enable only codec ready interrupt */
		intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK );
		priv->intmask = intmr; 

		/* reset interrupt status to allow correct power up sequence */
		twl6040_read_reg_volatile(codec, TWL6040_REG_INTID);
	}
	twl6040_write(codec, TWL6040_REG_INTMR, intmr);

	if (naudint) {
		/* audio interrupt */
		ret = request_threaded_irq(naudint, NULL,
				twl6040_naudint_handler,
				IRQF_TRIGGER_LOW | IRQF_ONESHOT,
				"twl6040_codec", codec);
		if (ret)
			goto gpio2_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);

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

	cdc_tcxo_set_req_int(CDC_TCXO_CLK3, 0);

	/* TODO: read HS jack insertion status */

	return 0;

bias_err:
	if (naudint)
		free_irq(naudint, codec);
#if defined(CONFIG_MACH_LGE_COSMO_REV_A)
err_hs_request_irq:
err_hs_gpio_direction:
	if (gpio_is_valid(hsjack_gpio))
		gpio_free(hsjack_gpio);
err_hs_gpio_request:
#endif
gpio2_err:
	if (gpio_is_valid(audpwron))
		gpio_free(audpwron);
gpio1_err:
	switch_dev_unregister(&jack->sdev);
switch_err:
	kfree(priv);
	return ret;
}