diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 8121978a31a8..cb3b581dbfb5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -216,6 +216,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TAS5720 imply SND_SOC_TAS6424 imply SND_SOC_TDA7419 + imply SND_SOC_TDA7803 imply SND_SOC_TFA9879 imply SND_SOC_TLV320ADCX140 imply SND_SOC_TLV320AIC23_I2C @@ -1442,6 +1443,11 @@ config SND_SOC_TDA7419 depends on I2C select REGMAP_I2C +config SND_SOC_TDA7803 + tristate "ST TDA7803 audio processor" + depends on I2C + select REGMAP_I2C + config SND_SOC_TFA9879 tristate "NXP Semiconductors TFA9879 amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 20ee39074e71..fd3e6861e75c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -232,6 +232,7 @@ snd-soc-tas571x-objs := tas571x.o snd-soc-tas5720-objs := tas5720.o snd-soc-tas6424-objs := tas6424.o snd-soc-tda7419-objs := tda7419.o +snd-soc-tda7803-objs := tda7803.o snd-soc-tas2770-objs := tas2770.o snd-soc-tfa9879-objs := tfa9879.o snd-soc-tlv320aic23-objs := tlv320aic23.o @@ -560,6 +561,7 @@ obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o +obj-$(CONFIG_SND_SOC_TDA7803) += snd-soc-tda7803.o obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o diff --git a/sound/soc/codecs/tda7803.c b/sound/soc/codecs/tda7803.c new file mode 100644 index 000000000000..b75459180f0b --- /dev/null +++ b/sound/soc/codecs/tda7803.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tda7803.h" + +#define TDA7803_SAMPLE_RATE \ + (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) + +struct tda7803_priv { + struct regmap *regmap; + u32 input_format; +}; + +static int tda7803_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct tda7803_priv *tda7803 = snd_soc_component_get_drvdata(component); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int val = 0; + + snd_soc_component_write(component, TDA7803_REG2, DIGITAL_MUTE_OFF | + CH2_4_UMUTE | CH1_3_UMUTE | + MUTE_TIME_SETTING_1_45MS); + snd_soc_component_write(component, TDA7803_REG7, AMPLIEFIR_SWITCH_ON); + + switch (tda7803->input_format) { + case 0: + val = INPUT_FORMAT_TDM_8CH_MODEL1; + break; + case 1: + val = INPUT_FORMAT_TDM_8CH_MODEL2; + break; + default: + return -EINVAL; + } + + snd_soc_dai_set_fmt(codec_dai, val); + + return 0; +} + +static int tda7803_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + int val = 0; + + switch (params_rate(params)) { + case 44100: + val = SAMPLE_FREQUENCY_RANGE_44100HZ; + break; + case 48000: + val = SAMPLE_FREQUENCY_RANGE_48000HZ; + break; + case 96000: + val = SAMPLE_FREQUENCY_RANGE_96000HZ; + break; + case 192000: + val = SAMPLE_FREQUENCY_RANGE_192000HZ; + break; + default: + return -EINVAL; + } + + snd_soc_component_write(component, TDA7803_REG3, val); + + return 0; +} + +static int tda7803_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + + snd_soc_component_write(component, TDA7803_REG3, fmt); + + return 0; +} + +static const struct snd_soc_dai_ops tda7803_ops = { + .startup = tda7803_startup, + .hw_params = tda7803_hw_params, + .set_fmt = tda7803_set_fmt, +}; + +static struct snd_soc_dai_driver tda7803_dai = { + .name = "tda7803-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 8, + .rates = TDA7803_SAMPLE_RATE, + .formats = SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &tda7803_ops, +}; + +static const struct snd_soc_component_driver soc_codec_dev_tda7803 = { + .name = "tda7803", +}; + +static const struct regmap_config tda7803_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TDA7803_REGMAX, + .cache_type = REGCACHE_RBTREE, +}; + +static int tda7803_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct tda7803_priv *tda7803; + int val; + + tda7803 = devm_kzalloc(&i2c->dev, sizeof(*tda7803), GFP_KERNEL); + if (!tda7803) + return -ENOMEM; + + i2c_set_clientdata(i2c, tda7803); + + tda7803->regmap = devm_regmap_init_i2c(i2c, &tda7803_i2c_regmap); + if (IS_ERR(tda7803->regmap)) + return PTR_ERR(tda7803->regmap); + + if (!device_property_read_u32(&i2c->dev, "st,tda7803-format", &val)) + tda7803->input_format = val; + + return devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_tda7803, + &tda7803_dai, 1); +} + +static const struct i2c_device_id tda7803_i2c_id[] = { + { "tda7803", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tda7803_i2c_id); + +static const struct of_device_id tda7803_of_match[] = { + { .compatible = "st,tda7803" }, + { }, +}; + +static struct i2c_driver tda7803_i2c_driver = { + .driver = { + .name = "tda7803", + .of_match_table = of_match_ptr(tda7803_of_match), + }, + .probe = tda7803_i2c_probe, + .id_table = tda7803_i2c_id, +}; +module_i2c_driver(tda7803_i2c_driver); + +MODULE_AUTHOR("Jun Zeng "); +MODULE_DESCRIPTION("TDA7803 audio processor driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tda7803.h b/sound/soc/codecs/tda7803.h new file mode 100644 index 000000000000..54a7b610722f --- /dev/null +++ b/sound/soc/codecs/tda7803.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + * + */ + +#ifndef __TDA7803_H__ +#define __TDA7803_H__ + +/* tda7803 registers space*/ +#define TDA7803_REG0 (0x00) +#define CH1_AMP_SBI_MODE (0x00 << 0) +#define CH1_AMP_ABI_MODE (0x01 << 0) +#define CH2_AMP_SBI_MODE (0x00 << 1) +#define CH2_AMP_ABI_MODE (0x01 << 1) +#define CH3_AMP_SBI_MODE (0x00 << 2) +#define CH3_AMP_ABI_MODE (0x01 << 2) +#define CH4_AMP_SBI_MODE (0x00 << 3) +#define CH4_AMP_ABI_MODE (0x01 << 3) +#define CH1_TRI_MODE_OFF (0x00 << 4) +#define CH1_TRI_MODE_ON (0x01 << 4) +#define CH2_TRI_MODE_OFF (0x00 << 5) +#define CH2_TRI_MODE_ON (0x01 << 5) +#define CH3_TRI_MODE_OFF (0x00 << 6) +#define CH3_TRI_MODE_ON (0x01 << 6) +#define CH4_TRI_MODE_OFF (0x00 << 7) +#define CH4_TRI_MODE_ON (0x01 << 7) + +#define TDA7803_REG1 (0x01) +#define CH2_4_GAIN_GV1 (0x00 << 0) +#define CH2_4_GAIN_GV2 (0x01 << 0) +#define CH2_4_GAIN_GV3 (0x02 << 0) +#define CH2_4_GAIN_GV4 (0x03 << 0) +#define CH1_3_GAIN_GV1 (0x00 << 2) +#define CH1_3_GAIN_GV2 (0x01 << 2) +#define CH1_3_GAIN_GV3 (0x02 << 2) +#define CH1_3_GAIN_GV4 (0x03 << 2) +#define GAIN_SELECT_NO (0x00 << 4) +#define GAIN_SELECT_6DB (0x01 << 4) +#define GAIN_SELECT_12DB (0x02 << 4) +#define GAIN_SELECT_NOT_USED (0x03 << 4) +#define IMPEDANCE_OPTIMIZER_REAR_2OHM (0x00 << 6) +#define IMPEDANCE_OPTIMIZER_REAR_4OHM (0x01 << 6) +#define IMPEDANCE_OPTIMIZER_FRONT_2OHM (0x00 << 7) +#define IMPEDANCE_OPTIMIZER_FRONT_4OHM (0x01 << 7) + +#define TDA7803_REG2 (0x02) +#define LOW_BATTERY_MUTE_THRESHOLD_1 (0x00 << 0) +#define LOW_BATTERY_MUTE_THRESHOLD_2 (0x01 << 0) +#define DIGITAL_MUTE_ON (0x00 << 2) +#define DIGITAL_MUTE_OFF (0x01 << 2) +#define CH2_4_MUTE (0x00 << 3) +#define CH2_4_UMUTE (0x01 << 3) +#define CH1_3_MUTE (0x00 << 4) +#define CH1_3_UMUTE (0x01 << 4) +#define MUTE_TIME_SETTING_1_45MS (0x00 << 5) +#define MUTE_TIME_SETTING_5_8MS (0x01 << 5) +#define MUTE_TIME_SETTING_11_6MS (0x02 << 5) +#define MUTE_TIME_SETTING_23_2MS (0x03 << 5) +#define MUTE_TIME_SETTING_46_4MS (0x04 << 5) +#define MUTE_TIME_SETTING_92_8MS (0x05 << 5) +#define MUTE_TIME_SETTING_185_5MS (0x06 << 5) +#define MUTE_TIME_SETTING_371_1MS (0x07 << 5) + +#define TDA7803_REG3 (0x03) +#define HIGH_PASS_FILTER_DISABLE (0x00 << 0) +#define HIGH_PASS_FILTER_ENABLE (0x01 << 0) +#define INPUT_OFFSET_DETECTION_DIS (0x00 << 1) +#define INPUT_OFFSET_DETECTION_EN (0x01 << 1) +#define NOISE_GATING_FUNCTION_EN (0x00 << 2) +#define NOISE_GATING_FUNCTION_DIS (0x01 << 2) +#define INPUT_FORMAT_I2S_STD (0x00 << 3) +#define INPUT_FORMAT_TDM_4CH (0x01 << 3) +#define INPUT_FORMAT_TDM_8CH_MODEL1 (0x02 << 3) +#define INPUT_FORMAT_TDM_8CH_MODEL2 (0x03 << 3) +#define INPUT_FORMAT_TDM_16CH_MODEL1 (0x04 << 3) +#define INPUT_FORMAT_TDM_16CH_MODEL2 (0x05 << 3) +#define INPUT_FORMAT_TDM_16CH_MODEL3 (0x06 << 3) +#define INPUT_FORMAT_TDM_16CH_MODEL4 (0x07 << 3) +#define SAMPLE_FREQUENCY_RANGE_44100HZ (0x00 << 6) +#define SAMPLE_FREQUENCY_RANGE_48000HZ (0x01 << 6) +#define SAMPLE_FREQUENCY_RANGE_96000HZ (0x02 << 6) +#define SAMPLE_FREQUENCY_RANGE_192000HZ (0x03 << 6) + +#define TDA7803_REG4 (0x04) +#define DIAGNOSTIC_MODE_DISABLE (0x00 << 0) +#define DIAGNOSTIC_MODE_ENABLE (0x01 << 0) +#define CH2_4_SPEAKER_MODE (0x00 << 1) +#define CH2_4_LINE_DRIVER_MODE (0x01 << 1) +#define CH1_3_SPEAKER_MODE (0x00 << 2) +#define CH1_3_LINE_DRIVER_MODE (0x01 << 2) +#define DIAGNOSTIC_DISABLE (0X00 << 3) +#define DIAGNOSTIC_ENABLE (0X01 << 3) +#define DIAGNOSTIC_CURRENT_THRESHOLD_HIGH (0X00 << 4) +#define DIAGNOSTIC_CURRENT_THRESHOLD_LOW (0X01 << 4) +#define OFFSET_INFORMATION_YES (0X00 << 5) +#define OFFSET_INFORMATION_NO (0X01 << 5) +#define SHORT_FAULT_INFORMATION_YES (0X00 << 6) +#define SHORT_FAULT_INFORMATION_NO (0X01 << 6) + +#define TDA7803_REG5 (0x05) +#define CAPABILITY_ENHANCER_DISABLE (0x00 << 1) +#define CAPABILITY_ENHANCER_ENABLE (0x0F << 1) +#define THERMAL_THRESHOLD_DEFAULT (0x00 << 6) +#define THERMAL_THRESHOLD_TW_NEGATIVE_10 (0x01 << 6) +#define THERMAL_THRESHOLD_TW_NEGATIVE_20 (0x02 << 6) + +#define TDA7803_REG6 (0x06) +#define PARALLEL_MODE_CONFIG_MODE_1 (0x00 << 2) +#define PARALLEL_MODE_CONFIG_MODE_2 (0x01 << 2) +#define PARALLEL_MODE_CONFIG_MODE_3 (0x02 << 2) +#define PARALLEL_MODE_CONFIG_MODE_4 (0x03 << 2) +#define DIAGNOSITC_PULSE_STRETCH_MODE_1 (0x00 << 5) +#define DIAGNOSITC_PULSE_STRETCH_MODE_2 (0x01 << 5) +#define DIAGNOSITC_PULSE_STRETCH_MODE_3 (0x02 << 5) +#define DIAGNOSITC_PULSE_STRETCH_MODE_4 (0x03 << 5) +#define DIAGNOSITC_PULSE_STRETCH_MODE_5 (0x04 << 5) +#define DIAGNOSITC_PULSE_STRETCH_DEFAULT (0x05 << 5) + +#define TDA7803_REG7 (0x07) +#define AMPLIEFIR_SWITCH_OFF (0x00 << 0) +#define AMPLIEFIR_SWITCH_ON (0x01 << 0) +#define CLIPP_LEVEL_1_REAR_CHANNELS2_4 (0x00 << 1) +#define CLIPP_LEVEL_2_REAR_CHANNELS2_4 (0x01 << 1) +#define CLIPP_LEVEL_3_REAR_CHANNELS2_4 (0x02 << 1) +#define NOT_CLIPP_FOR_REAR_CHANNELS2_4 (0x03 << 1) +#define CLIPP_LEVEL_1_REAR_CHANNELS1_3 (0x00 << 3) +#define CLIPP_LEVEL_2_REAR_CHANNELS1_3 (0x01 << 3) +#define CLIPP_LEVEL_3_REAR_CHANNELS1_3 (0x02 << 3) +#define NOT_CLIPP_FOR_REAR_CHANNELS1_3 (0x03 << 3) +#define TEMPERATURE_WARNING_TW1 (0x00 << 5) +#define TEMPERATURE_WARNING_TW2 (0x01 << 5) +#define TEMPERATURE_WARNING_TW3 (0x02 << 5) +#define TEMPERATURE_WARNING_TW4 (0x03 << 5) +#define NOT_TEMPERATURE_WARNING (0x04 << 5) + +#define TDA7803_REGMAX (0x08) +#endif /* __TDA7803_H__ */