• Home
  • Raw
  • Download

Lines Matching +full:adc +full:- +full:diff +full:- +full:channels

2  * wm8978.c  --  WM8978 ALSA SoC Audio Codec driver
4 * Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 * Copyright 2006-2009 Wolfson Microelectronics PLC.
109 static const char *wm8978_companding[] = {"Off", "NC", "u-law", "A-law"};
136 static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
137 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
138 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0);
139 static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0);
140 static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1);
148 SOC_ENUM("ADC Companding", adc_compand),
159 SOC_DOUBLE("ADC Inversion Switch", WM8978_ADC_CONTROL, 0, 1, 1, 0),
161 SOC_DOUBLE_R_TLV("ADC Volume",
215 /* OUT1 - Headphones */
223 /* OUT2 - Speakers */
231 /* OUT3/4 - Line Output */
259 /* DAC / ADC oversampling */
262 SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL,
298 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture",
300 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture",
377 {"Right ADC", NULL, "Right Boost Mixer"},
383 {"Left ADC", NULL, "Left Boost Mixer"},
420 pll_div->div2 = 1; in pll_factors()
423 pll_div->div2 = 0; in pll_factors()
427 dev_warn(component->dev, in pll_factors()
431 pll_div->n = n_div; in pll_factors()
432 n_mod = target - source * n_div; in pll_factors()
439 pll_div->k = k; in pll_factors()
467 return -EINVAL; in wm8978_enum_mclk()
478 unsigned int f_opclk = wm8978->f_opclk, f_mclk = wm8978->f_mclk, in wm8978_configure_pll()
479 f_256fs = wm8978->f_256fs; in wm8978_configure_pll()
483 return -EINVAL; in wm8978_configure_pll()
488 wm8978->mclk_idx = -1; in wm8978_configure_pll()
500 return -EINVAL; in wm8978_configure_pll()
504 opclk_div = (3 * f_mclk / 4 + f_opclk - 1) / f_opclk; in wm8978_configure_pll()
508 dev_dbg(component->dev, "%s: OPCLKDIV=%d\n", __func__, opclk_div); in wm8978_configure_pll()
511 (opclk_div - 1) << 4); in wm8978_configure_pll()
513 wm8978->f_pllout = f_opclk * opclk_div; in wm8978_configure_pll()
525 int idx = wm8978_enum_mclk(f_256fs, f_mclk, &wm8978->f_pllout); in wm8978_configure_pll()
529 wm8978->mclk_idx = idx; in wm8978_configure_pll()
531 return -EINVAL; in wm8978_configure_pll()
534 f2 = wm8978->f_pllout * 4; in wm8978_configure_pll()
536 dev_dbg(component->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, in wm8978_configure_pll()
537 wm8978->f_mclk, wm8978->f_pllout); in wm8978_configure_pll()
539 pll_factors(component, &pll_div, f2, wm8978->f_mclk); in wm8978_configure_pll()
541 dev_dbg(component->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", in wm8978_configure_pll()
568 struct snd_soc_component *component = codec_dai->component; in wm8978_set_dai_clkdiv()
574 wm8978->f_opclk = div; in wm8978_set_dai_clkdiv()
576 if (wm8978->f_mclk) in wm8978_set_dai_clkdiv()
581 * user-requested OPCLK frquency as good as possible. in wm8978_set_dai_clkdiv()
588 * find an exact MCLK divider configuration - it will in wm8978_set_dai_clkdiv()
595 return -EINVAL; in wm8978_set_dai_clkdiv()
599 return -EINVAL; in wm8978_set_dai_clkdiv()
602 dev_dbg(component->dev, "%s: ID %d, value %u\n", __func__, div_id, div); in wm8978_set_dai_clkdiv()
613 struct snd_soc_component *component = codec_dai->component; in wm8978_set_dai_sysclk()
617 dev_dbg(component->dev, "%s: ID %d, freq %u\n", __func__, clk_id, freq); in wm8978_set_dai_sysclk()
620 wm8978->f_mclk = freq; in wm8978_set_dai_sysclk()
623 if (wm8978->f_opclk) in wm8978_set_dai_sysclk()
629 wm8978->sysclk = clk_id; in wm8978_set_dai_sysclk()
632 if (wm8978->sysclk == WM8978_PLL && (!freq || clk_id == WM8978_MCLK)) { in wm8978_set_dai_sysclk()
636 /* GPIO1 into default mode as input - before configuring PLL */ in wm8978_set_dai_sysclk()
641 wm8978->sysclk = WM8978_MCLK; in wm8978_set_dai_sysclk()
642 wm8978->f_pllout = 0; in wm8978_set_dai_sysclk()
643 wm8978->f_opclk = 0; in wm8978_set_dai_sysclk()
650 * Set ADC and Voice DAC format.
654 struct snd_soc_component *component = codec_dai->component; in wm8978_set_dai_fmt()
662 dev_dbg(component->dev, "%s\n", __func__); in wm8978_set_dai_fmt()
673 return -EINVAL; in wm8978_set_dai_fmt()
690 return -EINVAL; in wm8978_set_dai_fmt()
707 return -EINVAL; in wm8978_set_dai_fmt()
723 struct snd_soc_component *component = dai->component; in wm8978_hw_params()
732 unsigned int f_sel, diff, diff_best = INT_MAX; in wm8978_hw_params() local
735 if (!wm8978->f_mclk) in wm8978_hw_params()
736 return -EINVAL; in wm8978_hw_params()
776 wm8978->f_256fs = params_rate(params) * 256; in wm8978_hw_params()
778 if (wm8978->sysclk == WM8978_MCLK) { in wm8978_hw_params()
779 wm8978->mclk_idx = -1; in wm8978_hw_params()
780 f_sel = wm8978->f_mclk; in wm8978_hw_params()
782 if (!wm8978->f_opclk) { in wm8978_hw_params()
788 f_sel = wm8978->f_pllout; in wm8978_hw_params()
791 if (wm8978->mclk_idx < 0) { in wm8978_hw_params()
793 if (f_sel < wm8978->f_256fs || f_sel > 12 * wm8978->f_256fs) in wm8978_hw_params()
794 return -EINVAL; in wm8978_hw_params()
797 diff = abs(wm8978->f_256fs * 3 - in wm8978_hw_params()
800 if (diff < diff_best) { in wm8978_hw_params()
801 diff_best = diff; in wm8978_hw_params()
805 if (!diff) in wm8978_hw_params()
810 best = wm8978->mclk_idx; in wm8978_hw_params()
811 diff = 0; in wm8978_hw_params()
814 if (diff) in wm8978_hw_params()
815 dev_warn(component->dev, "Imprecise sampling rate: %uHz%s\n", in wm8978_hw_params()
817 wm8978->sysclk == WM8978_MCLK ? in wm8978_hw_params()
820 dev_dbg(component->dev, "%s: width %d, rate %u, MCLK divisor #%d\n", __func__, in wm8978_hw_params()
829 if (wm8978->sysclk != current_clk_id) { in wm8978_hw_params()
830 if (wm8978->sysclk == WM8978_PLL) in wm8978_hw_params()
844 struct snd_soc_component *component = dai->component; in wm8978_mute()
846 dev_dbg(component->dev, "%s: %d\n", __func__, mute); in wm8978_mute()
882 /* Preserve PLL - OPCLK may be used by someone */ in wm8978_set_bias_level()
889 dev_dbg(component->dev, "%s: %d, %x\n", __func__, level, power1); in wm8978_set_bias_level()
907 .name = "wm8978-hifi",
934 regcache_mark_dirty(wm8978->regmap); in wm8978_suspend()
944 regcache_sync(wm8978->regmap); in wm8978_resume()
948 if (wm8978->f_pllout) in wm8978_resume()
956 * These registers contain an "update" bit - bit 8. This means, for example,
957 * that one can write new DAC digital volume for both channels, but only when
958 * the update bit is set, will also the volume be updated - simultaneously for
959 * both channels.
983 wm8978->sysclk = WM8978_PLL; in wm8978_probe()
1031 wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv), in wm8978_i2c_probe()
1034 return -ENOMEM; in wm8978_i2c_probe()
1036 wm8978->regmap = devm_regmap_init_i2c(i2c, &wm8978_regmap_config); in wm8978_i2c_probe()
1037 if (IS_ERR(wm8978->regmap)) { in wm8978_i2c_probe()
1038 ret = PTR_ERR(wm8978->regmap); in wm8978_i2c_probe()
1039 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); in wm8978_i2c_probe()
1046 ret = regmap_write(wm8978->regmap, WM8978_RESET, 0); in wm8978_i2c_probe()
1048 dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); in wm8978_i2c_probe()
1052 ret = devm_snd_soc_register_component(&i2c->dev, in wm8978_i2c_probe()
1055 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); in wm8978_i2c_probe()