lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Thu, 20 Feb 2020 12:49:30 -0600
From:   Dan Murphy <dmurphy@...com>
To:     <lgirdwood@...il.com>, <broonie@...nel.org>, <perex@...ex.cz>,
        <tiwai@...e.com>
CC:     <alsa-devel@...a-project.org>, <linux-kernel@...r.kernel.org>,
        Dan Murphy <dmurphy@...com>
Subject: [PATCH v2] ASoC: tas2562: Add support for digital volume control

Add support for digital volume control.  There is no dedicated register
for volume control but instead there are 4.  The values of the registers
are determined with exponential floating point math.
So a table was created with register values for 2dB step increments
from -110dB to 0dB.

Signed-off-by: Dan Murphy <dmurphy@...com>
---

v2 - Fix init values to lower volume CFG4 is the LSB and CFG1 is MSB

 sound/soc/codecs/tas2562.c | 94 ++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/tas2562.h |  6 ++-
 2 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c
index b2682c2360b6..92e4bf34b35c 100644
--- a/sound/soc/codecs/tas2562.c
+++ b/sound/soc/codecs/tas2562.c
@@ -26,6 +26,24 @@
 #define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
 			 SNDRV_PCM_FORMAT_S32_LE)
 
+/* DVC equation involves floating point math
+ * round(10^(volume in dB/20)*2^30)
+ * so create a lookup table for 2dB step
+ */
+static const unsigned int float_vol_db_lookup[] = {
+0x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151,
+0x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b,
+0x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a,
+0x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f,
+0x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7,
+0x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d,
+0x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a,
+0x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27,
+0x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68,
+0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362,
+0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000
+};
+
 struct tas2562_data {
 	struct snd_soc_component *component;
 	struct gpio_desc *sdz_gpio;
@@ -34,6 +52,7 @@ struct tas2562_data {
 	struct i2c_client *client;
 	int v_sense_slot;
 	int i_sense_slot;
+	int volume_lvl;
 };
 
 static int tas2562_set_bias_level(struct snd_soc_component *component,
@@ -334,6 +353,22 @@ static int tas2562_codec_probe(struct snd_soc_component *component)
 	if (ret < 0)
 		return ret;
 
+	/* Set the Digital volume to -110dB */
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG4, 0x43);
+	if (ret)
+		return ret;
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG3, 0x0d);
+	if (ret)
+		return ret;
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG2, 0x00);
+	if (ret)
+		return ret;
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG1, 0x00);
+	if (ret)
+		return ret;
+
+	tas2562->volume_lvl = 0;
+
 	return 0;
 }
 
@@ -414,6 +449,50 @@ static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = tas2562->volume_lvl;
+	return 0;
+}
+
+static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
+	struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
+	int ret;
+	u32 reg_val;
+
+	reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2];
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
+				      (reg_val & 0xff));
+	if (ret)
+		return ret;
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
+				      ((reg_val >> 8) & 0xff));
+	if (ret)
+		return ret;
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG2,
+				      ((reg_val >> 16) & 0xff));
+	if (ret)
+		return ret;
+	ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
+				      ((reg_val >> 24) & 0xff));
+	if (ret)
+		return ret;
+
+	tas2562->volume_lvl = ucontrol->value.integer.value[0];
+
+	return ret;
+}
+
+/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */
+static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0);
+
 static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0);
 
 static const struct snd_kcontrol_new isense_switch =
@@ -427,6 +506,17 @@ static const struct snd_kcontrol_new vsense_switch =
 static const struct snd_kcontrol_new tas2562_snd_controls[] = {
 	SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 0, 0x1c, 0,
 		       tas2562_dac_tlv),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Digital Volume Control",
+		.index = 0,
+		.tlv.p = dvc_tlv,
+		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = snd_soc_info_volsw,
+		.get = tas2562_volume_control_get,
+		.put = tas2562_volume_control_put,
+		.private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0) ,
+	},
 };
 
 static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
@@ -517,6 +607,10 @@ static const struct reg_default tas2562_reg_defaults[] = {
 	{ TAS2562_PB_CFG1, 0x20 },
 	{ TAS2562_TDM_CFG0, 0x09 },
 	{ TAS2562_TDM_CFG1, 0x02 },
+	{ TAS2562_DVC_CFG1, 0x40 },
+	{ TAS2562_DVC_CFG2, 0x40 },
+	{ TAS2562_DVC_CFG3, 0x00 },
+	{ TAS2562_DVC_CFG4, 0x00 },
 };
 
 static const struct regmap_config tas2562_regmap_config = {
diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h
index 6f55ebcf19ea..28e75fc431d0 100644
--- a/sound/soc/codecs/tas2562.h
+++ b/sound/soc/codecs/tas2562.h
@@ -35,8 +35,10 @@
 #define TAS2562_REV_ID		TAS2562_REG(0, 0x7d)
 
 /* Page 2 */
-#define TAS2562_DVC_CFG1	TAS2562_REG(2, 0x01)
-#define TAS2562_DVC_CFG2	TAS2562_REG(2, 0x02)
+#define TAS2562_DVC_CFG1	TAS2562_REG(2, 0x0c)
+#define TAS2562_DVC_CFG2	TAS2562_REG(2, 0x0d)
+#define TAS2562_DVC_CFG3	TAS2562_REG(2, 0x0e)
+#define TAS2562_DVC_CFG4	TAS2562_REG(2, 0x0f)
 
 #define TAS2562_RESET	BIT(0)
 
-- 
2.25.0

Powered by blists - more mailing lists