Lines Matching +full:boost +full:- +full:bypass
1 // SPDX-License-Identifier: GPL-2.0-only
3 * wm8960.c -- WM8960 ALSA SoC Audio driver
5 * Copyright 2007-11 Wolfson Microelectronics, plc
28 /* R25 - Power 1 */
32 /* R26 - Power 2 */
37 /* R28 - Anti-pop 1 */
44 /* R29 - Anti-pop 2 */
176 if (wm8960->deemph) { in wm8960_set_deemph()
179 if (abs(deemph_settings[i] - wm8960->lrclk) < in wm8960_set_deemph()
180 abs(deemph_settings[best] - wm8960->lrclk)) in wm8960_set_deemph()
189 dev_dbg(component->dev, "Set deemphasis %d\n", val); in wm8960_set_deemph()
201 ucontrol->value.integer.value[0] = wm8960->deemph; in wm8960_get_deemph()
210 unsigned int deemph = ucontrol->value.integer.value[0]; in wm8960_put_deemph()
213 return -EINVAL; in wm8960_put_deemph()
215 wm8960->deemph = deemph; in wm8960_put_deemph()
220 static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
221 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1725, 75, 0);
222 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
223 static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
224 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
225 static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);
239 SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume",
241 SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume",
243 SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume",
245 SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume",
247 SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT1 Volume",
249 SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT1 Volume",
267 SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),
275 SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[2]),
276 SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[3]),
295 SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",
299 SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",
315 SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0),
325 SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0),
331 SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0),
337 SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0),
355 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
357 SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0,
408 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },
409 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },
410 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },
412 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer" },
413 { "Left Input Mixer", "Boost Switch", "LINPUT1" }, /* Really Boost Switch */
417 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },
418 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },
419 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },
421 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer" },
422 { "Right Input Mixer", "Boost Switch", "RINPUT1" }, /* Really Boost Switch */
430 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer" },
434 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" },
473 struct wm8960_data *pdata = &wm8960->pdata; in wm8960_add_widgets()
485 if (pdata && pdata->capless) { in wm8960_add_widgets()
504 list_for_each_entry(w, &component->card->widgets, list) { in wm8960_add_widgets()
505 if (w->dapm != dapm) in wm8960_add_widgets()
507 if (strcmp(w->name, "LOUT1 PGA") == 0) in wm8960_add_widgets()
508 wm8960->lout1 = w; in wm8960_add_widgets()
509 if (strcmp(w->name, "ROUT1 PGA") == 0) in wm8960_add_widgets()
510 wm8960->rout1 = w; in wm8960_add_widgets()
511 if (strcmp(w->name, "OUT3 VMID") == 0) in wm8960_add_widgets()
512 wm8960->out3 = w; in wm8960_add_widgets()
521 struct snd_soc_component *component = codec_dai->component; in wm8960_set_dai_fmt()
532 return -EINVAL; in wm8960_set_dai_fmt()
552 return -EINVAL; in wm8960_set_dai_fmt()
569 return -EINVAL; in wm8960_set_dai_fmt()
592 /* -1 for reserved value */
593 static const int sysclk_divs[] = { 1, -1, 2, -1 };
605 * wm8960_configure_sysclk - checks if there is a sysclk frequency available
607 * - sysclk = MCLK / sysclk_divs
608 * - lrclk = sysclk / dac_divs
609 * - 10 * bclk = sysclk / bclk_divs
622 * -1, in case no sysclk frequency available found
635 *bclk_idx = -1; in wm8960_configure_sysclk()
637 bclk = wm8960->bclk; in wm8960_configure_sysclk()
638 lrclk = wm8960->lrclk; in wm8960_configure_sysclk()
642 if (sysclk_divs[i] == -1) in wm8960_configure_sysclk()
649 diff = sysclk - bclk * bclk_divs[k] / 10; in wm8960_configure_sysclk()
673 * wm8960_configure_pll - checks if there is a PLL out frequency available
675 * - sysclk = lrclk * dac_divs
676 * - freq_out = sysclk * sysclk_divs
677 * - 10 * sysclk = bclk * bclk_divs
703 bclk = wm8960->bclk; in wm8960_configure_pll()
704 lrclk = wm8960->lrclk; in wm8960_configure_pll()
707 best_freq_out = -EINVAL; in wm8960_configure_pll()
708 *sysclk_idx = *dac_idx = *bclk_idx = -1; in wm8960_configure_pll()
711 if (sysclk_divs[i] == -1) in wm8960_configure_pll()
721 diff = sysclk - bclk * bclk_divs[k] / 10; in wm8960_configure_pll()
750 dev_dbg(component->dev, in wm8960_configure_clocking()
755 if (wm8960->clk_id != WM8960_SYSCLK_MCLK && !wm8960->freq_in) { in wm8960_configure_clocking()
756 dev_err(component->dev, "No MCLK configured\n"); in wm8960_configure_clocking()
757 return -EINVAL; in wm8960_configure_clocking()
760 freq_in = wm8960->freq_in; in wm8960_configure_clocking()
767 if (wm8960->clk_id == WM8960_SYSCLK_AUTO) { in wm8960_configure_clocking()
771 } else if (wm8960->sysclk) { in wm8960_configure_clocking()
772 freq_out = wm8960->sysclk; in wm8960_configure_clocking()
774 dev_err(component->dev, "No SYSCLK configured\n"); in wm8960_configure_clocking()
775 return -EINVAL; in wm8960_configure_clocking()
778 if (wm8960->clk_id != WM8960_SYSCLK_PLL) { in wm8960_configure_clocking()
782 } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) { in wm8960_configure_clocking()
783 dev_err(component->dev, "failed to configure clock\n"); in wm8960_configure_clocking()
784 return -EINVAL; in wm8960_configure_clocking()
790 dev_err(component->dev, "failed to configure clock via PLL\n"); in wm8960_configure_clocking()
813 struct snd_soc_component *component = dai->component; in wm8960_hw_params()
816 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in wm8960_hw_params()
819 wm8960->bclk = snd_soc_params_to_bclk(params); in wm8960_hw_params()
821 wm8960->bclk *= 2; in wm8960_hw_params()
841 dev_err(component->dev, "unsupported width %d\n", in wm8960_hw_params()
843 return -EINVAL; in wm8960_hw_params()
846 wm8960->lrclk = params_rate(params); in wm8960_hw_params()
861 wm8960->is_stream_in_use[tx] = true; in wm8960_hw_params()
863 if (!wm8960->is_stream_in_use[!tx]) in wm8960_hw_params()
872 struct snd_soc_component *component = dai->component; in wm8960_hw_free()
874 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; in wm8960_hw_free()
876 wm8960->is_stream_in_use[tx] = false; in wm8960_hw_free()
883 struct snd_soc_component *component = dai->component; in wm8960_mute()
906 if (!IS_ERR(wm8960->mclk)) { in wm8960_set_bias_level_out3()
907 ret = clk_prepare_enable(wm8960->mclk); in wm8960_set_bias_level_out3()
909 dev_err(component->dev, in wm8960_set_bias_level_out3()
929 if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1)) in wm8960_set_bias_level_out3()
932 if (!IS_ERR(wm8960->mclk)) in wm8960_set_bias_level_out3()
933 clk_disable_unprepare(wm8960->mclk); in wm8960_set_bias_level_out3()
944 regcache_sync(wm8960->regmap); in wm8960_set_bias_level_out3()
946 /* Enable anti-pop features */ in wm8960_set_bias_level_out3()
959 /* Disable anti-pop features */ in wm8960_set_bias_level_out3()
968 /* Enable anti-pop features */ in wm8960_set_bias_level_out3()
1005 if (wm8960->lout1 && wm8960->lout1->power) in wm8960_set_bias_level_capless()
1007 if (wm8960->rout1 && wm8960->rout1->power) in wm8960_set_bias_level_capless()
1009 if (wm8960->out3 && wm8960->out3->power) in wm8960_set_bias_level_capless()
1029 if (!IS_ERR(wm8960->mclk)) { in wm8960_set_bias_level_capless()
1030 ret = clk_prepare_enable(wm8960->mclk); in wm8960_set_bias_level_capless()
1032 dev_err(component->dev, in wm8960_set_bias_level_capless()
1050 if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1)) in wm8960_set_bias_level_capless()
1053 if (!IS_ERR(wm8960->mclk)) in wm8960_set_bias_level_capless()
1054 clk_disable_unprepare(wm8960->mclk); in wm8960_set_bias_level_capless()
1056 /* Enable anti-pop mode */ in wm8960_set_bias_level_capless()
1069 regcache_sync(wm8960->regmap); in wm8960_set_bias_level_capless()
1084 /* Disable anti-pop features */ in wm8960_set_bias_level_capless()
1143 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target); in pll_factors()
1151 pll_div->pre_div = 1; in pll_factors()
1154 pll_div->pre_div = 0; in pll_factors()
1158 return -EINVAL; in pll_factors()
1161 pll_div->n = Ndiv; in pll_factors()
1176 pll_div->k = K; in pll_factors()
1179 pll_div->n, pll_div->k, pll_div->pre_div); in pll_factors()
1229 struct snd_soc_component *component = codec_dai->component; in wm8960_set_dai_pll()
1232 wm8960->freq_in = freq_in; in wm8960_set_dai_pll()
1243 struct snd_soc_component *component = codec_dai->component; in wm8960_set_dai_clkdiv()
1268 return -EINVAL; in wm8960_set_dai_clkdiv()
1279 return wm8960->set_bias_level(component, level); in wm8960_set_bias_level()
1285 struct snd_soc_component *component = dai->component; in wm8960_set_dai_sysclk()
1300 return -EINVAL; in wm8960_set_dai_sysclk()
1303 wm8960->sysclk = freq; in wm8960_set_dai_sysclk()
1304 wm8960->clk_id = clk_id; in wm8960_set_dai_sysclk()
1327 .name = "wm8960-hifi",
1347 struct wm8960_data *pdata = &wm8960->pdata; in wm8960_probe()
1349 if (pdata->capless) in wm8960_probe()
1350 wm8960->set_bias_level = wm8960_set_bias_level_capless; in wm8960_probe()
1352 wm8960->set_bias_level = wm8960_set_bias_level_out3; in wm8960_probe()
1386 const struct device_node *np = i2c->dev.of_node; in wm8960_set_pdata_from_of()
1389 pdata->capless = true; in wm8960_set_pdata_from_of()
1391 if (of_property_read_bool(np, "wlf,shared-lrclk")) in wm8960_set_pdata_from_of()
1392 pdata->shared_lrclk = true; in wm8960_set_pdata_from_of()
1394 of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg, in wm8960_set_pdata_from_of()
1395 ARRAY_SIZE(pdata->gpio_cfg)); in wm8960_set_pdata_from_of()
1397 of_property_read_u32_array(np, "wlf,hp-cfg", pdata->hp_cfg, in wm8960_set_pdata_from_of()
1398 ARRAY_SIZE(pdata->hp_cfg)); in wm8960_set_pdata_from_of()
1404 struct wm8960_data *pdata = dev_get_platdata(&i2c->dev); in wm8960_i2c_probe()
1408 wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct wm8960_priv), in wm8960_i2c_probe()
1411 return -ENOMEM; in wm8960_i2c_probe()
1413 wm8960->mclk = devm_clk_get(&i2c->dev, "mclk"); in wm8960_i2c_probe()
1414 if (IS_ERR(wm8960->mclk)) { in wm8960_i2c_probe()
1415 if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER) in wm8960_i2c_probe()
1416 return -EPROBE_DEFER; in wm8960_i2c_probe()
1419 wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap); in wm8960_i2c_probe()
1420 if (IS_ERR(wm8960->regmap)) in wm8960_i2c_probe()
1421 return PTR_ERR(wm8960->regmap); in wm8960_i2c_probe()
1424 memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data)); in wm8960_i2c_probe()
1425 else if (i2c->dev.of_node) in wm8960_i2c_probe()
1426 wm8960_set_pdata_from_of(i2c, &wm8960->pdata); in wm8960_i2c_probe()
1428 ret = wm8960_reset(wm8960->regmap); in wm8960_i2c_probe()
1430 dev_err(&i2c->dev, "Failed to issue reset\n"); in wm8960_i2c_probe()
1434 if (wm8960->pdata.shared_lrclk) { in wm8960_i2c_probe()
1435 ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, in wm8960_i2c_probe()
1438 dev_err(&i2c->dev, "Failed to enable LRCM: %d\n", in wm8960_i2c_probe()
1445 regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x100, 0x100); in wm8960_i2c_probe()
1446 regmap_update_bits(wm8960->regmap, WM8960_RINVOL, 0x100, 0x100); in wm8960_i2c_probe()
1447 regmap_update_bits(wm8960->regmap, WM8960_LADC, 0x100, 0x100); in wm8960_i2c_probe()
1448 regmap_update_bits(wm8960->regmap, WM8960_RADC, 0x100, 0x100); in wm8960_i2c_probe()
1449 regmap_update_bits(wm8960->regmap, WM8960_LDAC, 0x100, 0x100); in wm8960_i2c_probe()
1450 regmap_update_bits(wm8960->regmap, WM8960_RDAC, 0x100, 0x100); in wm8960_i2c_probe()
1451 regmap_update_bits(wm8960->regmap, WM8960_LOUT1, 0x100, 0x100); in wm8960_i2c_probe()
1452 regmap_update_bits(wm8960->regmap, WM8960_ROUT1, 0x100, 0x100); in wm8960_i2c_probe()
1453 regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100); in wm8960_i2c_probe()
1454 regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100); in wm8960_i2c_probe()
1457 regmap_update_bits(wm8960->regmap, WM8960_IFACE2, 1 << 6, in wm8960_i2c_probe()
1458 wm8960->pdata.gpio_cfg[0] << 6); in wm8960_i2c_probe()
1459 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 0xF << 4, in wm8960_i2c_probe()
1460 wm8960->pdata.gpio_cfg[1] << 4); in wm8960_i2c_probe()
1463 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 3 << 2, in wm8960_i2c_probe()
1464 wm8960->pdata.hp_cfg[0] << 2); in wm8960_i2c_probe()
1465 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, 3 << 5, in wm8960_i2c_probe()
1466 wm8960->pdata.hp_cfg[1] << 5); in wm8960_i2c_probe()
1467 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL1, 3, in wm8960_i2c_probe()
1468 wm8960->pdata.hp_cfg[2]); in wm8960_i2c_probe()
1472 ret = devm_snd_soc_register_component(&i2c->dev, in wm8960_i2c_probe()