Lines Matching +full:ch3 +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0
3 * ALSA SoC Texas Instruments TAS6424 Quad-Channel Audio Amplifier
5 * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/
24 #include <sound/soc-dapm.h>
33 "dvdd", /* Digital power supply. Connect to 3.3-V supply. */
35 "pvdd", /* Class-D amp output FETs supply. */
53 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that
54 * setting the gain below -100 dB (register value <0x7) is effectively a MUTE
57 static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0);
61 TAS6424_CH1_VOL_CTRL, 0, 0xff, 0, dac_tlv),
63 TAS6424_CH2_VOL_CTRL, 0, 0xff, 0, dac_tlv),
64 SOC_SINGLE_TLV("Speaker Driver CH3 Playback Volume",
65 TAS6424_CH3_VOL_CTRL, 0, 0xff, 0, dac_tlv),
67 TAS6424_CH4_VOL_CTRL, 0, 0xff, 0, dac_tlv),
75 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in tas6424_dac_event()
78 dev_dbg(component->dev, "%s() event=0x%0x\n", __func__, event); in tas6424_dac_event()
81 /* Observe codec shutdown-to-active time */ in tas6424_dac_event()
85 tas6424->last_fault1 = 0; in tas6424_dac_event()
86 tas6424->last_fault2 = 0; in tas6424_dac_event()
87 tas6424->last_warn = 0; in tas6424_dac_event()
88 schedule_delayed_work(&tas6424->fault_check_work, in tas6424_dac_event()
92 cancel_delayed_work_sync(&tas6424->fault_check_work); in tas6424_dac_event()
95 return 0; in tas6424_dac_event()
99 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
100 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas6424_dac_event,
114 struct snd_soc_component *component = dai->component; in tas6424_hw_params()
117 u8 sap_ctrl = 0; in tas6424_hw_params()
119 dev_dbg(component->dev, "%s() rate=%u width=%u\n", __func__, rate, width); in tas6424_hw_params()
132 dev_err(component->dev, "unsupported sample rate: %u\n", rate); in tas6424_hw_params()
133 return -EINVAL; in tas6424_hw_params()
143 dev_err(component->dev, "unsupported sample width: %u\n", width); in tas6424_hw_params()
144 return -EINVAL; in tas6424_hw_params()
152 return 0; in tas6424_hw_params()
157 struct snd_soc_component *component = dai->component; in tas6424_set_dai_fmt()
158 u8 serial_format = 0; in tas6424_set_dai_fmt()
160 dev_dbg(component->dev, "%s() fmt=0x%0x\n", __func__, fmt); in tas6424_set_dai_fmt()
167 dev_err(component->dev, "Invalid DAI master/slave interface\n"); in tas6424_set_dai_fmt()
168 return -EINVAL; in tas6424_set_dai_fmt()
176 dev_err(component->dev, "Invalid DAI clock signal polarity\n"); in tas6424_set_dai_fmt()
177 return -EINVAL; in tas6424_set_dai_fmt()
200 dev_err(component->dev, "Invalid DAI interface format\n"); in tas6424_set_dai_fmt()
201 return -EINVAL; in tas6424_set_dai_fmt()
207 return 0; in tas6424_set_dai_fmt()
214 struct snd_soc_component *component = dai->component; in tas6424_set_dai_tdm_slot()
218 dev_dbg(component->dev, "%s() tx_mask=%d rx_mask=%d\n", __func__, in tas6424_set_dai_tdm_slot()
222 return 0; /* nothing needed to disable TDM mode */ in tas6424_set_dai_tdm_slot()
232 if (last_slot - first_slot != 4) { in tas6424_set_dai_tdm_slot()
233 dev_err(component->dev, "tdm mask must cover 4 contiguous slots\n"); in tas6424_set_dai_tdm_slot()
234 return -EINVAL; in tas6424_set_dai_tdm_slot()
238 case 0: in tas6424_set_dai_tdm_slot()
245 dev_err(component->dev, "tdm mask must start at slot 0 or 4\n"); in tas6424_set_dai_tdm_slot()
246 return -EINVAL; in tas6424_set_dai_tdm_slot()
250 sap_tdm_slot_last ? TAS6424_SAP_TDM_SLOT_LAST : 0); in tas6424_set_dai_tdm_slot()
252 return 0; in tas6424_set_dai_tdm_slot()
257 struct snd_soc_component *component = dai->component; in tas6424_mute()
261 dev_dbg(component->dev, "%s() mute=%d\n", __func__, mute); in tas6424_mute()
263 if (tas6424->mute_gpio) { in tas6424_mute()
264 gpiod_set_value_cansleep(tas6424->mute_gpio, mute); in tas6424_mute()
265 return 0; in tas6424_mute()
275 return 0; in tas6424_mute()
285 regcache_cache_only(tas6424->regmap, true); in tas6424_power_off()
286 regcache_mark_dirty(tas6424->regmap); in tas6424_power_off()
288 ret = regulator_bulk_disable(ARRAY_SIZE(tas6424->supplies), in tas6424_power_off()
289 tas6424->supplies); in tas6424_power_off()
290 if (ret < 0) { in tas6424_power_off()
291 dev_err(component->dev, "failed to disable supplies: %d\n", ret); in tas6424_power_off()
295 return 0; in tas6424_power_off()
303 int no_auto_diags = 0; in tas6424_power_on()
306 if (!regmap_read(tas6424->regmap, TAS6424_DC_DIAG_CTRL1, &reg_val)) in tas6424_power_on()
309 ret = regulator_bulk_enable(ARRAY_SIZE(tas6424->supplies), in tas6424_power_on()
310 tas6424->supplies); in tas6424_power_on()
311 if (ret < 0) { in tas6424_power_on()
312 dev_err(component->dev, "failed to enable supplies: %d\n", ret); in tas6424_power_on()
316 regcache_cache_only(tas6424->regmap, false); in tas6424_power_on()
318 ret = regcache_sync(tas6424->regmap); in tas6424_power_on()
319 if (ret < 0) { in tas6424_power_on()
320 dev_err(component->dev, "failed to sync regcache: %d\n", ret); in tas6424_power_on()
324 if (tas6424->mute_gpio) { in tas6424_power_on()
325 gpiod_set_value_cansleep(tas6424->mute_gpio, 0); in tas6424_power_on()
329 * access is not necessary to un-mute the channels in tas6424_power_on()
344 return 0; in tas6424_power_on()
350 dev_dbg(component->dev, "%s() level=%d\n", __func__, level); in tas6424_set_bias_level()
365 return 0; in tas6424_set_bias_level()
391 .name = "tas6424-amplifier",
407 struct device *dev = tas6424->dev; in tas6424_fault_check_work()
411 ret = regmap_read(tas6424->regmap, TAS6424_CHANNEL_FAULT, &reg); in tas6424_fault_check_work()
412 if (ret < 0) { in tas6424_fault_check_work()
418 tas6424->last_cfault = reg; in tas6424_fault_check_work()
428 if ((reg & TAS6424_FAULT_OC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH1)) in tas6424_fault_check_work()
431 if ((reg & TAS6424_FAULT_OC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH2)) in tas6424_fault_check_work()
434 if ((reg & TAS6424_FAULT_OC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH3)) in tas6424_fault_check_work()
437 if ((reg & TAS6424_FAULT_OC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH4)) in tas6424_fault_check_work()
440 if ((reg & TAS6424_FAULT_DC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH1)) in tas6424_fault_check_work()
443 if ((reg & TAS6424_FAULT_DC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH2)) in tas6424_fault_check_work()
446 if ((reg & TAS6424_FAULT_DC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH3)) in tas6424_fault_check_work()
449 if ((reg & TAS6424_FAULT_DC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH4)) in tas6424_fault_check_work()
453 tas6424->last_cfault = reg; in tas6424_fault_check_work()
456 ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT1, &reg); in tas6424_fault_check_work()
457 if (ret < 0) { in tas6424_fault_check_work()
466 * stopped to avoid any false-positives. However there are no in tas6424_fault_check_work()
475 tas6424->last_fault1 = reg; in tas6424_fault_check_work()
479 if ((reg & TAS6424_FAULT_PVDD_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_OV)) in tas6424_fault_check_work()
482 if ((reg & TAS6424_FAULT_VBAT_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_VBAT_OV)) in tas6424_fault_check_work()
485 if ((reg & TAS6424_FAULT_PVDD_UV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_UV)) in tas6424_fault_check_work()
488 if ((reg & TAS6424_FAULT_VBAT_UV) && !(tas6424->last_fault1 & TAS6424_FAULT_VBAT_UV)) in tas6424_fault_check_work()
492 tas6424->last_fault1 = reg; in tas6424_fault_check_work()
495 ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT2, &reg); in tas6424_fault_check_work()
496 if (ret < 0) { in tas6424_fault_check_work()
508 tas6424->last_fault2 = reg; in tas6424_fault_check_work()
512 if ((reg & TAS6424_FAULT_OTSD) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD)) in tas6424_fault_check_work()
515 if ((reg & TAS6424_FAULT_OTSD_CH1) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD_CH1)) in tas6424_fault_check_work()
518 if ((reg & TAS6424_FAULT_OTSD_CH2) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD_CH2)) in tas6424_fault_check_work()
521 if ((reg & TAS6424_FAULT_OTSD_CH3) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD_CH3)) in tas6424_fault_check_work()
522 dev_crit(dev, "experienced an overtemp shutdown on CH3\n"); in tas6424_fault_check_work()
524 if ((reg & TAS6424_FAULT_OTSD_CH4) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD_CH4)) in tas6424_fault_check_work()
528 tas6424->last_fault2 = reg; in tas6424_fault_check_work()
531 ret = regmap_read(tas6424->regmap, TAS6424_WARN, &reg); in tas6424_fault_check_work()
532 if (ret < 0) { in tas6424_fault_check_work()
546 tas6424->last_warn = reg; in tas6424_fault_check_work()
550 if ((reg & TAS6424_WARN_VDD_UV) && !(tas6424->last_warn & TAS6424_WARN_VDD_UV)) in tas6424_fault_check_work()
553 if ((reg & TAS6424_WARN_VDD_POR) && !(tas6424->last_warn & TAS6424_WARN_VDD_POR)) in tas6424_fault_check_work()
556 if ((reg & TAS6424_WARN_VDD_OTW) && !(tas6424->last_warn & TAS6424_WARN_VDD_OTW)) in tas6424_fault_check_work()
559 if ((reg & TAS6424_WARN_VDD_OTW_CH1) && !(tas6424->last_warn & TAS6424_WARN_VDD_OTW_CH1)) in tas6424_fault_check_work()
562 if ((reg & TAS6424_WARN_VDD_OTW_CH2) && !(tas6424->last_warn & TAS6424_WARN_VDD_OTW_CH2)) in tas6424_fault_check_work()
565 if ((reg & TAS6424_WARN_VDD_OTW_CH3) && !(tas6424->last_warn & TAS6424_WARN_VDD_OTW_CH3)) in tas6424_fault_check_work()
566 dev_warn(dev, "experienced an overtemp warning on CH3\n"); in tas6424_fault_check_work()
568 if ((reg & TAS6424_WARN_VDD_OTW_CH4) && !(tas6424->last_warn & TAS6424_WARN_VDD_OTW_CH4)) in tas6424_fault_check_work()
572 tas6424->last_warn = reg; in tas6424_fault_check_work()
575 ret = regmap_write_bits(tas6424->regmap, TAS6424_MISC_CTRL3, in tas6424_fault_check_work()
577 if (ret < 0) in tas6424_fault_check_work()
580 ret = regmap_write_bits(tas6424->regmap, TAS6424_MISC_CTRL3, in tas6424_fault_check_work()
581 TAS6424_CLEAR_FAULT, 0); in tas6424_fault_check_work()
582 if (ret < 0) in tas6424_fault_check_work()
587 schedule_delayed_work(&tas6424->fault_check_work, in tas6424_fault_check_work()
592 { TAS6424_MODE_CTRL, 0x00 },
593 { TAS6424_MISC_CTRL1, 0x32 },
594 { TAS6424_MISC_CTRL2, 0x62 },
595 { TAS6424_SAP_CTRL, 0x04 },
596 { TAS6424_CH_STATE_CTRL, 0x55 },
597 { TAS6424_CH1_VOL_CTRL, 0xcf },
598 { TAS6424_CH2_VOL_CTRL, 0xcf },
599 { TAS6424_CH3_VOL_CTRL, 0xcf },
600 { TAS6424_CH4_VOL_CTRL, 0xcf },
601 { TAS6424_DC_DIAG_CTRL1, 0x00 },
602 { TAS6424_DC_DIAG_CTRL2, 0x11 },
603 { TAS6424_DC_DIAG_CTRL3, 0x11 },
604 { TAS6424_PIN_CTRL, 0xff },
605 { TAS6424_AC_DIAG_CTRL1, 0x00 },
606 { TAS6424_MISC_CTRL3, 0x00 },
607 { TAS6424_CLIP_CTRL, 0x01 },
608 { TAS6424_CLIP_WINDOW, 0x14 },
609 { TAS6424_CLIP_WARN, 0x00 },
610 { TAS6424_CBC_STAT, 0x00 },
611 { TAS6424_MISC_CTRL4, 0x40 },
688 struct device *dev = &client->dev; in tas6424_i2c_probe()
695 return -ENOMEM; in tas6424_i2c_probe()
698 tas6424->dev = dev; in tas6424_i2c_probe()
700 tas6424->regmap = devm_regmap_init_i2c(client, &tas6424_regmap_config); in tas6424_i2c_probe()
701 if (IS_ERR(tas6424->regmap)) { in tas6424_i2c_probe()
702 ret = PTR_ERR(tas6424->regmap); in tas6424_i2c_probe()
709 * out of the stand-by mode. in tas6424_i2c_probe()
713 tas6424->standby_gpio = devm_gpiod_get_optional(dev, "standby", in tas6424_i2c_probe()
715 if (IS_ERR(tas6424->standby_gpio)) { in tas6424_i2c_probe()
716 if (PTR_ERR(tas6424->standby_gpio) == -EPROBE_DEFER) in tas6424_i2c_probe()
717 return -EPROBE_DEFER; in tas6424_i2c_probe()
719 PTR_ERR(tas6424->standby_gpio)); in tas6424_i2c_probe()
720 tas6424->standby_gpio = NULL; in tas6424_i2c_probe()
729 tas6424->mute_gpio = devm_gpiod_get_optional(dev, "mute", in tas6424_i2c_probe()
731 if (IS_ERR(tas6424->mute_gpio)) { in tas6424_i2c_probe()
732 if (PTR_ERR(tas6424->mute_gpio) == -EPROBE_DEFER) in tas6424_i2c_probe()
733 return -EPROBE_DEFER; in tas6424_i2c_probe()
735 PTR_ERR(tas6424->mute_gpio)); in tas6424_i2c_probe()
736 tas6424->mute_gpio = NULL; in tas6424_i2c_probe()
739 for (i = 0; i < ARRAY_SIZE(tas6424->supplies); i++) in tas6424_i2c_probe()
740 tas6424->supplies[i].supply = tas6424_supply_names[i]; in tas6424_i2c_probe()
741 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(tas6424->supplies), in tas6424_i2c_probe()
742 tas6424->supplies); in tas6424_i2c_probe()
748 ret = regulator_bulk_enable(ARRAY_SIZE(tas6424->supplies), in tas6424_i2c_probe()
749 tas6424->supplies); in tas6424_i2c_probe()
755 /* Reset device to establish well-defined startup state */ in tas6424_i2c_probe()
756 ret = regmap_update_bits(tas6424->regmap, TAS6424_MODE_CTRL, in tas6424_i2c_probe()
763 INIT_DELAYED_WORK(&tas6424->fault_check_work, tas6424_fault_check_work); in tas6424_i2c_probe()
767 if (ret < 0) { in tas6424_i2c_probe()
772 return 0; in tas6424_i2c_probe()
777 struct device *dev = &client->dev; in tas6424_i2c_remove()
781 cancel_delayed_work_sync(&tas6424->fault_check_work); in tas6424_i2c_remove()
783 /* put the codec in stand-by */ in tas6424_i2c_remove()
784 if (tas6424->standby_gpio) in tas6424_i2c_remove()
785 gpiod_set_value_cansleep(tas6424->standby_gpio, 1); in tas6424_i2c_remove()
787 ret = regulator_bulk_disable(ARRAY_SIZE(tas6424->supplies), in tas6424_i2c_remove()
788 tas6424->supplies); in tas6424_i2c_remove()
789 if (ret < 0) { in tas6424_i2c_remove()
794 return 0; in tas6424_i2c_remove()
798 { "tas6424", 0 },