Lines Matching +full:dac +full:- +full:current +full:- +full:limit +full:- +full:low
1 // SPDX-License-Identifier: GPL-2.0-only
3 * es8316.c -- es8316 ALSA SoC audio driver
6 * Authors: David Yang <yangxiaohua@everest-semi.com>,
21 #include <sound/soc-dapm.h>
51 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9600, 50, 1);
52 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(adc_vol_tlv, -9600, 50, 1);
53 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_max_gain_tlv, -650, 150, 0);
54 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(alc_min_gain_tlv, -1200, 150, 0);
57 0, 10, TLV_DB_SCALE_ITEM(-1650, 150, 0),
58 11, 11, TLV_DB_SCALE_ITEM(-150, 0, 0),
62 0, 4, TLV_DB_SCALE_ITEM(-1200, 150, 0),
63 8, 11, TLV_DB_SCALE_ITEM(-450, 150, 0),
67 0, 0, TLV_DB_SCALE_ITEM(-350, 0, 0),
76 0, 0, TLV_DB_SCALE_ITEM(-4800, 0, 0),
77 1, 3, TLV_DB_SCALE_ITEM(-2400, 1200, 0),
100 SOC_DOUBLE_R_TLV("DAC Playback Volume", ES8316_DAC_VOLL,
102 SOC_SINGLE("DAC Soft Ramp Switch", ES8316_DAC_SET1, 4, 1, 1),
103 SOC_SINGLE("DAC Soft Ramp Rate", ES8316_DAC_SET1, 2, 4, 0),
104 SOC_SINGLE("DAC Notch Filter Switch", ES8316_DAC_SET2, 6, 1, 0),
105 SOC_SINGLE("DAC Double Fs Switch", ES8316_DAC_SET2, 7, 1, 0),
106 SOC_SINGLE("DAC Stereo Enhancement", ES8316_DAC_SET3, 0, 7, 0),
107 SOC_SINGLE("DAC Mono Mix Switch", ES8316_DAC_SET3, 3, 1, 0),
137 "lin1-rin1",
138 "lin2-rin2",
139 "lin1-rin1 with 20db Boost",
140 "lin2-rin2 with 20db Boost"
154 "dmic data at low level",
167 "lin1-rin1",
168 "lin2-rin2",
169 "lin-rin with Boost",
170 "lin-rin with Boost and PGA"
188 SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH, 7, 1, 0),
192 SOC_DAPM_SINGLE("Right DAC Switch", ES8316_HPMIX_SWITCH, 3, 1, 0),
195 /* DAC data source mux */
237 SND_SOC_DAPM_MUX("DAC Source Mux", SND_SOC_NOPM, 0, 0,
240 SND_SOC_DAPM_SUPPLY("DAC Vref", ES8316_SYS_PDN, 0, 1, NULL, 0),
241 SND_SOC_DAPM_SUPPLY("DAC Clock", ES8316_CLKMGR_CLKSW, 2, 0, NULL, 0),
242 SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN, 0, 1),
243 SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN, 4, 1),
297 {"Differential Mux", "lin1-rin1", "MIC1"},
298 {"Differential Mux", "lin2-rin2", "MIC2"},
307 * the DAC clock must be running for the ADC to work.
309 {"Mono ADC", NULL, "DAC Clock"},
316 {"DAC Source Mux", "LDATA TO LDAC, RDATA TO RDAC", "I2S IN"},
318 {"Left DAC", NULL, "DAC Clock"},
319 {"Right DAC", NULL, "DAC Clock"},
321 {"Left DAC", NULL, "DAC Vref"},
322 {"Right DAC", NULL, "DAC Vref"},
324 {"Left DAC", NULL, "DAC Source Mux"},
325 {"Right DAC", NULL, "DAC Source Mux"},
327 {"Left Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
328 {"Right Headphone Mux", "lin-rin with Boost and PGA", "Line input PGA"},
331 {"Left Headphone Mixer", "Left DAC Switch", "Left DAC"},
334 {"Right Headphone Mixer", "Right DAC Switch", "Right DAC"},
366 struct snd_soc_component *component = codec_dai->component; in es8316_set_dai_sysclk()
371 es8316->sysclk = freq; in es8316_set_dai_sysclk()
372 es8316->sysclk_constraints.list = NULL; in es8316_set_dai_sysclk()
373 es8316->sysclk_constraints.count = 0; in es8316_set_dai_sysclk()
378 ret = clk_set_rate(es8316->mclk, freq); in es8316_set_dai_sysclk()
382 /* Limit supported sample rates to ones that can be autodetected in es8316_set_dai_sysclk()
389 es8316->allowed_rates[count++] = freq / ratio; in es8316_set_dai_sysclk()
393 es8316->sysclk_constraints.list = es8316->allowed_rates; in es8316_set_dai_sysclk()
394 es8316->sysclk_constraints.count = count; in es8316_set_dai_sysclk()
403 struct snd_soc_component *component = codec_dai->component; in es8316_set_dai_fmt()
413 dev_err(component->dev, "Codec driver only supports I2S format\n"); in es8316_set_dai_fmt()
414 return -EINVAL; in es8316_set_dai_fmt()
432 return -EINVAL; in es8316_set_dai_fmt()
452 struct snd_soc_component *component = dai->component; in es8316_pcm_startup()
455 if (es8316->sysclk_constraints.list) in es8316_pcm_startup()
456 snd_pcm_hw_constraint_list(substream->runtime, 0, in es8316_pcm_startup()
458 &es8316->sysclk_constraints); in es8316_pcm_startup()
467 struct snd_soc_component *component = dai->component; in es8316_pcm_hw_params()
478 if (es8316->sysclk % ratio != 0) in es8316_pcm_hw_params()
480 if (es8316->sysclk / ratio == params_rate(params)) in es8316_pcm_hw_params()
484 return -EINVAL; in es8316_pcm_hw_params()
485 lrck_divider = es8316->sysclk / params_rate(params); in es8316_pcm_hw_params()
506 return -EINVAL; in es8316_pcm_hw_params()
523 snd_soc_component_update_bits(dai->component, ES8316_DAC_SET1, 0x20, in es8316_mute()
591 struct snd_soc_component *comp = es8316->component; in es8316_irq()
594 mutex_lock(&es8316->lock); in es8316_irq()
596 regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags); in es8316_irq()
598 goto out; /* Powered-down / reset */ in es8316_irq()
601 if (!es8316->jack) in es8316_irq()
604 if (es8316->jd_inverted) in es8316_irq()
607 dev_dbg(comp->dev, "gpio flags %#04x\n", flags); in es8316_irq()
610 if (es8316->jack->status & SND_JACK_MICROPHONE) in es8316_irq()
613 if (es8316->jack->status & SND_JACK_HEADPHONE) { in es8316_irq()
614 snd_soc_jack_report(es8316->jack, 0, in es8316_irq()
616 dev_dbg(comp->dev, "jack unplugged\n"); in es8316_irq()
618 } else if (!(es8316->jack->status & SND_JACK_HEADPHONE)) { in es8316_irq()
621 regmap_read(es8316->regmap, ES8316_GPIO_FLAG, &flags); in es8316_irq()
622 if (es8316->jd_inverted) in es8316_irq()
624 dev_dbg(comp->dev, "gpio flags %#04x\n", flags); in es8316_irq()
630 snd_soc_jack_report(es8316->jack, in es8316_irq()
633 /* Keep mic-gnd-short detection on for button press */ in es8316_irq()
636 snd_soc_jack_report(es8316->jack, in es8316_irq()
639 /* No longer need mic-gnd-short detection */ in es8316_irq()
642 } else if (es8316->jack->status & SND_JACK_MICROPHONE) { in es8316_irq()
646 snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0); in es8316_irq()
649 snd_soc_jack_report(es8316->jack, in es8316_irq()
656 mutex_unlock(&es8316->lock); in es8316_irq()
666 * Init es8316->jd_inverted here and not in the probe, as we cannot in es8316_enable_jack_detect()
667 * guarantee that the bytchr-es8316 driver, which might set this in es8316_enable_jack_detect()
670 es8316->jd_inverted = device_property_read_bool(component->dev, in es8316_enable_jack_detect()
671 "everest,jack-detect-inverted"); in es8316_enable_jack_detect()
673 mutex_lock(&es8316->lock); in es8316_enable_jack_detect()
675 es8316->jack = jack; in es8316_enable_jack_detect()
677 if (es8316->jack->status & SND_JACK_MICROPHONE) in es8316_enable_jack_detect()
684 mutex_unlock(&es8316->lock); in es8316_enable_jack_detect()
687 enable_irq(es8316->irq); in es8316_enable_jack_detect()
688 es8316_irq(es8316->irq, es8316); in es8316_enable_jack_detect()
695 if (!es8316->jack) in es8316_disable_jack_detect()
698 disable_irq(es8316->irq); in es8316_disable_jack_detect()
700 mutex_lock(&es8316->lock); in es8316_disable_jack_detect()
705 if (es8316->jack->status & SND_JACK_MICROPHONE) { in es8316_disable_jack_detect()
707 snd_soc_jack_report(es8316->jack, 0, SND_JACK_BTN_0); in es8316_disable_jack_detect()
710 es8316->jack = NULL; in es8316_disable_jack_detect()
712 mutex_unlock(&es8316->lock); in es8316_disable_jack_detect()
731 es8316->component = component; in es8316_probe()
733 es8316->mclk = devm_clk_get_optional(component->dev, "mclk"); in es8316_probe()
734 if (IS_ERR(es8316->mclk)) { in es8316_probe()
735 dev_err(component->dev, "unable to get mclk\n"); in es8316_probe()
736 return PTR_ERR(es8316->mclk); in es8316_probe()
738 if (!es8316->mclk) in es8316_probe()
739 dev_warn(component->dev, "assuming static mclk\n"); in es8316_probe()
741 ret = clk_prepare_enable(es8316->mclk); in es8316_probe()
743 dev_err(component->dev, "unable to enable mclk\n"); in es8316_probe()
747 /* Reset codec and enable current state machine */ in es8316_probe()
761 * but here is a vendor-provided value that improves volume in es8316_probe()
773 clk_disable_unprepare(es8316->mclk); in es8316_remove()
780 regcache_cache_only(es8316->regmap, false); in es8316_resume()
781 regcache_sync(es8316->regmap); in es8316_resume()
790 regcache_cache_only(es8316->regmap, true); in es8316_suspend()
791 regcache_mark_dirty(es8316->regmap); in es8316_suspend()
834 struct device *dev = &i2c_client->dev; in es8316_i2c_probe()
838 es8316 = devm_kzalloc(&i2c_client->dev, sizeof(struct es8316_priv), in es8316_i2c_probe()
841 return -ENOMEM; in es8316_i2c_probe()
845 es8316->regmap = devm_regmap_init_i2c(i2c_client, &es8316_regmap); in es8316_i2c_probe()
846 if (IS_ERR(es8316->regmap)) in es8316_i2c_probe()
847 return PTR_ERR(es8316->regmap); in es8316_i2c_probe()
849 es8316->irq = i2c_client->irq; in es8316_i2c_probe()
850 mutex_init(&es8316->lock); in es8316_i2c_probe()
852 if (es8316->irq > 0) { in es8316_i2c_probe()
853 ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, in es8316_i2c_probe()
857 dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); in es8316_i2c_probe()
858 es8316->irq = -ENXIO; in es8316_i2c_probe()
862 return devm_snd_soc_register_component(&i2c_client->dev, in es8316_i2c_probe()
902 MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");