ASoC: codecs: tas5720: add support for TAS5720A-Q1 (automotive) variant
This change adds support the TAS5720A-Q1 audio codec, in the same driver as tas5720. Functionally, this driver is pretty similar to it's TAS5720x variant. The first 3 registers are the same, so the main control and device identification can happen with these registers. The next registers differ. This variant offers control (in the registers) for 2 speakers, which is implemented here (in a basic manner). Signed-off-by: Steffen Aschbacher <steffen.aschbacher@stihl.de> Signed-off-by: Alexandru Ardelean <alex@shruggie.ro> Link: https://lore.kernel.org/r/20230128082744.41849-2-alex@shruggie.ro Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
879142be61
Коммит
c24a62be09
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
enum tas572x_type {
|
enum tas572x_type {
|
||||||
TAS5720,
|
TAS5720,
|
||||||
|
TAS5720A_Q1,
|
||||||
TAS5722,
|
TAS5722,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,17 +167,26 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable manual TDM slot selection (instead of I2C ID based) */
|
/*
|
||||||
ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG,
|
* Enable manual TDM slot selection (instead of I2C ID based).
|
||||||
TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC);
|
* This is not applicable to TAS5720A-Q1.
|
||||||
if (ret < 0)
|
*/
|
||||||
goto error_snd_soc_component_update_bits;
|
switch (tas5720->devtype) {
|
||||||
|
case TAS5720A_Q1:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG,
|
||||||
|
TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error_snd_soc_component_update_bits;
|
||||||
|
|
||||||
/* Configure the TDM slot to process audio from */
|
/* Configure the TDM slot to process audio from */
|
||||||
ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
|
ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
|
||||||
TAS5720_TDM_SLOT_SEL_MASK, first_slot);
|
TAS5720_TDM_SLOT_SEL_MASK, first_slot);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_snd_soc_component_update_bits;
|
goto error_snd_soc_component_update_bits;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure TDM slot width. This is only applicable to TAS5722. */
|
/* Configure TDM slot width. This is only applicable to TAS5722. */
|
||||||
switch (tas5720->devtype) {
|
switch (tas5720->devtype) {
|
||||||
|
@ -201,10 +211,22 @@ error_snd_soc_component_update_bits:
|
||||||
|
|
||||||
static int tas5720_mute_soc_component(struct snd_soc_component *component, int mute)
|
static int tas5720_mute_soc_component(struct snd_soc_component *component, int mute)
|
||||||
{
|
{
|
||||||
|
struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component);
|
||||||
|
unsigned int reg, mask;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG,
|
switch (tas5720->devtype) {
|
||||||
TAS5720_MUTE, mute ? TAS5720_MUTE : 0);
|
case TAS5720A_Q1:
|
||||||
|
reg = TAS5720_Q1_VOLUME_CTRL_CFG_REG;
|
||||||
|
mask = TAS5720_Q1_MUTE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reg = TAS5720_DIGITAL_CTRL2_REG;
|
||||||
|
mask = TAS5720_MUTE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snd_soc_component_update_bits(component, reg, mask, mute ? mask : 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(component->dev, "error (un-)muting device: %d\n", ret);
|
dev_err(component->dev, "error (un-)muting device: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -309,6 +331,9 @@ static int tas5720_codec_probe(struct snd_soc_component *component)
|
||||||
case TAS5720:
|
case TAS5720:
|
||||||
expected_device_id = TAS5720_DEVICE_ID;
|
expected_device_id = TAS5720_DEVICE_ID;
|
||||||
break;
|
break;
|
||||||
|
case TAS5720A_Q1:
|
||||||
|
expected_device_id = TAS5720A_Q1_DEVICE_ID;
|
||||||
|
break;
|
||||||
case TAS5722:
|
case TAS5722:
|
||||||
expected_device_id = TAS5722_DEVICE_ID;
|
expected_device_id = TAS5722_DEVICE_ID;
|
||||||
break;
|
break;
|
||||||
|
@ -474,6 +499,15 @@ static const struct regmap_config tas5720_regmap_config = {
|
||||||
.volatile_reg = tas5720_is_volatile_reg,
|
.volatile_reg = tas5720_is_volatile_reg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config tas5720a_q1_regmap_config = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
|
||||||
|
.max_register = TAS5720_MAX_REG,
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
.volatile_reg = tas5720_is_volatile_reg,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_config tas5722_regmap_config = {
|
static const struct regmap_config tas5722_regmap_config = {
|
||||||
.reg_bits = 8,
|
.reg_bits = 8,
|
||||||
.val_bits = 8,
|
.val_bits = 8,
|
||||||
|
@ -494,6 +528,16 @@ static const DECLARE_TLV_DB_RANGE(dac_analog_tlv,
|
||||||
0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0),
|
0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DAC analog gain for TAS5720A-Q1. There are three discrete values to select from, ranging
|
||||||
|
* from 19.2 dB to 25.0dB.
|
||||||
|
*/
|
||||||
|
static const DECLARE_TLV_DB_RANGE(dac_analog_tlv_a_q1,
|
||||||
|
0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0),
|
||||||
|
0x1, 0x1, TLV_DB_SCALE_ITEM(2260, 0, 0),
|
||||||
|
0x2, 0x2, TLV_DB_SCALE_ITEM(2500, 0, 0),
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps
|
* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps
|
||||||
* depending on the device. Note that setting the gain below -100 dB
|
* depending on the device. Note that setting the gain below -100 dB
|
||||||
|
@ -540,6 +584,15 @@ static const struct snd_kcontrol_new tas5720_snd_controls[] = {
|
||||||
TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv),
|
TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_kcontrol_new tas5720a_q1_snd_controls[] = {
|
||||||
|
SOC_DOUBLE_R_TLV("Speaker Driver Playback Volume",
|
||||||
|
TAS5720_Q1_VOLUME_CTRL_LEFT_REG,
|
||||||
|
TAS5720_Q1_VOLUME_CTRL_RIGHT_REG,
|
||||||
|
0, 0xff, 0, tas5720_dac_tlv),
|
||||||
|
SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG,
|
||||||
|
TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv_a_q1),
|
||||||
|
};
|
||||||
|
|
||||||
static const struct snd_kcontrol_new tas5722_snd_controls[] = {
|
static const struct snd_kcontrol_new tas5722_snd_controls[] = {
|
||||||
SOC_SINGLE_EXT_TLV("Speaker Driver Playback Volume",
|
SOC_SINGLE_EXT_TLV("Speaker Driver Playback Volume",
|
||||||
0, 0, 511, 0,
|
0, 0, 511, 0,
|
||||||
|
@ -577,6 +630,22 @@ static const struct snd_soc_component_driver soc_component_dev_tas5720 = {
|
||||||
.endianness = 1,
|
.endianness = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct snd_soc_component_driver soc_component_dev_tas5720_a_q1 = {
|
||||||
|
.probe = tas5720_codec_probe,
|
||||||
|
.remove = tas5720_codec_remove,
|
||||||
|
.suspend = tas5720_suspend,
|
||||||
|
.resume = tas5720_resume,
|
||||||
|
.controls = tas5720a_q1_snd_controls,
|
||||||
|
.num_controls = ARRAY_SIZE(tas5720a_q1_snd_controls),
|
||||||
|
.dapm_widgets = tas5720_dapm_widgets,
|
||||||
|
.num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets),
|
||||||
|
.dapm_routes = tas5720_audio_map,
|
||||||
|
.num_dapm_routes = ARRAY_SIZE(tas5720_audio_map),
|
||||||
|
.idle_bias_on = 1,
|
||||||
|
.use_pmdown_time = 1,
|
||||||
|
.endianness = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct snd_soc_component_driver soc_component_dev_tas5722 = {
|
static const struct snd_soc_component_driver soc_component_dev_tas5722 = {
|
||||||
.probe = tas5720_codec_probe,
|
.probe = tas5720_codec_probe,
|
||||||
.remove = tas5720_codec_remove,
|
.remove = tas5720_codec_remove,
|
||||||
|
@ -636,6 +705,7 @@ static struct snd_soc_dai_driver tas5720_dai[] = {
|
||||||
|
|
||||||
static const struct i2c_device_id tas5720_id[] = {
|
static const struct i2c_device_id tas5720_id[] = {
|
||||||
{ "tas5720", TAS5720 },
|
{ "tas5720", TAS5720 },
|
||||||
|
{ "tas5720a-q1", TAS5720A_Q1 },
|
||||||
{ "tas5722", TAS5722 },
|
{ "tas5722", TAS5722 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
@ -662,6 +732,9 @@ static int tas5720_probe(struct i2c_client *client)
|
||||||
case TAS5720:
|
case TAS5720:
|
||||||
regmap_config = &tas5720_regmap_config;
|
regmap_config = &tas5720_regmap_config;
|
||||||
break;
|
break;
|
||||||
|
case TAS5720A_Q1:
|
||||||
|
regmap_config = &tas5720a_q1_regmap_config;
|
||||||
|
break;
|
||||||
case TAS5722:
|
case TAS5722:
|
||||||
regmap_config = &tas5722_regmap_config;
|
regmap_config = &tas5722_regmap_config;
|
||||||
break;
|
break;
|
||||||
|
@ -695,6 +768,12 @@ static int tas5720_probe(struct i2c_client *client)
|
||||||
tas5720_dai,
|
tas5720_dai,
|
||||||
ARRAY_SIZE(tas5720_dai));
|
ARRAY_SIZE(tas5720_dai));
|
||||||
break;
|
break;
|
||||||
|
case TAS5720A_Q1:
|
||||||
|
ret = devm_snd_soc_register_component(&client->dev,
|
||||||
|
&soc_component_dev_tas5720_a_q1,
|
||||||
|
tas5720_dai,
|
||||||
|
ARRAY_SIZE(tas5720_dai));
|
||||||
|
break;
|
||||||
case TAS5722:
|
case TAS5722:
|
||||||
ret = devm_snd_soc_register_component(&client->dev,
|
ret = devm_snd_soc_register_component(&client->dev,
|
||||||
&soc_component_dev_tas5722,
|
&soc_component_dev_tas5722,
|
||||||
|
@ -716,6 +795,7 @@ static int tas5720_probe(struct i2c_client *client)
|
||||||
#if IS_ENABLED(CONFIG_OF)
|
#if IS_ENABLED(CONFIG_OF)
|
||||||
static const struct of_device_id tas5720_of_match[] = {
|
static const struct of_device_id tas5720_of_match[] = {
|
||||||
{ .compatible = "ti,tas5720", },
|
{ .compatible = "ti,tas5720", },
|
||||||
|
{ .compatible = "ti,tas5720a-q1", },
|
||||||
{ .compatible = "ti,tas5722", },
|
{ .compatible = "ti,tas5722", },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#ifndef __TAS5720_H__
|
#ifndef __TAS5720_H__
|
||||||
#define __TAS5720_H__
|
#define __TAS5720_H__
|
||||||
|
|
||||||
/* Register Address Map */
|
/* Register Address Map - first 3 regs are common for all variants */
|
||||||
#define TAS5720_DEVICE_ID_REG 0x00
|
#define TAS5720_DEVICE_ID_REG 0x00
|
||||||
#define TAS5720_POWER_CTRL_REG 0x01
|
#define TAS5720_POWER_CTRL_REG 0x01
|
||||||
#define TAS5720_DIGITAL_CTRL1_REG 0x02
|
#define TAS5720_DIGITAL_CTRL1_REG 0x02
|
||||||
|
@ -27,7 +27,13 @@
|
||||||
#define TAS5722_ANALOG_CTRL2_REG 0x14
|
#define TAS5722_ANALOG_CTRL2_REG 0x14
|
||||||
#define TAS5722_MAX_REG TAS5722_ANALOG_CTRL2_REG
|
#define TAS5722_MAX_REG TAS5722_ANALOG_CTRL2_REG
|
||||||
|
|
||||||
|
/* Register Address Map - volume controls for the TAS5720-Q1 variant */
|
||||||
|
#define TAS5720_Q1_VOLUME_CTRL_CFG_REG 0x03
|
||||||
|
#define TAS5720_Q1_VOLUME_CTRL_LEFT_REG 0x04
|
||||||
|
#define TAS5720_Q1_VOLUME_CTRL_RIGHT_REG 0x05
|
||||||
|
|
||||||
/* TAS5720_DEVICE_ID_REG */
|
/* TAS5720_DEVICE_ID_REG */
|
||||||
|
#define TAS5720A_Q1_DEVICE_ID 0x00
|
||||||
#define TAS5720_DEVICE_ID 0x01
|
#define TAS5720_DEVICE_ID 0x01
|
||||||
#define TAS5722_DEVICE_ID 0x12
|
#define TAS5722_DEVICE_ID 0x12
|
||||||
|
|
||||||
|
@ -53,6 +59,10 @@
|
||||||
#define TAS5720_MUTE BIT(4)
|
#define TAS5720_MUTE BIT(4)
|
||||||
#define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0)
|
#define TAS5720_TDM_SLOT_SEL_MASK GENMASK(2, 0)
|
||||||
|
|
||||||
|
/* TAS5720_Q1_VOLUME_CTRL_CFG_REG */
|
||||||
|
#define TAS5720_Q1_FADE BIT(7)
|
||||||
|
#define TAS5720_Q1_MUTE GENMASK(1, 0)
|
||||||
|
|
||||||
/* TAS5720_ANALOG_CTRL_REG */
|
/* TAS5720_ANALOG_CTRL_REG */
|
||||||
#define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4)
|
#define TAS5720_PWM_RATE_6_3_FSYNC (0x0 << 4)
|
||||||
#define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4)
|
#define TAS5720_PWM_RATE_8_4_FSYNC (0x1 << 4)
|
||||||
|
@ -70,6 +80,9 @@
|
||||||
#define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2)
|
#define TAS5720_ANALOG_GAIN_MASK GENMASK(3, 2)
|
||||||
#define TAS5720_ANALOG_GAIN_SHIFT (0x2)
|
#define TAS5720_ANALOG_GAIN_SHIFT (0x2)
|
||||||
|
|
||||||
|
/* TAS5720_Q1_ANALOG_CTRL_REG */
|
||||||
|
#define TAS5720_Q1_CHAN_SEL BIT(1)
|
||||||
|
|
||||||
/* TAS5720_FAULT_REG */
|
/* TAS5720_FAULT_REG */
|
||||||
#define TAS5720_OC_THRESH_100PCT (0x0 << 4)
|
#define TAS5720_OC_THRESH_100PCT (0x0 << 4)
|
||||||
#define TAS5720_OC_THRESH_75PCT (0x1 << 4)
|
#define TAS5720_OC_THRESH_75PCT (0x1 << 4)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче