Lines Matching +full:power +full:- +full:supplies
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>
55 /* Power-up register defaults */
154 /* regulator power supply names */
156 "vdd-dig", /* digital supply, 3.3V */
157 "vdd-pll", /* pll supply, 3.3V */
158 "vcc" /* power amp supply, 5V - 26V */
164 struct regulator_bulk_data supplies[ARRAY_SIZE(sta350_supply_names)]; member
179 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12750, 50, 1);
180 static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1);
181 static const DECLARE_TLV_DB_SCALE(tone_tlv, -1200, 200, 0);
184 "Anti-Clipping", "Dynamic Range Compression"
196 "FFX 3-state output - normal operation", "Binary output"
216 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0),
222 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0),
223 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0),
224 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0),
225 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0),
229 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0),
230 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0),
231 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0),
236 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0),
237 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0),
238 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0),
239 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
296 int numcoef = kcontrol->private_value >> 16; in sta350_coefficient_info()
297 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; in sta350_coefficient_info()
298 uinfo->count = 3 * numcoef; in sta350_coefficient_info()
307 int numcoef = kcontrol->private_value >> 16; in sta350_coefficient_get()
308 int index = kcontrol->private_value & 0xffff; in sta350_coefficient_get()
312 mutex_lock(&sta350->coeff_lock); in sta350_coefficient_get()
315 regmap_read(sta350->regmap, STA350_CFUD, &cfud); in sta350_coefficient_get()
321 regmap_write(sta350->regmap, STA350_CFUD, cfud); in sta350_coefficient_get()
323 regmap_write(sta350->regmap, STA350_CFADDR2, index); in sta350_coefficient_get()
325 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x04); in sta350_coefficient_get()
327 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x08); in sta350_coefficient_get()
329 ret = -EINVAL; in sta350_coefficient_get()
334 regmap_read(sta350->regmap, STA350_B1CF1 + i, &val); in sta350_coefficient_get()
335 ucontrol->value.bytes.data[i] = val; in sta350_coefficient_get()
339 mutex_unlock(&sta350->coeff_lock); in sta350_coefficient_get()
349 int numcoef = kcontrol->private_value >> 16; in sta350_coefficient_put()
350 int index = kcontrol->private_value & 0xffff; in sta350_coefficient_put()
355 regmap_read(sta350->regmap, STA350_CFUD, &cfud); in sta350_coefficient_put()
361 regmap_write(sta350->regmap, STA350_CFUD, cfud); in sta350_coefficient_put()
363 regmap_write(sta350->regmap, STA350_CFADDR2, index); in sta350_coefficient_put()
365 sta350->coef_shadow[index + i] = in sta350_coefficient_put()
366 (ucontrol->value.bytes.data[3 * i] << 16) in sta350_coefficient_put()
367 | (ucontrol->value.bytes.data[3 * i + 1] << 8) in sta350_coefficient_put()
368 | (ucontrol->value.bytes.data[3 * i + 2]); in sta350_coefficient_put()
370 regmap_write(sta350->regmap, STA350_B1CF1 + i, in sta350_coefficient_put()
371 ucontrol->value.bytes.data[i]); in sta350_coefficient_put()
373 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01); in sta350_coefficient_put()
375 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x02); in sta350_coefficient_put()
377 return -EINVAL; in sta350_coefficient_put()
389 regmap_read(sta350->regmap, STA350_CFUD, &cfud); in sta350_sync_coef_shadow()
393 regmap_write(sta350->regmap, STA350_CFADDR2, i); in sta350_sync_coef_shadow()
394 regmap_write(sta350->regmap, STA350_B1CF1, in sta350_sync_coef_shadow()
395 (sta350->coef_shadow[i] >> 16) & 0xff); in sta350_sync_coef_shadow()
396 regmap_write(sta350->regmap, STA350_B1CF2, in sta350_sync_coef_shadow()
397 (sta350->coef_shadow[i] >> 8) & 0xff); in sta350_sync_coef_shadow()
398 regmap_write(sta350->regmap, STA350_B1CF3, in sta350_sync_coef_shadow()
399 (sta350->coef_shadow[i]) & 0xff); in sta350_sync_coef_shadow()
402 * self-clearing, so do it explicitly in sta350_sync_coef_shadow()
404 regmap_write(sta350->regmap, STA350_CFUD, cfud); in sta350_sync_coef_shadow()
405 regmap_write(sta350->regmap, STA350_CFUD, cfud | 0x01); in sta350_sync_coef_shadow()
417 regmap_read(sta350->regmap, STA350_CFUD, &mute); in sta350_cache_sync()
418 regmap_write(sta350->regmap, STA350_MMUTE, mute | STA350_MMUTE_MMUTE); in sta350_cache_sync()
420 rc = regcache_sync(sta350->regmap); in sta350_cache_sync()
421 regmap_write(sta350->regmap, STA350_MMUTE, mute); in sta350_cache_sync()
448 SOC_SINGLE("De-emphasis Filter Switch",
452 SOC_SINGLE("Post-scale Link Switch",
458 SOC_SINGLE("Zero-detect Mute Enable Switch",
533 BIQUAD_COEFS("Ch1 - Biquad 1", 0),
534 BIQUAD_COEFS("Ch1 - Biquad 2", 5),
535 BIQUAD_COEFS("Ch1 - Biquad 3", 10),
536 BIQUAD_COEFS("Ch1 - Biquad 4", 15),
537 BIQUAD_COEFS("Ch2 - Biquad 1", 20),
538 BIQUAD_COEFS("Ch2 - Biquad 2", 25),
539 BIQUAD_COEFS("Ch2 - Biquad 3", 30),
540 BIQUAD_COEFS("Ch2 - Biquad 4", 35),
541 BIQUAD_COEFS("High-pass", 40),
542 BIQUAD_COEFS("Low-pass", 45),
543 SINGLE_COEF("Ch1 - Prescale", 50),
544 SINGLE_COEF("Ch2 - Prescale", 51),
545 SINGLE_COEF("Ch1 - Postscale", 52),
546 SINGLE_COEF("Ch2 - Postscale", 53),
547 SINGLE_COEF("Ch3 - Postscale", 54),
548 SINGLE_COEF("Thermal warning - Postscale", 55),
549 SINGLE_COEF("Ch1 - Mix 1", 56),
550 SINGLE_COEF("Ch1 - Mix 2", 57),
551 SINGLE_COEF("Ch2 - Mix 1", 58),
552 SINGLE_COEF("Ch2 - Mix 2", 59),
553 SINGLE_COEF("Ch3 - Mix 1", 60),
554 SINGLE_COEF("Ch3 - Mix 2", 61),
593 * sta350_set_dai_sysclk - configure MCLK
609 struct snd_soc_component *component = codec_dai->component; in sta350_set_dai_sysclk()
612 dev_dbg(component->dev, "mclk=%u\n", freq); in sta350_set_dai_sysclk()
613 sta350->mclk = freq; in sta350_set_dai_sysclk()
619 * sta350_set_dai_fmt - configure the codec for the selected audio format
629 struct snd_soc_component *component = codec_dai->component; in sta350_set_dai_fmt()
637 return -EINVAL; in sta350_set_dai_fmt()
644 sta350->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; in sta350_set_dai_fmt()
647 return -EINVAL; in sta350_set_dai_fmt()
658 return -EINVAL; in sta350_set_dai_fmt()
661 return regmap_update_bits(sta350->regmap, STA350_CONFB, in sta350_set_dai_fmt()
666 * sta350_hw_params - program the STA350 with the given hardware parameters.
678 struct snd_soc_component *component = dai->component; in sta350_hw_params()
680 int i, mcs = -EINVAL, ir = -EINVAL; in sta350_hw_params()
685 if (!sta350->mclk) { in sta350_hw_params()
686 dev_err(component->dev, in sta350_hw_params()
687 "sta350->mclk is unset. Unable to determine ratio\n"); in sta350_hw_params()
688 return -EIO; in sta350_hw_params()
692 ratio = sta350->mclk / rate; in sta350_hw_params()
693 dev_dbg(component->dev, "rate: %u, ratio: %u\n", rate, ratio); in sta350_hw_params()
703 dev_err(component->dev, "Unsupported samplerate: %u\n", rate); in sta350_hw_params()
704 return -EINVAL; in sta350_hw_params()
715 dev_err(component->dev, "Unresolvable ratio: %u\n", ratio); in sta350_hw_params()
716 return -EINVAL; in sta350_hw_params()
725 dev_dbg(component->dev, "24bit\n"); in sta350_hw_params()
728 dev_dbg(component->dev, "24bit or 32bit\n"); in sta350_hw_params()
729 switch (sta350->format) { in sta350_hw_params()
743 dev_dbg(component->dev, "20bit\n"); in sta350_hw_params()
744 switch (sta350->format) { in sta350_hw_params()
758 dev_dbg(component->dev, "18bit\n"); in sta350_hw_params()
759 switch (sta350->format) { in sta350_hw_params()
773 dev_dbg(component->dev, "16bit\n"); in sta350_hw_params()
774 switch (sta350->format) { in sta350_hw_params()
788 return -EINVAL; in sta350_hw_params()
791 ret = regmap_update_bits(sta350->regmap, STA350_CONFA, in sta350_hw_params()
797 ret = regmap_update_bits(sta350->regmap, STA350_CONFB, in sta350_hw_params()
808 if (sta350->gpiod_power_down) in sta350_startup_sequence()
809 gpiod_set_value(sta350->gpiod_power_down, 1); in sta350_startup_sequence()
811 if (sta350->gpiod_nreset) { in sta350_startup_sequence()
812 gpiod_set_value(sta350->gpiod_nreset, 0); in sta350_startup_sequence()
814 gpiod_set_value(sta350->gpiod_nreset, 1); in sta350_startup_sequence()
822 * sta350_set_bias_level - DAPM callback
824 * @level: DAPM power level
826 * This is called by ALSA to put the component into low power mode
828 * all registers must be restored after power on.
836 dev_dbg(component->dev, "level = %d\n", level); in sta350_set_bias_level()
842 /* Full power on */ in sta350_set_bias_level()
843 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_set_bias_level()
851 ARRAY_SIZE(sta350->supplies), in sta350_set_bias_level()
852 sta350->supplies); in sta350_set_bias_level()
854 dev_err(component->dev, in sta350_set_bias_level()
855 "Failed to enable supplies: %d\n", in sta350_set_bias_level()
863 /* Power down */ in sta350_set_bias_level()
864 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_set_bias_level()
871 /* The chip runs through the power down sequence for us */ in sta350_set_bias_level()
872 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_set_bias_level()
875 /* power down: low */ in sta350_set_bias_level()
876 if (sta350->gpiod_power_down) in sta350_set_bias_level()
877 gpiod_set_value(sta350->gpiod_power_down, 0); in sta350_set_bias_level()
879 if (sta350->gpiod_nreset) in sta350_set_bias_level()
880 gpiod_set_value(sta350->gpiod_nreset, 0); in sta350_set_bias_level()
882 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), in sta350_set_bias_level()
883 sta350->supplies); in sta350_set_bias_level()
896 .name = "sta350-hifi",
910 struct sta350_platform_data *pdata = sta350->pdata; in sta350_probe()
913 ret = regulator_bulk_enable(ARRAY_SIZE(sta350->supplies), in sta350_probe()
914 sta350->supplies); in sta350_probe()
916 dev_err(component->dev, "Failed to enable supplies: %d\n", ret); in sta350_probe()
922 dev_err(component->dev, "Failed to startup device\n"); in sta350_probe()
927 if (!pdata->thermal_warning_recovery) in sta350_probe()
929 if (!pdata->thermal_warning_adjustment) in sta350_probe()
931 if (!pdata->fault_detect_recovery) in sta350_probe()
933 regmap_update_bits(sta350->regmap, STA350_CONFA, in sta350_probe()
939 regmap_update_bits(sta350->regmap, STA350_CONFC, in sta350_probe()
941 pdata->ffx_power_output_mode in sta350_probe()
943 regmap_update_bits(sta350->regmap, STA350_CONFC, in sta350_probe()
945 pdata->drop_compensation_ns in sta350_probe()
947 regmap_update_bits(sta350->regmap, in sta350_probe()
950 pdata->oc_warning_adjustment ? in sta350_probe()
954 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
956 pdata->max_power_use_mpcc ? in sta350_probe()
958 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
960 pdata->max_power_correction ? in sta350_probe()
962 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
964 pdata->am_reduction_mode ? in sta350_probe()
966 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
968 pdata->odd_pwm_speed_mode ? in sta350_probe()
970 regmap_update_bits(sta350->regmap, STA350_CONFE, in sta350_probe()
972 pdata->distortion_compensation ? in sta350_probe()
975 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_probe()
977 pdata->invalid_input_detect_mute ? in sta350_probe()
979 regmap_update_bits(sta350->regmap, STA350_CONFF, in sta350_probe()
981 pdata->output_conf in sta350_probe()
985 regmap_update_bits(sta350->regmap, STA350_C1CFG, in sta350_probe()
987 pdata->ch1_output_mapping in sta350_probe()
989 regmap_update_bits(sta350->regmap, STA350_C2CFG, in sta350_probe()
991 pdata->ch2_output_mapping in sta350_probe()
993 regmap_update_bits(sta350->regmap, STA350_C3CFG, in sta350_probe()
995 pdata->ch3_output_mapping in sta350_probe()
999 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1001 pdata->activate_mute_output ? in sta350_probe()
1003 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1005 pdata->bridge_immediate_off ? in sta350_probe()
1007 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1009 pdata->noise_shape_dc_cut ? in sta350_probe()
1011 regmap_update_bits(sta350->regmap, STA350_MISC1, in sta350_probe()
1013 pdata->powerdown_master_vol ? in sta350_probe()
1016 regmap_update_bits(sta350->regmap, STA350_MISC2, in sta350_probe()
1018 pdata->powerdown_delay_divider in sta350_probe()
1023 sta350->coef_shadow[i] = 0x400000; in sta350_probe()
1025 sta350->coef_shadow[i] = 0x7fffff; in sta350_probe()
1026 sta350->coef_shadow[55] = 0x5a9df7; in sta350_probe()
1027 sta350->coef_shadow[56] = 0x7fffff; in sta350_probe()
1028 sta350->coef_shadow[59] = 0x7fffff; in sta350_probe()
1029 sta350->coef_shadow[60] = 0x400000; in sta350_probe()
1030 sta350->coef_shadow[61] = 0x400000; in sta350_probe()
1034 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); in sta350_probe()
1043 regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); in sta350_remove()
1082 [STA350_FFX_PM_DROP_COMP] = "drop-compensation",
1083 [STA350_FFX_PM_TAPERED_COMP] = "tapered-compensation",
1084 [STA350_FFX_PM_FULL_POWER] = "full-power-mode",
1085 [STA350_FFX_PM_VARIABLE_DROP_COMP] = "variable-drop-compensation",
1090 struct device_node *np = dev->of_node; in sta350_probe_dt()
1098 return -ENOMEM; in sta350_probe_dt()
1100 of_property_read_u8(np, "st,output-conf", in sta350_probe_dt()
1101 &pdata->output_conf); in sta350_probe_dt()
1102 of_property_read_u8(np, "st,ch1-output-mapping", in sta350_probe_dt()
1103 &pdata->ch1_output_mapping); in sta350_probe_dt()
1104 of_property_read_u8(np, "st,ch2-output-mapping", in sta350_probe_dt()
1105 &pdata->ch2_output_mapping); in sta350_probe_dt()
1106 of_property_read_u8(np, "st,ch3-output-mapping", in sta350_probe_dt()
1107 &pdata->ch3_output_mapping); in sta350_probe_dt()
1109 pdata->thermal_warning_recovery = in sta350_probe_dt()
1110 of_property_read_bool(np, "st,thermal-warning-recovery"); in sta350_probe_dt()
1111 pdata->thermal_warning_adjustment = in sta350_probe_dt()
1112 of_property_read_bool(np, "st,thermal-warning-adjustment"); in sta350_probe_dt()
1113 pdata->fault_detect_recovery = in sta350_probe_dt()
1114 of_property_read_bool(np, "st,fault-detect-recovery"); in sta350_probe_dt()
1116 pdata->ffx_power_output_mode = STA350_FFX_PM_VARIABLE_DROP_COMP; in sta350_probe_dt()
1117 if (!of_property_read_string(np, "st,ffx-power-output-mode", in sta350_probe_dt()
1119 int i, mode = -EINVAL; in sta350_probe_dt()
1129 pdata->ffx_power_output_mode = mode; in sta350_probe_dt()
1133 of_property_read_u16(np, "st,drop-compensation-ns", &tmp); in sta350_probe_dt()
1134 pdata->drop_compensation_ns = clamp_t(u16, tmp, 0, 300) / 20; in sta350_probe_dt()
1136 pdata->oc_warning_adjustment = in sta350_probe_dt()
1137 of_property_read_bool(np, "st,overcurrent-warning-adjustment"); in sta350_probe_dt()
1140 pdata->max_power_use_mpcc = in sta350_probe_dt()
1141 of_property_read_bool(np, "st,max-power-use-mpcc"); in sta350_probe_dt()
1142 pdata->max_power_correction = in sta350_probe_dt()
1143 of_property_read_bool(np, "st,max-power-correction"); in sta350_probe_dt()
1144 pdata->am_reduction_mode = in sta350_probe_dt()
1145 of_property_read_bool(np, "st,am-reduction-mode"); in sta350_probe_dt()
1146 pdata->odd_pwm_speed_mode = in sta350_probe_dt()
1147 of_property_read_bool(np, "st,odd-pwm-speed-mode"); in sta350_probe_dt()
1148 pdata->distortion_compensation = in sta350_probe_dt()
1149 of_property_read_bool(np, "st,distortion-compensation"); in sta350_probe_dt()
1152 pdata->invalid_input_detect_mute = in sta350_probe_dt()
1153 of_property_read_bool(np, "st,invalid-input-detect-mute"); in sta350_probe_dt()
1156 pdata->activate_mute_output = in sta350_probe_dt()
1157 of_property_read_bool(np, "st,activate-mute-output"); in sta350_probe_dt()
1158 pdata->bridge_immediate_off = in sta350_probe_dt()
1159 of_property_read_bool(np, "st,bridge-immediate-off"); in sta350_probe_dt()
1160 pdata->noise_shape_dc_cut = in sta350_probe_dt()
1161 of_property_read_bool(np, "st,noise-shape-dc-cut"); in sta350_probe_dt()
1162 pdata->powerdown_master_vol = in sta350_probe_dt()
1163 of_property_read_bool(np, "st,powerdown-master-volume"); in sta350_probe_dt()
1165 if (!of_property_read_u8(np, "st,powerdown-delay-divider", &tmp8)) { in sta350_probe_dt()
1167 pdata->powerdown_delay_divider = ilog2(tmp8); in sta350_probe_dt()
1173 sta350->pdata = pdata; in sta350_probe_dt()
1181 struct device *dev = &i2c->dev; in sta350_i2c_probe()
1187 return -ENOMEM; in sta350_i2c_probe()
1189 mutex_init(&sta350->coeff_lock); in sta350_i2c_probe()
1190 sta350->pdata = dev_get_platdata(dev); in sta350_i2c_probe()
1193 if (dev->of_node) { in sta350_i2c_probe()
1201 sta350->gpiod_nreset = devm_gpiod_get_optional(dev, "reset", in sta350_i2c_probe()
1203 if (IS_ERR(sta350->gpiod_nreset)) in sta350_i2c_probe()
1204 return PTR_ERR(sta350->gpiod_nreset); in sta350_i2c_probe()
1206 sta350->gpiod_power_down = devm_gpiod_get_optional(dev, "power-down", in sta350_i2c_probe()
1208 if (IS_ERR(sta350->gpiod_power_down)) in sta350_i2c_probe()
1209 return PTR_ERR(sta350->gpiod_power_down); in sta350_i2c_probe()
1212 for (i = 0; i < ARRAY_SIZE(sta350->supplies); i++) in sta350_i2c_probe()
1213 sta350->supplies[i].supply = sta350_supply_names[i]; in sta350_i2c_probe()
1215 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sta350->supplies), in sta350_i2c_probe()
1216 sta350->supplies); in sta350_i2c_probe()
1218 dev_err(dev, "Failed to request supplies: %d\n", ret); in sta350_i2c_probe()
1222 sta350->regmap = devm_regmap_init_i2c(i2c, &sta350_regmap); in sta350_i2c_probe()
1223 if (IS_ERR(sta350->regmap)) { in sta350_i2c_probe()
1224 ret = PTR_ERR(sta350->regmap); in sta350_i2c_probe()