Lines Matching +full:ac +full:- +full:detect +full:- +full:gpios
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Codec driver for ST STA350 2.1-channel high-efficiency digital audio system
35 #include <sound/soc-dapm.h>
58 /* Power-up register defaults */
159 "vdd-dig", /* digital supply, 3.3V */
160 "vdd-pll", /* pll supply, 3.3V */
161 "vcc" /* power amp supply, 5V - 26V */
182 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12750, 50, 1);
183 static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
184 static const DECLARE_TLV_DB_SCALE(tone_tlv, -1200, 200, 0);
187 "Anti-Clipping", "Dynamic Range Compression"
190 "User", "AC no clipping", "AC limited clipping (10%)",
199 "FFX 3-state output - normal operation", "Binary output"
219 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
225 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
226 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
227 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
228 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
232 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
233 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
234 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
239 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
240 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
241 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
242 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
299 int numcoef = kcontrol->private_value >> 16; in sta350_coefficient_info()
300 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; in sta350_coefficient_info()
301 uinfo->count = 3 * numcoef; in sta350_coefficient_info()
310 int numcoef = kcontrol->private_value >> 16; in sta350_coefficient_get()
311 int index = kcontrol->private_value & 0xffff; in sta350_coefficient_get()
315 mutex_lock(&sta350->coeff_lock); in sta350_coefficient_get()
318 regmap_read(sta350->regmap, STA350_CFUD, &cfud); in sta350_coefficient_get()
324 regmap_write(sta350->regmap, STA350_CFUD, cfud); in sta350_coefficient_get()
326 regmap_write(sta350->regmap, STA350_CFADDR2, index); in sta350_coefficient_get()
328 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x04); in sta350_coefficient_get()
330 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x08); in sta350_coefficient_get()
332 ret = -EINVAL; in sta350_coefficient_get()
337 regmap_read(sta350->regmap, STA350_B1CF1 + i, &val); in sta350_coefficient_get()
338 ucontrol->value.bytes.data[i] = val; in sta350_coefficient_get()
342 mutex_unlock(&sta350->coeff_lock); in sta350_coefficient_get()
352 int numcoef = kcontrol->private_value >> 16; in sta350_coefficient_put()
353 int index = kcontrol->private_value & 0xffff; in sta350_coefficient_put()
358 regmap_read(sta350->regmap, STA350_CFUD, &cfud); in sta350_coefficient_put()
364 regmap_write(sta350->regmap, STA350_CFUD, cfud); in sta350_coefficient_put()
366 regmap_write(sta350->regmap, STA350_CFADDR2, index); in sta350_coefficient_put()
368 sta350->coef_shadow[index + i] = in sta350_coefficient_put()
369 (ucontrol->value.bytes.data[3 * i] << 16) in sta350_coefficient_put()
370 | (ucontrol->value.bytes.data[3 * i + 1] << 8) in sta350_coefficient_put()
371 | (ucontrol->value.bytes.data[3 * i + 2]); in sta350_coefficient_put()
373 regmap_write(sta350->regmap, STA350_B1CF1 + i, in sta350_coefficient_put()
374 ucontrol->value.bytes.data[i]); in sta350_coefficient_put()
376 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01); in sta350_coefficient_put()
378 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x02); in sta350_coefficient_put()
380 return -EINVAL; in sta350_coefficient_put()
392 regmap_read(sta350->regmap, STA350_CFUD, &cfud); in sta350_sync_coef_shadow()
396 regmap_write(sta350->regmap, STA350_CFADDR2, i); in sta350_sync_coef_shadow()
397 regmap_write(sta350->regmap, STA350_B1CF1, in sta350_sync_coef_shadow()
398 (sta350->coef_shadow[i] >> 16) & 0xff); in sta350_sync_coef_shadow()
399 regmap_write(sta350->regmap, STA350_B1CF2, in sta350_sync_coef_shadow()
400 (sta350->coef_shadow[i] >> 8) & 0xff); in sta350_sync_coef_shadow()
401 regmap_write(sta350->regmap, STA350_B1CF3, in sta350_sync_coef_shadow()
402 (sta350->coef_shadow[i]) & 0xff); in sta350_sync_coef_shadow()
405 * self-clearing, so do it explicitly in sta350_sync_coef_shadow()
407 regmap_write(sta350->regmap, STA350_CFUD, cfud); in sta350_sync_coef_shadow()
408 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01); in sta350_sync_coef_shadow()
420 regmap_read(sta350->regmap, STA350_CFUD, &mute); in sta350_cache_sync()
421 regmap_write(sta350->regmap, STA350_MMUTE, mute | STA350_MMUTE_MMUTE); in sta350_cache_sync()
423 rc = regcache_sync(sta350->regmap); in sta350_cache_sync()
424 regmap_write(sta350->regmap, STA350_MMUTE, mute); in sta350_cache_sync()
451 SOC_SINGLE("De-emphasis Filter Switch",
455 SOC_SINGLE("Post-scale Link Switch",
461 SOC_SINGLE("Zero-detect Mute Enable Switch",
511 SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)",
514 SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)",
517 SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)",
520 SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)",
536 BIQUAD_COEFS("Ch1 - Biquad 1", 0),
537 BIQUAD_COEFS("Ch1 - Biquad 2", 5),
538 BIQUAD_COEFS("Ch1 - Biquad 3", 10),
539 BIQUAD_COEFS("Ch1 - Biquad 4", 15),
540 BIQUAD_COEFS("Ch2 - Biquad 1", 20),
541 BIQUAD_COEFS("Ch2 - Biquad 2", 25),
542 BIQUAD_COEFS("Ch2 - Biquad 3", 30),
543 BIQUAD_COEFS("Ch2 - Biquad 4", 35),
544 BIQUAD_COEFS("High-pass", 40),
545 BIQUAD_COEFS("Low-pass", 45),
546 SINGLE_COEF("Ch1 - Prescale", 50),
547 SINGLE_COEF("Ch2 - Prescale", 51),
548 SINGLE_COEF("Ch1 - Postscale", 52),
549 SINGLE_COEF("Ch2 - Postscale", 53),
550 SINGLE_COEF("Ch3 - Postscale", 54),
551 SINGLE_COEF("Thermal warning - Postscale", 55),
552 SINGLE_COEF("Ch1 - Mix 1", 56),
553 SINGLE_COEF("Ch1 - Mix 2", 57),
554 SINGLE_COEF("Ch2 - Mix 1", 58),
555 SINGLE_COEF("Ch2 - Mix 2", 59),
556 SINGLE_COEF("Ch3 - Mix 1", 60),
557 SINGLE_COEF("Ch3 - Mix 2", 61),
596 * sta350_set_dai_sysclk - configure MCLK
612 struct snd_soc_component *component = codec_dai->component; in sta350_set_dai_sysclk()
615 dev_dbg(component->dev, "mclk=%u\n", freq); in sta350_set_dai_sysclk()
616 sta350->mclk = freq; in sta350_set_dai_sysclk()
622 * sta350_set_dai_fmt - configure the codec for the selected audio format
632 struct snd_soc_component *component = codec_dai->component; in sta350_set_dai_fmt()
640 return -EINVAL; in sta350_set_dai_fmt()
647 sta350->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; in sta350_set_dai_fmt()
650 return -EINVAL; in sta350_set_dai_fmt()
661 return -EINVAL; in sta350_set_dai_fmt()
664 return regmap_update_bits(sta350->regmap, STA350_CONFB, in sta350_set_dai_fmt()
669 * sta350_hw_params - program the STA350 with the given hardware parameters.
681 struct snd_soc_component *component = dai->component; in sta350_hw_params()
683 int i, mcs = -EINVAL, ir = -EINVAL; in sta350_hw_params()
688 if (!sta350->mclk) { in sta350_hw_params()
689 dev_err(component->dev, in sta350_hw_params()
690 "sta350->mclk is unset. Unable to determine ratio\n"); in sta350_hw_params()
691 return -EIO; in sta350_hw_params()
695 ratio = sta350->mclk / rate; in sta350_hw_params()
696 dev_dbg(component->dev, "rate: %u, ratio: %u\n", rate, ratio); in sta350_hw_params()
706 dev_err(component->dev, "Unsupported samplerate: %u\n", rate); in sta350_hw_params()
707 return -EINVAL; in sta350_hw_params()
718 dev_err(component->dev, "Unresolvable ratio: %u\n", ratio); in sta350_hw_params()
719 return -EINVAL; in sta350_hw_params()
728 dev_dbg(component->dev, "24bit\n"); in sta350_hw_params()
731 dev_dbg(component->dev, "24bit or 32bit\n"); in sta350_hw_params()
732 switch (sta350->format) { in sta350_hw_params()
746 dev_dbg(component->dev, "20bit\n"); in sta350_hw_params()
747 switch (sta350->format) { in sta350_hw_params()
761 dev_dbg(component->dev, "18bit\n"); in sta350_hw_params()
762 switch (sta350->format) { in sta350_hw_params()
776 dev_dbg(component->dev, "16bit\n"); in sta350_hw_params()
777 switch (sta350->format) { in sta350_hw_params()
791 return -EINVAL; in sta350_hw_params()
794 ret = regmap_update_bits(sta350->regmap, STA350_CONFA, in sta350_hw_params()
800 ret = regmap_update_bits(sta350->regmap, STA350_CONFB, in sta350_hw_params()
811 if (sta350->gpiod_power_down) in sta350_startup_sequence()
812 gpiod_set_value(sta350->gpiod_power_down, 1); in sta350_startup_sequence()
814 if (sta350->gpiod_nreset) { in sta350_startup_sequence()
815 gpiod_set_value(sta350->gpiod_nreset, 0); in sta350_startup_sequence()
817 gpiod_set_value(sta350->gpiod_nreset, 1); in sta350_startup_sequence()
825 * sta350_set_bias_level - DAPM callback
839 dev_dbg(component->dev, "level = %d\n", level); in sta350_set_bias_level()
846 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_set_bias_level()
854 ARRAY_SIZE(sta350->supplies), in sta350_set_bias_level()
855 sta350->supplies); in sta350_set_bias_level()
857 dev_err(component->dev, in sta350_set_bias_level()
867 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_set_bias_level()
875 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_set_bias_level()
879 if (sta350->gpiod_power_down) in sta350_set_bias_level()
880 gpiod_set_value(sta350->gpiod_power_down, 0); in sta350_set_bias_level()
882 if (sta350->gpiod_nreset) in sta350_set_bias_level()
883 gpiod_set_value(sta350->gpiod_nreset, 0); in sta350_set_bias_level()
885 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), in sta350_set_bias_level()
886 sta350->supplies); in sta350_set_bias_level()
899 .name = "sta350-hifi",
913 struct sta350_platform_data *pdata = sta350->pdata; in sta350_probe()
916 ret = regulator_bulk_enable(ARRAY_SIZE(sta350->supplies), in sta350_probe()
917 sta350->supplies); in sta350_probe()
919 dev_err(component->dev, "Failed to enable supplies: %d\n", ret); in sta350_probe()
925 dev_err(component->dev, "Failed to startup device\n"); in sta350_probe()
930 if (!pdata->thermal_warning_recovery) in sta350_probe()
932 if (!pdata->thermal_warning_adjustment) in sta350_probe()
934 if (!pdata->fault_detect_recovery) in sta350_probe()
936 regmap_update_bits(sta350->regmap, STA350_CONFA, in sta350_probe()
942 regmap_update_bits(sta350->regmap, STA350_CONFC, in sta350_probe()
944 pdata->ffx_power_output_mode in sta350_probe()
946 regmap_update_bits(sta350->regmap, STA350_CONFC, in sta350_probe()
948 pdata->drop_compensation_ns in sta350_probe()
950 regmap_update_bits(sta350->regmap, in sta350_probe()
953 pdata->oc_warning_adjustment ? in sta350_probe()
957 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
959 pdata->max_power_use_mpcc ? in sta350_probe()
961 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
963 pdata->max_power_correction ? in sta350_probe()
965 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
967 pdata->am_reduction_mode ? in sta350_probe()
969 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
971 pdata->odd_pwm_speed_mode ? in sta350_probe()
973 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
975 pdata->distortion_compensation ? in sta350_probe()
978 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_probe()
980 pdata->invalid_input_detect_mute ? in sta350_probe()
982 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_probe()
984 pdata->output_conf in sta350_probe()
988 regmap_update_bits(sta350->regmap, STA350_C1CFG, in sta350_probe()
990 pdata->ch1_output_mapping in sta350_probe()
992 regmap_update_bits(sta350->regmap, STA350_C2CFG, in sta350_probe()
994 pdata->ch2_output_mapping in sta350_probe()
996 regmap_update_bits(sta350->regmap, STA350_C3CFG, in sta350_probe()
998 pdata->ch3_output_mapping in sta350_probe()
1002 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1004 pdata->activate_mute_output ? in sta350_probe()
1006 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1008 pdata->bridge_immediate_off ? in sta350_probe()
1010 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1012 pdata->noise_shape_dc_cut ? in sta350_probe()
1014 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1016 pdata->powerdown_master_vol ? in sta350_probe()
1019 regmap_update_bits(sta350->regmap, STA350_MISC2, in sta350_probe()
1021 pdata->powerdown_delay_divider in sta350_probe()
1026 sta350->coef_shadow[i] = 0x400000; in sta350_probe()
1028 sta350->coef_shadow[i] = 0x7fffff; in sta350_probe()
1029 sta350->coef_shadow[55] = 0x5a9df7; in sta350_probe()
1030 sta350->coef_shadow[56] = 0x7fffff; in sta350_probe()
1031 sta350->coef_shadow[59] = 0x7fffff; in sta350_probe()
1032 sta350->coef_shadow[60] = 0x400000; in sta350_probe()
1033 sta350->coef_shadow[61] = 0x400000; in sta350_probe()
1037 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); in sta350_probe()
1046 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); in sta350_remove()
1086 [STA350_FFX_PM_DROP_COMP] = "drop-compensation",
1087 [STA350_FFX_PM_TAPERED_COMP] = "tapered-compensation",
1088 [STA350_FFX_PM_FULL_POWER] = "full-power-mode",
1089 [STA350_FFX_PM_VARIABLE_DROP_COMP] = "variable-drop-compensation",
1094 struct device_node *np = dev->of_node; in sta350_probe_dt()
1102 return -ENOMEM; in sta350_probe_dt()
1104 of_property_read_u8(np, "st,output-conf", in sta350_probe_dt()
1105 &pdata->output_conf); in sta350_probe_dt()
1106 of_property_read_u8(np, "st,ch1-output-mapping", in sta350_probe_dt()
1107 &pdata->ch1_output_mapping); in sta350_probe_dt()
1108 of_property_read_u8(np, "st,ch2-output-mapping", in sta350_probe_dt()
1109 &pdata->ch2_output_mapping); in sta350_probe_dt()
1110 of_property_read_u8(np, "st,ch3-output-mapping", in sta350_probe_dt()
1111 &pdata->ch3_output_mapping); in sta350_probe_dt()
1113 if (of_get_property(np, "st,thermal-warning-recovery", NULL)) in sta350_probe_dt()
1114 pdata->thermal_warning_recovery = 1; in sta350_probe_dt()
1115 if (of_get_property(np, "st,thermal-warning-adjustment", NULL)) in sta350_probe_dt()
1116 pdata->thermal_warning_adjustment = 1; in sta350_probe_dt()
1117 if (of_get_property(np, "st,fault-detect-recovery", NULL)) in sta350_probe_dt()
1118 pdata->fault_detect_recovery = 1; in sta350_probe_dt()
1120 pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP; in sta350_probe_dt()
1121 if (!of_property_read_string(np, "st,ffx-power-output-mode", in sta350_probe_dt()
1123 int i, mode = -EINVAL; in sta350_probe_dt()
1133 pdata->ffx_power_output_mode = mode; in sta350_probe_dt()
1137 of_property_read_u16(np, "st,drop-compensation-ns", &tmp); in sta350_probe_dt()
1138 pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; in sta350_probe_dt()
1140 if (of_get_property(np, "st,overcurrent-warning-adjustment", NULL)) in sta350_probe_dt()
1141 pdata->oc_warning_adjustment = 1; in sta350_probe_dt()
1144 if (of_get_property(np, "st,max-power-use-mpcc", NULL)) in sta350_probe_dt()
1145 pdata->max_power_use_mpcc = 1; in sta350_probe_dt()
1147 if (of_get_property(np, "st,max-power-correction", NULL)) in sta350_probe_dt()
1148 pdata->max_power_correction = 1; in sta350_probe_dt()
1150 if (of_get_property(np, "st,am-reduction-mode", NULL)) in sta350_probe_dt()
1151 pdata->am_reduction_mode = 1; in sta350_probe_dt()
1153 if (of_get_property(np, "st,odd-pwm-speed-mode", NULL)) in sta350_probe_dt()
1154 pdata->odd_pwm_speed_mode = 1; in sta350_probe_dt()
1156 if (of_get_property(np, "st,distortion-compensation", NULL)) in sta350_probe_dt()
1157 pdata->distortion_compensation = 1; in sta350_probe_dt()
1160 if (of_get_property(np, "st,invalid-input-detect-mute", NULL)) in sta350_probe_dt()
1161 pdata->invalid_input_detect_mute = 1; in sta350_probe_dt()
1164 if (of_get_property(np, "st,activate-mute-output", NULL)) in sta350_probe_dt()
1165 pdata->activate_mute_output = 1; in sta350_probe_dt()
1167 if (of_get_property(np, "st,bridge-immediate-off", NULL)) in sta350_probe_dt()
1168 pdata->bridge_immediate_off = 1; in sta350_probe_dt()
1170 if (of_get_property(np, "st,noise-shape-dc-cut", NULL)) in sta350_probe_dt()
1171 pdata->noise_shape_dc_cut = 1; in sta350_probe_dt()
1173 if (of_get_property(np, "st,powerdown-master-volume", NULL)) in sta350_probe_dt()
1174 pdata->powerdown_master_vol = 1; in sta350_probe_dt()
1176 if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) { in sta350_probe_dt()
1178 pdata->powerdown_delay_divider = ilog2(tmp8); in sta350_probe_dt()
1184 sta350->pdata = pdata; in sta350_probe_dt()
1193 struct device *dev = &i2c->dev; in sta350_i2c_probe()
1199 return -ENOMEM; in sta350_i2c_probe()
1201 mutex_init(&sta350->coeff_lock); in sta350_i2c_probe()
1202 sta350->pdata = dev_get_platdata(dev); in sta350_i2c_probe()
1205 if (dev->of_node) { in sta350_i2c_probe()
1212 /* GPIOs */ in sta350_i2c_probe()
1213 sta350->gpiod_nreset = devm_gpiod_get_optional(dev, "reset", in sta350_i2c_probe()
1215 if (IS_ERR(sta350->gpiod_nreset)) in sta350_i2c_probe()
1216 return PTR_ERR(sta350->gpiod_nreset); in sta350_i2c_probe()
1218 sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down", in sta350_i2c_probe()
1220 if (IS_ERR(sta350->gpiod_power_down)) in sta350_i2c_probe()
1221 return PTR_ERR(sta350->gpiod_power_down); in sta350_i2c_probe()
1224 for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++) in sta350_i2c_probe()
1225 sta350->supplies[i].supply = sta350_supply_names[i]; in sta350_i2c_probe()
1227 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sta350->supplies), in sta350_i2c_probe()
1228 sta350->supplies); in sta350_i2c_probe()
1234 sta350->regmap = devm_regmap_init_i2c(i2c, &sta350_regmap); in sta350_i2c_probe()
1235 if (IS_ERR(sta350->regmap)) { in sta350_i2c_probe()
1236 ret = PTR_ERR(sta350->regmap); in sta350_i2c_probe()