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