static int twl6040_vib_power(bool on)
{
	int ret = 0;

	mutex_lock(&misc_data->power_mutex);

	cancel_delayed_work_sync(&misc_data->power_work);

	if (on == misc_data->powered)
		goto out;

	if (on) {
		/* vibra power-up is immediate */
		ret = twl6040_enable(misc_data->twl6040);
		if (ret)
			goto out;
		misc_data->powered = true;
	} else {
		/* vibra power-down is deferred */
		schedule_delayed_work(&misc_data->power_work,
			msecs_to_jiffies(TWL6040_VIB_POWER_DOWN_DELAY));
	}

out:
	mutex_unlock(&misc_data->power_mutex);
	return ret;
}
Example #2
0
static int archos_omap4_mcpdm_startup(struct snd_pcm_substream *substream)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_codec *codec = rtd->codec;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct twl6040 *twl6040 = codec->control_data;
    int clk_id, freq, ret = 0;

    /* TWL6040 supplies McPDM PAD_CLKS */
    ret = twl6040_enable(twl6040);
    if (ret) {
        printk(KERN_ERR "failed to enable TWL6040\n");
        return ret;
    }

    if (twl6040_power_mode) {
        clk_id = TWL6040_HPPLL_ID;
        freq = 19200000;
        _enable_master_clock();
        ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
                                     SND_SOC_CLOCK_IN);
    } else {
        clk_id = TWL6040_LPPLL_ID;
        freq = 32768;
        /* set the codec mclk */
        ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
                                     SND_SOC_CLOCK_IN);
        _disable_master_clock();
    }

    if (ret)
        printk(KERN_ERR "can't set codec system clock\n");

    return ret;
}
Example #3
0
static int sdp4430_dmic_startup(struct snd_pcm_substream *substream)
{
	struct twl6040 *twl6040 = twl6040_codec->control_data;
	/* In order for the DMIC's to use the PAD CLOCKS, the twl6040
	 * must be powered up, since it supplies the clock source.
	 */
	return twl6040_enable(twl6040);
}
Example #4
0
static int vib_resume(struct device *dev)
{
	struct vib_data *data = dev_get_drvdata(dev);

	twl6040_enable(data->twl6040);

	return 0;
}
Example #5
0
static int sdp4430_mcpdm_twl6040_pre(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_codec *codec = rtd->codec;
	struct twl6040 *twl6040 = codec->control_data;

	/* TWL6040 supplies McPDM PAD_CLKS */
	return twl6040_enable(twl6040);
}
static int sdp4430_mcpdm_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct twl6040 *twl6040 = codec->control_data;
	int clk_id, freq, ret;

	/* TWL6040 supplies McPDM PAD_CLKS */
	ret = twl6040_enable(twl6040);
	if (ret) {
		printk(KERN_ERR "failed to enable TWL6040\n");
		return ret;
	}

	if (twl6040_power_mode) {
		clk_id = TWL6040_HPPLL_ID;
		/*freq = 38400000;*/
		freq = 26000000;

		/*
		 * TWL6040 requires MCLK to be active as long as
		 * high-performance mode is in use. Glitch-free mux
		 * cannot tolerate MCLK gating
		 */
		ret = cdc_tcxo_set_req_int(CDC_TCXO_CLK2, 1);
		if (ret) {
			printk(KERN_ERR "failed to enable twl6040 MCLK\n");
			goto err;
		}
	} else {
		clk_id = TWL6040_LPPLL_ID;
		freq = 32768;
	}

	/* set the codec mclk */
	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
				SND_SOC_CLOCK_IN);
	if (ret) {
		printk(KERN_ERR "can't set codec system clock\n");
		goto err;
	}

	/* low-power mode uses 32k clock, MCLK is not required */
	if (!twl6040_power_mode) {
		ret = cdc_tcxo_set_req_int(CDC_TCXO_CLK2, 0);
		if (ret)
			printk(KERN_ERR "failed to disable twl6040 MCLK\n");
	}

	return 0;

err:
	twl6040_disable(twl6040);
	return ret;
}
Example #7
0
static int vib_probe(struct platform_device *pdev)
{
	struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
	struct vib_data *data;
	int ret = 0;

	if (!pdata) {
		ret = -EBUSY;
		goto err0;
	}

	data = kzalloc(sizeof(struct vib_data), GFP_KERNEL);
	if (!data) {
		ret = -ENOMEM;
		goto err0;
	}

	data->pdata = pdata;
	data->twl6040 = dev_get_drvdata(pdev->dev.parent);

	INIT_WORK(&data->vib_work, vib_update);

	hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

	data->timer.function = vib_timer_func;
	spin_lock_init(&data->lock);

	data->dev.name = "vibrator";
	data->dev.get_time = vib_get_time;
	data->dev.enable = vib_enable;
	ret = timed_output_dev_register(&data->dev);
	if (ret < 0)
		goto err1;

	if (data->pdata->init)
		ret = data->pdata->init();
	if (ret < 0)
		goto err2;

	misc_data = data;
	platform_set_drvdata(pdev, data);

	twl6040_enable(data->twl6040);
	vib_enable(&data->dev, data->pdata->initial_vibrate);

	return 0;

err2:
	timed_output_dev_unregister(&data->dev);
err1:
	kfree(data);
err0:
	return ret;
}
Example #8
0
static int sdp4430_mcpdm_twl6040_pre(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_codec *codec = rtd->codec;
	struct twl6040 *twl6040 = codec->control_data;
	int ret;

	/* enable external 32kHz clock */
	ret = regulator_enable(twl6040_clk32kreg);
	if (ret) {
		printk(KERN_ERR "failed to enable TWL6040 CLK32K\n");
		return ret;
	}

	/* disable internal 32kHz oscillator */
	twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_CLK32KSEL);

	/* TWL6040 supplies McPDM PAD_CLKS */
	return twl6040_enable(twl6040);
}
Example #9
0
static int twl6040_set_bias_level(struct snd_soc_codec *codec,
				enum snd_soc_bias_level level)
{
	struct twl6040_codec *twl6040 = codec->control_data;
	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);

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

		twl6040_enable(twl6040);
		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;

		twl6040_disable(twl6040);
		priv->codec_powered = 0;
		break;
	}

	priv->pll = twl6040_get_pll(twl6040);
	priv->sysclk = twl6040_get_sysclk(twl6040);
	codec->dapm->bias_level = level;

	return 0;
}
Example #10
0
static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
{
	struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
	struct vibra_info *info;
	int ret;

	if (!pdata) {
		dev_err(&pdev->dev, "platform_data not available\n");
		return -EINVAL;
	}

	info = kzalloc(sizeof(*info), GFP_KERNEL);
	if (!info) {
		dev_err(&pdev->dev, "couldn't allocate memory \n");
		return -ENOMEM;
	}

	info->dev = &pdev->dev;
	info->coexist = pdata->coexist;
	info->twl6040 = dev_get_drvdata(pdev->dev.parent);
	INIT_WORK(&info->play_work, vibra_play_work);

	info->input_dev = input_allocate_device();
	if (info->input_dev == NULL) {
		dev_err(&pdev->dev, "couldn't allocate input device\n");
		ret = -ENOMEM;
		goto err_kzalloc;
	}

	input_set_drvdata(info->input_dev, info);

	info->input_dev->name = "twl6040:vibrator";
	info->input_dev->id.version = 1;
	info->input_dev->dev.parent = pdev->dev.parent;
	info->input_dev->open = twl6040_vibra_open;
	info->input_dev->close = twl6040_vibra_close;
	__set_bit(FF_RUMBLE, info->input_dev->ffbit);

	ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
	if (ret < 0) {
		dev_err(&pdev->dev, "couldn't register vibrator to FF\n");
		goto err_ialloc;
	}

	ret = input_register_device(info->input_dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "couldn't register input device\n");
		goto err_iff;
	}

	platform_set_drvdata(pdev, info);

	twl6040_enable(info->twl6040);

	return 0;

err_iff:
	input_ff_destroy(info->input_dev);
err_ialloc:
	input_free_device(info->input_dev);
err_kzalloc:
	kfree(info);
	return ret;
}