예제 #1
0
static int wm8993_remove(struct snd_soc_codec *codec)
{
	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);

	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
	return 0;
}
예제 #2
0
static int wm8993_resume(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = socdev->card->codec;
	struct wm8993_priv *wm8993 = codec->private_data;
	int ret;

	wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	/* Restart the FLL? */
	if (wm8993->fll_fout) {
		int fll_fout = wm8993->fll_fout;
		int fll_fref  = wm8993->fll_fref;

		wm8993->fll_fref = 0;
		wm8993->fll_fout = 0;

		ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src,
				     fll_fref, fll_fout);
		if (ret != 0)
			dev_err(codec->dev, "Failed to restart FLL\n");
	}

	return 0;
}
예제 #3
0
파일: wm8993.c 프로젝트: Apaisal/linux
static int wm8993_remove(struct snd_soc_codec *codec)
{
	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);

	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
	return 0;
}
예제 #4
0
static int wm8993_i2c_remove(struct i2c_client *client)
{
	struct wm8993_priv *wm8993 = i2c_get_clientdata(client);

	snd_soc_unregister_codec(&wm8993->codec);
	snd_soc_unregister_dai(&wm8993_dai);

	wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
	kfree(wm8993);

	return 0;
}
예제 #5
0
static int wm8993_suspend(struct snd_soc_codec *codec)
{
	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
	int fll_fout = wm8993->fll_fout;
	int fll_fref  = wm8993->fll_fref;
	int ret;

	/* Stop the FLL in an orderly fashion */
	ret = _wm8993_set_fll(codec, 0, 0, 0, 0);
	if (ret != 0) {
		dev_err(codec->dev, "Failed to stop FLL\n");
		return ret;
	}

	wm8993->fll_fout = fll_fout;
	wm8993->fll_fref = fll_fref;

	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);

	return 0;
}
예제 #6
0
static int wm8993_resume(struct snd_soc_codec *codec)
{
	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
	int ret;

	wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);

	/* Restart the FLL? */
	if (wm8993->fll_fout) {
		int fll_fout = wm8993->fll_fout;
		int fll_fref  = wm8993->fll_fref;

		wm8993->fll_fref = 0;
		wm8993->fll_fout = 0;

		ret = _wm8993_set_fll(codec, 0, wm8993->fll_src,
				     fll_fref, fll_fout);
		if (ret != 0)
			dev_err(codec->dev, "Failed to restart FLL\n");
	}

	return 0;
}
예제 #7
0
static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = socdev->card->codec;
	struct wm8993_priv *wm8993 = codec->private_data;
	int fll_fout = wm8993->fll_fout;
	int fll_fref  = wm8993->fll_fref;
	int ret;

	/* Stop the FLL in an orderly fashion */
	ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0);
	if (ret != 0) {
		dev_err(&pdev->dev, "Failed to stop FLL\n");
		return ret;
	}

	wm8993->fll_fout = fll_fout;
	wm8993->fll_fref = fll_fref;

	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);

	return 0;
}
예제 #8
0
static int wm8993_probe(struct snd_soc_codec *codec)
{
	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	int ret;

	wm8993->hubs_data.hp_startup_mode = 1;
	wm8993->hubs_data.dcs_codes_l = -2;
	wm8993->hubs_data.dcs_codes_r = -2;
	wm8993->hubs_data.series_startup = 1;

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

	/* Latch volume update bits and default ZC on */
	snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
			    WM8993_DAC_VU, WM8993_DAC_VU);
	snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
			    WM8993_ADC_VU, WM8993_ADC_VU);

	/* Manualy manage the HPOUT sequencing for independent stereo
	 * control. */
	snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
			    WM8993_HPOUT1_AUTO_PU, 0);

	/* Use automatic clock configuration */
	snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);

	wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
				      wm8993->pdata.lineout2_diff,
				      wm8993->pdata.lineout1fb,
				      wm8993->pdata.lineout2fb,
				      wm8993->pdata.jd_scthr,
				      wm8993->pdata.jd_thr,
				      wm8993->pdata.micbias1_delay,
				      wm8993->pdata.micbias2_delay,
				      wm8993->pdata.micbias1_lvl,
				      wm8993->pdata.micbias2_lvl);

	ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	if (ret != 0)
		return ret;

	snd_soc_add_codec_controls(codec, wm8993_snd_controls,
			     ARRAY_SIZE(wm8993_snd_controls));
	if (wm8993->pdata.num_retune_configs != 0) {
		dev_dbg(codec->dev, "Using ReTune Mobile\n");
	} else {
		dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
		snd_soc_add_codec_controls(codec, wm8993_eq_controls,
				     ARRAY_SIZE(wm8993_eq_controls));
	}

	snd_soc_dapm_new_controls(dapm, wm8993_dapm_widgets,
				  ARRAY_SIZE(wm8993_dapm_widgets));
	wm_hubs_add_analogue_controls(codec);

	snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
	wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
				    wm8993->pdata.lineout2_diff);

	/* If the line outputs are differential then we aren't presenting
	 * VMID as an output and can disable it.
	 */
	if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
		codec->dapm.idle_bias_off = 1;

	return 0;

}
예제 #9
0
static int wm8993_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct wm8993_priv *wm8993;
	struct snd_soc_codec *codec;
	unsigned int val;
	int ret;
	int i;

	if (wm8993_codec) {
		dev_err(&i2c->dev, "A WM8993 is already registered\n");
		return -EINVAL;
	}

	wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
	if (wm8993 == NULL)
		return -ENOMEM;

	codec = &wm8993->codec;
	if (i2c->dev.platform_data)
		memcpy(&wm8993->pdata, i2c->dev.platform_data,
		       sizeof(wm8993->pdata));

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

	codec->name = "WM8993";
	codec->volatile_register = wm8993_volatile;
	codec->reg_cache = wm8993->reg_cache;
	codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
	codec->bias_level = SND_SOC_BIAS_OFF;
	codec->set_bias_level = wm8993_set_bias_level;
	codec->dai = &wm8993_dai;
	codec->num_dai = 1;
	codec->private_data = wm8993;

	wm8993->hubs_data.hp_startup_mode = 1;
	wm8993->hubs_data.dcs_codes = -2;

	memcpy(wm8993->reg_cache, wm8993_reg_defaults,
	       sizeof(wm8993->reg_cache));

	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;
	}

	i2c_set_clientdata(i2c, wm8993);
	codec->control_data = i2c;
	wm8993_codec = codec;

	codec->dev = &i2c->dev;

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

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

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

	val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
	if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
		dev_err(codec->dev, "Invalid ID register value %x\n", val);
		ret = -EINVAL;
		goto err_enable;
	}

	ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
	if (ret != 0)
		goto err_enable;

	codec->cache_only = 1;

	/* By default we're using the output mixers */
	wm8993->class_w_users = 2;

	/* Latch volume update bits and default ZC on */
	snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
			    WM8993_DAC_VU, WM8993_DAC_VU);
	snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
			    WM8993_ADC_VU, WM8993_ADC_VU);

	/* Manualy manage the HPOUT sequencing for independent stereo
	 * control. */
	snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
			    WM8993_HPOUT1_AUTO_PU, 0);

	/* Use automatic clock configuration */
	snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);

	wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
				      wm8993->pdata.lineout2_diff,
				      wm8993->pdata.lineout1fb,
				      wm8993->pdata.lineout2fb,
				      wm8993->pdata.jd_scthr,
				      wm8993->pdata.jd_thr,
				      wm8993->pdata.micbias1_lvl,
				      wm8993->pdata.micbias2_lvl);
			     
	ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	if (ret != 0)
		goto err_enable;

	wm8993_dai.dev = codec->dev;

	ret = snd_soc_register_dai(&wm8993_dai);
	if (ret != 0)
		goto err_bias;

	ret = snd_soc_register_codec(codec);

	return 0;

err_bias:
	wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
err_enable:
	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
err_get:
	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
err:
	wm8993_codec = NULL;
	kfree(wm8993);
	return ret;
}
예제 #10
0
파일: wm8993.c 프로젝트: Apaisal/linux
static int wm8993_probe(struct snd_soc_codec *codec)
{
	struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	int ret, i, val;

	wm8993->hubs_data.hp_startup_mode = 1;
	wm8993->hubs_data.dcs_codes_l = -2;
	wm8993->hubs_data.dcs_codes_r = -2;
	wm8993->hubs_data.series_startup = 1;

	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;
	}

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

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

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

	val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
	if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
		dev_err(codec->dev, "Invalid ID register value %x\n", val);
		ret = -EINVAL;
		goto err_enable;
	}

	ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
	if (ret != 0)
		goto err_enable;

	codec->cache_only = 1;

	/* By default we're using the output mixers */
	wm8993->class_w_users = 2;

	/* Latch volume update bits and default ZC on */
	snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
			    WM8993_DAC_VU, WM8993_DAC_VU);
	snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
			    WM8993_ADC_VU, WM8993_ADC_VU);

	/* Manualy manage the HPOUT sequencing for independent stereo
	 * control. */
	snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
			    WM8993_HPOUT1_AUTO_PU, 0);

	/* Use automatic clock configuration */
	snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);

	wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
				      wm8993->pdata.lineout2_diff,
				      wm8993->pdata.lineout1fb,
				      wm8993->pdata.lineout2fb,
				      wm8993->pdata.jd_scthr,
				      wm8993->pdata.jd_thr,
				      wm8993->pdata.micbias1_lvl,
				      wm8993->pdata.micbias2_lvl);

	ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	if (ret != 0)
		goto err_enable;

	snd_soc_add_controls(codec, wm8993_snd_controls,
			     ARRAY_SIZE(wm8993_snd_controls));
	if (wm8993->pdata.num_retune_configs != 0) {
		dev_dbg(codec->dev, "Using ReTune Mobile\n");
	} else {
		dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
		snd_soc_add_controls(codec, wm8993_eq_controls,
				     ARRAY_SIZE(wm8993_eq_controls));
	}

	snd_soc_dapm_new_controls(dapm, wm8993_dapm_widgets,
				  ARRAY_SIZE(wm8993_dapm_widgets));
	wm_hubs_add_analogue_controls(codec);

	snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
	wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
				    wm8993->pdata.lineout2_diff);

	return 0;

err_enable:
	regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
err_get:
	regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
	return ret;
}