Lines Matching +full:ac +full:- +full:detect +full:- +full:gpios

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system
35 #include <sound/soc-dapm.h>
58 /* Power-up register defaults */
136 "Vcc" /* power amp spply, 10V - 36V */
157 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
158 static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
159 static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0);
162 "Anti-Clipping", "Dynamic Range Compression" };
166 "User", "AC no clipping", "AC limited clipping (10%)",
173 "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1",
174 "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2",
189 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
195 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
196 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
197 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
198 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
202 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
203 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
204 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
209 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
210 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
211 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
212 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
262 int numcoef = kcontrol->private_value >> 16; in sta32x_coefficient_info()
263 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; in sta32x_coefficient_info()
264 uinfo->count = 3 * numcoef; in sta32x_coefficient_info()
273 int numcoef = kcontrol->private_value >> 16; in sta32x_coefficient_get()
274 int index = kcontrol->private_value & 0xffff; in sta32x_coefficient_get()
278 mutex_lock(&sta32x->coeff_lock); in sta32x_coefficient_get()
281 regmap_read(sta32x->regmap, STA32X_CFUD, &cfud); in sta32x_coefficient_get()
287 regmap_write(sta32x->regmap, STA32X_CFUD, cfud); in sta32x_coefficient_get()
289 regmap_write(sta32x->regmap, STA32X_CFADDR2, index); in sta32x_coefficient_get()
291 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x04); in sta32x_coefficient_get()
293 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x08); in sta32x_coefficient_get()
295 ret = -EINVAL; in sta32x_coefficient_get()
300 regmap_read(sta32x->regmap, STA32X_B1CF1 + i, &val); in sta32x_coefficient_get()
301 ucontrol->value.bytes.data[i] = val; in sta32x_coefficient_get()
305 mutex_unlock(&sta32x->coeff_lock); in sta32x_coefficient_get()
315 int numcoef = kcontrol->private_value >> 16; in sta32x_coefficient_put()
316 int index = kcontrol->private_value & 0xffff; in sta32x_coefficient_put()
321 regmap_read(sta32x->regmap, STA32X_CFUD, &cfud); in sta32x_coefficient_put()
327 regmap_write(sta32x->regmap, STA32X_CFUD, cfud); in sta32x_coefficient_put()
329 regmap_write(sta32x->regmap, STA32X_CFADDR2, index); in sta32x_coefficient_put()
331 sta32x->coef_shadow[index + i] = in sta32x_coefficient_put()
332 (ucontrol->value.bytes.data[3 * i] << 16) in sta32x_coefficient_put()
333 | (ucontrol->value.bytes.data[3 * i + 1] << 8) in sta32x_coefficient_put()
334 | (ucontrol->value.bytes.data[3 * i + 2]); in sta32x_coefficient_put()
336 regmap_write(sta32x->regmap, STA32X_B1CF1 + i, in sta32x_coefficient_put()
337 ucontrol->value.bytes.data[i]); in sta32x_coefficient_put()
339 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01); in sta32x_coefficient_put()
341 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x02); in sta32x_coefficient_put()
343 return -EINVAL; in sta32x_coefficient_put()
355 regmap_read(sta32x->regmap, STA32X_CFUD, &cfud); in sta32x_sync_coef_shadow()
359 regmap_write(sta32x->regmap, STA32X_CFADDR2, i); in sta32x_sync_coef_shadow()
360 regmap_write(sta32x->regmap, STA32X_B1CF1, in sta32x_sync_coef_shadow()
361 (sta32x->coef_shadow[i] >> 16) & 0xff); in sta32x_sync_coef_shadow()
362 regmap_write(sta32x->regmap, STA32X_B1CF2, in sta32x_sync_coef_shadow()
363 (sta32x->coef_shadow[i] >> 8) & 0xff); in sta32x_sync_coef_shadow()
364 regmap_write(sta32x->regmap, STA32X_B1CF3, in sta32x_sync_coef_shadow()
365 (sta32x->coef_shadow[i]) & 0xff); in sta32x_sync_coef_shadow()
368 * self-clearing, so do it explicitly in sta32x_sync_coef_shadow()
370 regmap_write(sta32x->regmap, STA32X_CFUD, cfud); in sta32x_sync_coef_shadow()
371 regmap_write(sta32x->regmap, STA32X_CFUD, cfud | 0x01); in sta32x_sync_coef_shadow()
383 regmap_read(sta32x->regmap, STA32X_MMUTE, &mute); in sta32x_cache_sync()
384 regmap_write(sta32x->regmap, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); in sta32x_cache_sync()
386 rc = regcache_sync(sta32x->regmap); in sta32x_cache_sync()
387 regmap_write(sta32x->regmap, STA32X_MMUTE, mute); in sta32x_cache_sync()
396 struct snd_soc_component *component = sta32x->component; in sta32x_watchdog()
401 regcache_cache_bypass(sta32x->regmap, true); in sta32x_watchdog()
403 regcache_cache_bypass(sta32x->regmap, false); in sta32x_watchdog()
405 regcache_mark_dirty(sta32x->regmap); in sta32x_watchdog()
409 if (!sta32x->shutdown) in sta32x_watchdog()
411 &sta32x->watchdog_work, in sta32x_watchdog()
417 if (sta32x->pdata->needs_esd_watchdog) { in sta32x_watchdog_start()
418 sta32x->shutdown = 0; in sta32x_watchdog_start()
420 &sta32x->watchdog_work, in sta32x_watchdog_start()
427 if (sta32x->pdata->needs_esd_watchdog) { in sta32x_watchdog_stop()
428 sta32x->shutdown = 1; in sta32x_watchdog_stop()
429 cancel_delayed_work_sync(&sta32x->watchdog_work); in sta32x_watchdog_stop()
456 SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0),
461 SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0),
486 SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT,
488 SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT,
490 SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT,
492 SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT,
503 BIQUAD_COEFS("Ch1 - Biquad 1", 0),
504 BIQUAD_COEFS("Ch1 - Biquad 2", 5),
505 BIQUAD_COEFS("Ch1 - Biquad 3", 10),
506 BIQUAD_COEFS("Ch1 - Biquad 4", 15),
507 BIQUAD_COEFS("Ch2 - Biquad 1", 20),
508 BIQUAD_COEFS("Ch2 - Biquad 2", 25),
509 BIQUAD_COEFS("Ch2 - Biquad 3", 30),
510 BIQUAD_COEFS("Ch2 - Biquad 4", 35),
511 BIQUAD_COEFS("High-pass", 40),
512 BIQUAD_COEFS("Low-pass", 45),
513 SINGLE_COEF("Ch1 - Prescale", 50),
514 SINGLE_COEF("Ch2 - Prescale", 51),
515 SINGLE_COEF("Ch1 - Postscale", 52),
516 SINGLE_COEF("Ch2 - Postscale", 53),
517 SINGLE_COEF("Ch3 - Postscale", 54),
518 SINGLE_COEF("Thermal warning - Postscale", 55),
519 SINGLE_COEF("Ch1 - Mix 1", 56),
520 SINGLE_COEF("Ch1 - Mix 2", 57),
521 SINGLE_COEF("Ch2 - Mix 1", 58),
522 SINGLE_COEF("Ch2 - Mix 2", 59),
523 SINGLE_COEF("Ch3 - Mix 1", 60),
524 SINGLE_COEF("Ch3 - Mix 2", 61),
562 * sta32x_set_dai_sysclk - configure MCLK
583 struct snd_soc_component *component = codec_dai->component; in sta32x_set_dai_sysclk()
586 dev_dbg(component->dev, "mclk=%u\n", freq); in sta32x_set_dai_sysclk()
587 sta32x->mclk = freq; in sta32x_set_dai_sysclk()
593 * sta32x_set_dai_fmt - configure the codec for the selected audio format
603 struct snd_soc_component *component = codec_dai->component; in sta32x_set_dai_fmt()
611 return -EINVAL; in sta32x_set_dai_fmt()
618 sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; in sta32x_set_dai_fmt()
621 return -EINVAL; in sta32x_set_dai_fmt()
632 return -EINVAL; in sta32x_set_dai_fmt()
635 return regmap_update_bits(sta32x->regmap, STA32X_CONFB, in sta32x_set_dai_fmt()
640 * sta32x_hw_params - program the STA32X with the given hardware parameters.
652 struct snd_soc_component *component = dai->component; in sta32x_hw_params()
654 int i, mcs = -EINVAL, ir = -EINVAL; in sta32x_hw_params()
659 if (!sta32x->mclk) { in sta32x_hw_params()
660 dev_err(component->dev, in sta32x_hw_params()
661 "sta32x->mclk is unset. Unable to determine ratio\n"); in sta32x_hw_params()
662 return -EIO; in sta32x_hw_params()
666 ratio = sta32x->mclk / rate; in sta32x_hw_params()
667 dev_dbg(component->dev, "rate: %u, ratio: %u\n", rate, ratio); in sta32x_hw_params()
677 dev_err(component->dev, "Unsupported samplerate: %u\n", rate); in sta32x_hw_params()
678 return -EINVAL; in sta32x_hw_params()
689 dev_err(component->dev, "Unresolvable ratio: %u\n", ratio); in sta32x_hw_params()
690 return -EINVAL; in sta32x_hw_params()
699 dev_dbg(component->dev, "24bit\n"); in sta32x_hw_params()
702 dev_dbg(component->dev, "24bit or 32bit\n"); in sta32x_hw_params()
703 switch (sta32x->format) { in sta32x_hw_params()
717 dev_dbg(component->dev, "20bit\n"); in sta32x_hw_params()
718 switch (sta32x->format) { in sta32x_hw_params()
732 dev_dbg(component->dev, "18bit\n"); in sta32x_hw_params()
733 switch (sta32x->format) { in sta32x_hw_params()
747 dev_dbg(component->dev, "16bit\n"); in sta32x_hw_params()
748 switch (sta32x->format) { in sta32x_hw_params()
762 return -EINVAL; in sta32x_hw_params()
765 ret = regmap_update_bits(sta32x->regmap, STA32X_CONFA, in sta32x_hw_params()
771 ret = regmap_update_bits(sta32x->regmap, STA32X_CONFB, in sta32x_hw_params()
782 if (sta32x->gpiod_nreset) { in sta32x_startup_sequence()
783 gpiod_set_value(sta32x->gpiod_nreset, 0); in sta32x_startup_sequence()
785 gpiod_set_value(sta32x->gpiod_nreset, 1); in sta32x_startup_sequence()
793 * sta32x_set_bias_level - DAPM callback
807 dev_dbg(component->dev, "level = %d\n", level); in sta32x_set_bias_level()
814 regmap_update_bits(sta32x->regmap, STA32X_CONFF, in sta32x_set_bias_level()
821 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), in sta32x_set_bias_level()
822 sta32x->supplies); in sta32x_set_bias_level()
824 dev_err(component->dev, in sta32x_set_bias_level()
835 regmap_update_bits(sta32x->regmap, STA32X_CONFF, in sta32x_set_bias_level()
843 regmap_update_bits(sta32x->regmap, STA32X_CONFF, in sta32x_set_bias_level()
848 gpiod_set_value(sta32x->gpiod_nreset, 0); in sta32x_set_bias_level()
850 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), in sta32x_set_bias_level()
851 sta32x->supplies); in sta32x_set_bias_level()
864 .name = "sta32x-hifi",
878 struct sta32x_platform_data *pdata = sta32x->pdata; in sta32x_probe()
881 sta32x->component = component; in sta32x_probe()
883 if (sta32x->xti_clk) { in sta32x_probe()
884 ret = clk_prepare_enable(sta32x->xti_clk); in sta32x_probe()
886 dev_err(component->dev, in sta32x_probe()
892 ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), in sta32x_probe()
893 sta32x->supplies); in sta32x_probe()
895 dev_err(component->dev, "Failed to enable supplies: %d\n", ret); in sta32x_probe()
901 dev_err(component->dev, "Failed to startup device\n"); in sta32x_probe()
906 if (!pdata->thermal_warning_recovery) in sta32x_probe()
908 if (!pdata->thermal_warning_adjustment) in sta32x_probe()
910 if (!pdata->fault_detect_recovery) in sta32x_probe()
912 regmap_update_bits(sta32x->regmap, STA32X_CONFA, in sta32x_probe()
918 regmap_update_bits(sta32x->regmap, STA32X_CONFC, in sta32x_probe()
920 pdata->drop_compensation_ns in sta32x_probe()
924 regmap_update_bits(sta32x->regmap, STA32X_CONFE, in sta32x_probe()
926 pdata->max_power_use_mpcc ? in sta32x_probe()
928 regmap_update_bits(sta32x->regmap, STA32X_CONFE, in sta32x_probe()
930 pdata->max_power_correction ? in sta32x_probe()
932 regmap_update_bits(sta32x->regmap, STA32X_CONFE, in sta32x_probe()
934 pdata->am_reduction_mode ? in sta32x_probe()
936 regmap_update_bits(sta32x->regmap, STA32X_CONFE, in sta32x_probe()
938 pdata->odd_pwm_speed_mode ? in sta32x_probe()
942 regmap_update_bits(sta32x->regmap, STA32X_CONFF, in sta32x_probe()
944 pdata->invalid_input_detect_mute ? in sta32x_probe()
948 regmap_update_bits(sta32x->regmap, STA32X_CONFF, in sta32x_probe()
950 pdata->output_conf in sta32x_probe()
954 regmap_update_bits(sta32x->regmap, STA32X_C1CFG, in sta32x_probe()
956 pdata->ch1_output_mapping in sta32x_probe()
958 regmap_update_bits(sta32x->regmap, STA32X_C2CFG, in sta32x_probe()
960 pdata->ch2_output_mapping in sta32x_probe()
962 regmap_update_bits(sta32x->regmap, STA32X_C3CFG, in sta32x_probe()
964 pdata->ch3_output_mapping in sta32x_probe()
969 sta32x->coef_shadow[i] = 0x400000; in sta32x_probe()
971 sta32x->coef_shadow[i] = 0x7fffff; in sta32x_probe()
972 sta32x->coef_shadow[55] = 0x5a9df7; in sta32x_probe()
973 sta32x->coef_shadow[56] = 0x7fffff; in sta32x_probe()
974 sta32x->coef_shadow[59] = 0x7fffff; in sta32x_probe()
975 sta32x->coef_shadow[60] = 0x400000; in sta32x_probe()
976 sta32x->coef_shadow[61] = 0x400000; in sta32x_probe()
978 if (sta32x->pdata->needs_esd_watchdog) in sta32x_probe()
979 INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog); in sta32x_probe()
983 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); in sta32x_probe()
988 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); in sta32x_probe()
990 if (sta32x->xti_clk) in sta32x_probe()
991 clk_disable_unprepare(sta32x->xti_clk); in sta32x_probe()
1000 regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); in sta32x_remove()
1002 if (sta32x->xti_clk) in sta32x_remove()
1003 clk_disable_unprepare(sta32x->xti_clk); in sta32x_remove()
1044 struct device_node *np = dev->of_node; in sta32x_probe_dt()
1050 return -ENOMEM; in sta32x_probe_dt()
1052 of_property_read_u8(np, "st,output-conf", in sta32x_probe_dt()
1053 &pdata->output_conf); in sta32x_probe_dt()
1054 of_property_read_u8(np, "st,ch1-output-mapping", in sta32x_probe_dt()
1055 &pdata->ch1_output_mapping); in sta32x_probe_dt()
1056 of_property_read_u8(np, "st,ch2-output-mapping", in sta32x_probe_dt()
1057 &pdata->ch2_output_mapping); in sta32x_probe_dt()
1058 of_property_read_u8(np, "st,ch3-output-mapping", in sta32x_probe_dt()
1059 &pdata->ch3_output_mapping); in sta32x_probe_dt()
1061 if (of_get_property(np, "st,fault-detect-recovery", NULL)) in sta32x_probe_dt()
1062 pdata->fault_detect_recovery = 1; in sta32x_probe_dt()
1063 if (of_get_property(np, "st,thermal-warning-recovery", NULL)) in sta32x_probe_dt()
1064 pdata->thermal_warning_recovery = 1; in sta32x_probe_dt()
1065 if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) in sta32x_probe_dt()
1066 pdata->thermal_warning_adjustment = 1; in sta32x_probe_dt()
1068 pdata->needs_esd_watchdog = 1; in sta32x_probe_dt()
1071 of_property_read_u16(np, "st,drop-compensation-ns", &tmp); in sta32x_probe_dt()
1072 pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; in sta32x_probe_dt()
1075 if (of_get_property(np, "st,max-power-use-mpcc", NULL)) in sta32x_probe_dt()
1076 pdata->max_power_use_mpcc = 1; in sta32x_probe_dt()
1078 if (of_get_property(np, "st,max-power-correction", NULL)) in sta32x_probe_dt()
1079 pdata->max_power_correction = 1; in sta32x_probe_dt()
1081 if (of_get_property(np, "st,am-reduction-mode", NULL)) in sta32x_probe_dt()
1082 pdata->am_reduction_mode = 1; in sta32x_probe_dt()
1084 if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) in sta32x_probe_dt()
1085 pdata->odd_pwm_speed_mode = 1; in sta32x_probe_dt()
1088 if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) in sta32x_probe_dt()
1089 pdata->invalid_input_detect_mute = 1; in sta32x_probe_dt()
1091 sta32x->pdata = pdata; in sta32x_probe_dt()
1100 struct device *dev = &i2c->dev; in sta32x_i2c_probe()
1104 sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), in sta32x_i2c_probe()
1107 return -ENOMEM; in sta32x_i2c_probe()
1109 mutex_init(&sta32x->coeff_lock); in sta32x_i2c_probe()
1110 sta32x->pdata = dev_get_platdata(dev); in sta32x_i2c_probe()
1113 if (dev->of_node) { in sta32x_i2c_probe()
1121 sta32x->xti_clk = devm_clk_get(dev, "xti"); in sta32x_i2c_probe()
1122 if (IS_ERR(sta32x->xti_clk)) { in sta32x_i2c_probe()
1123 ret = PTR_ERR(sta32x->xti_clk); in sta32x_i2c_probe()
1125 if (ret == -EPROBE_DEFER) in sta32x_i2c_probe()
1128 sta32x->xti_clk = NULL; in sta32x_i2c_probe()
1131 /* GPIOs */ in sta32x_i2c_probe()
1132 sta32x->gpiod_nreset = devm_gpiod_get_optional(dev, "reset", in sta32x_i2c_probe()
1134 if (IS_ERR(sta32x->gpiod_nreset)) in sta32x_i2c_probe()
1135 return PTR_ERR(sta32x->gpiod_nreset); in sta32x_i2c_probe()
1138 for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) in sta32x_i2c_probe()
1139 sta32x->supplies[i].supply = sta32x_supply_names[i]; in sta32x_i2c_probe()
1141 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies), in sta32x_i2c_probe()
1142 sta32x->supplies); in sta32x_i2c_probe()
1144 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); in sta32x_i2c_probe()
1148 sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); in sta32x_i2c_probe()
1149 if (IS_ERR(sta32x->regmap)) { in sta32x_i2c_probe()
1150 ret = PTR_ERR(sta32x->regmap); in sta32x_i2c_probe()