diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/tas2562.c | 78 | ||||
-rw-r--r-- | sound/soc/codecs/tas2562.h | 6 |
2 files changed, 82 insertions, 2 deletions
diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index b517ada7e809..561ac0ac0795 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, @@ -413,6 +432,50 @@ end: 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 = @@ -426,6 +489,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[] = { @@ -516,6 +590,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) |