Lines Matching +full:dai +full:- +full:tdm +full:- +full:slot +full:- +full:width +full:- +full:map
1 // SPDX-License-Identifier: GPL-2.0-only
3 * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier
5 * Copyright (C)2015-2016 Texas Instruments Incorporated - https://www.ti.com
22 #include <sound/soc-dapm.h>
37 "dvdd", /* Digital power supply. Connect to 3.3-V supply. */
38 "pvdd", /* Class-D amp and analog power supply (connected). */
54 struct snd_soc_dai *dai) in tas5720_hw_params() argument
56 struct snd_soc_component *component = dai->component; in tas5720_hw_params()
71 dev_err(component->dev, "unsupported sample rate: %u\n", rate); in tas5720_hw_params()
72 return -EINVAL; in tas5720_hw_params()
78 dev_err(component->dev, "error setting sample rate: %d\n", ret); in tas5720_hw_params()
85 static int tas5720_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) in tas5720_set_dai_fmt() argument
87 struct snd_soc_component *component = dai->component; in tas5720_set_dai_fmt()
92 dev_vdbg(component->dev, "DAI clocking invalid\n"); in tas5720_set_dai_fmt()
93 return -EINVAL; in tas5720_set_dai_fmt()
105 * mode it doesn't care about the LRCLK duty cycle during TDM in tas5720_set_dai_fmt()
115 * not care about the LRCLK duty cycle during TDM to receive in tas5720_set_dai_fmt()
126 dev_vdbg(component->dev, "DAI Format is not found\n"); in tas5720_set_dai_fmt()
127 return -EINVAL; in tas5720_set_dai_fmt()
134 dev_err(component->dev, "error setting SAIF format: %d\n", ret); in tas5720_set_dai_fmt()
141 static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, in tas5720_set_dai_tdm_slot() argument
145 struct snd_soc_component *component = dai->component; in tas5720_set_dai_tdm_slot()
151 dev_err(component->dev, "tx masks must not be 0\n"); in tas5720_set_dai_tdm_slot()
152 return -EINVAL; in tas5720_set_dai_tdm_slot()
156 * Determine the first slot that is being requested. We will only in tas5720_set_dai_tdm_slot()
157 * use the first slot that is found since the TAS5720 is a mono in tas5720_set_dai_tdm_slot()
163 dev_err(component->dev, "slot selection out of bounds (%u)\n", in tas5720_set_dai_tdm_slot()
165 return -EINVAL; in tas5720_set_dai_tdm_slot()
169 * Enable manual TDM slot selection (instead of I2C ID based). in tas5720_set_dai_tdm_slot()
170 * This is not applicable to TAS5720A-Q1. in tas5720_set_dai_tdm_slot()
172 switch (tas5720->devtype) { in tas5720_set_dai_tdm_slot()
181 /* Configure the TDM slot to process audio from */ in tas5720_set_dai_tdm_slot()
189 /* Configure TDM slot width. This is only applicable to TAS5722. */ in tas5720_set_dai_tdm_slot()
190 switch (tas5720->devtype) { in tas5720_set_dai_tdm_slot()
206 dev_err(component->dev, "error configuring TDM mode: %d\n", ret); in tas5720_set_dai_tdm_slot()
216 switch (tas5720->devtype) { in tas5720_mute_soc_component()
229 dev_err(component->dev, "error (un-)muting device: %d\n", ret); in tas5720_mute_soc_component()
236 static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction) in tas5720_mute() argument
238 return tas5720_mute_soc_component(dai->component, mute); in tas5720_mute()
245 struct device *dev = tas5720->component->dev; in tas5720_fault_check_work()
249 ret = regmap_read(tas5720->regmap, TAS5720_FAULT_REG, &curr_fault); in tas5720_fault_check_work()
264 if ((curr_fault & TAS5720_OCE) && !(tas5720->last_fault & TAS5720_OCE)) in tas5720_fault_check_work()
267 if ((curr_fault & TAS5720_DCE) && !(tas5720->last_fault & TAS5720_DCE)) in tas5720_fault_check_work()
270 if ((curr_fault & TAS5720_OTE) && !(tas5720->last_fault & TAS5720_OTE)) in tas5720_fault_check_work()
274 tas5720->last_fault = curr_fault; in tas5720_fault_check_work()
280 * Periodically toggle SDZ (shutdown bit) H->L->H to clear any latching in tas5720_fault_check_work()
285 ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, in tas5720_fault_check_work()
290 ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, in tas5720_fault_check_work()
297 schedule_delayed_work(&tas5720->fault_check_work, in tas5720_fault_check_work()
307 tas5720->component = component; in tas5720_codec_probe()
309 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), in tas5720_codec_probe()
310 tas5720->supplies); in tas5720_codec_probe()
312 dev_err(component->dev, "failed to enable supplies: %d\n", ret); in tas5720_codec_probe()
321 ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id); in tas5720_codec_probe()
323 dev_err(component->dev, "failed to read device ID register: %d\n", in tas5720_codec_probe()
328 switch (tas5720->devtype) { in tas5720_codec_probe()
339 dev_err(component->dev, "unexpected private driver data\n"); in tas5720_codec_probe()
340 ret = -EINVAL; in tas5720_codec_probe()
345 dev_warn(component->dev, "wrong device ID. expected: %u read: %u\n", in tas5720_codec_probe()
354 switch (tas5720->devtype) { in tas5720_codec_probe()
367 * Enter shutdown mode - our default when not playing audio - to in tas5720_codec_probe()
377 INIT_DELAYED_WORK(&tas5720->fault_check_work, tas5720_fault_check_work); in tas5720_codec_probe()
382 dev_err(component->dev, "error configuring device registers: %d\n", ret); in tas5720_codec_probe()
385 regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), in tas5720_codec_probe()
386 tas5720->supplies); in tas5720_codec_probe()
395 cancel_delayed_work_sync(&tas5720->fault_check_work); in tas5720_codec_remove()
397 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), in tas5720_codec_remove()
398 tas5720->supplies); in tas5720_codec_remove()
400 dev_err(component->dev, "failed to disable supplies: %d\n", ret); in tas5720_codec_remove()
406 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in tas5720_dac_event()
415 dev_err(component->dev, "error waking component: %d\n", ret); in tas5720_dac_event()
420 * Observe codec shutdown-to-active time. The datasheet only in tas5720_dac_event()
421 * lists a nominal value however just use-it as-is without in tas5720_dac_event()
430 tas5720->last_fault = 0; in tas5720_dac_event()
431 schedule_delayed_work(&tas5720->fault_check_work, in tas5720_dac_event()
435 cancel_delayed_work_sync(&tas5720->fault_check_work); in tas5720_dac_event()
441 dev_err(component->dev, "error shutting down component: %d\n", in tas5720_dac_event()
456 regcache_cache_only(tas5720->regmap, true); in tas5720_suspend()
457 regcache_mark_dirty(tas5720->regmap); in tas5720_suspend()
459 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), in tas5720_suspend()
460 tas5720->supplies); in tas5720_suspend()
462 dev_err(component->dev, "failed to disable supplies: %d\n", ret); in tas5720_suspend()
472 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), in tas5720_resume()
473 tas5720->supplies); in tas5720_resume()
475 dev_err(component->dev, "failed to enable supplies: %d\n", ret); in tas5720_resume()
479 regcache_cache_only(tas5720->regmap, false); in tas5720_resume()
481 ret = regcache_sync(tas5720->regmap); in tas5720_resume()
483 dev_err(component->dev, "failed to sync regcache: %d\n", ret); in tas5720_resume()
544 * DAC analog gain for TAS5720A-Q1. There are three discrete values to select from, ranging
554 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps
555 * depending on the device. Note that setting the gain below -100 dB
561 static DECLARE_TLV_DB_SCALE(tas5720_dac_tlv, -10350, 50, 0);
562 static DECLARE_TLV_DB_SCALE(tas5722_dac_tlv, -10350, 25, 0);
571 ucontrol->value.integer.value[0] = val << 1; in tas5722_volume_get()
574 ucontrol->value.integer.value[0] |= val & TAS5722_VOL_CONTROL_LSB; in tas5722_volume_get()
583 unsigned int sel = ucontrol->value.integer.value[0]; in tas5722_volume_set()
694 * TAS5720 DAI structure
706 .name = "tas5720-amplifier",
720 { "tas5720a-q1", TAS5720A_Q1 },
728 struct device *dev = &client->dev; in tas5720_probe()
736 return -ENOMEM; in tas5720_probe()
738 data->devtype = (uintptr_t)i2c_get_match_data(client); in tas5720_probe()
740 switch (data->devtype) { in tas5720_probe()
752 return -EINVAL; in tas5720_probe()
754 data->regmap = devm_regmap_init_i2c(client, regmap_config); in tas5720_probe()
755 if (IS_ERR(data->regmap)) { in tas5720_probe()
756 ret = PTR_ERR(data->regmap); in tas5720_probe()
757 dev_err(dev, "failed to allocate register map: %d\n", ret); in tas5720_probe()
761 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) in tas5720_probe()
762 data->supplies[i].supply = tas5720_supply_names[i]; in tas5720_probe()
764 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), in tas5720_probe()
765 data->supplies); in tas5720_probe()
773 switch (data->devtype) { in tas5720_probe()
775 ret = devm_snd_soc_register_component(&client->dev, in tas5720_probe()
781 ret = devm_snd_soc_register_component(&client->dev, in tas5720_probe()
787 ret = devm_snd_soc_register_component(&client->dev, in tas5720_probe()
794 return -EINVAL; in tas5720_probe()
807 { .compatible = "ti,tas5720a-q1", },