diff options
| -rw-r--r-- | sound/soc/codecs/aw88261.c | 42 | ||||
| -rw-r--r-- | sound/soc/codecs/aw88261.h | 4 |
2 files changed, 23 insertions, 23 deletions
diff --git a/sound/soc/codecs/aw88261.c b/sound/soc/codecs/aw88261.c index bc37067bef96..b14ca4163043 100644 --- a/sound/soc/codecs/aw88261.c +++ b/sound/soc/codecs/aw88261.c @@ -15,6 +15,7 @@ #include <linux/regulator/consumer.h> #include <sound/soc.h> #include <sound/pcm_params.h> +#include <sound/tlv.h> #include "aw88261.h" #include "aw88395/aw88395_data_type.h" #include "aw88395/aw88395_device.h" @@ -29,20 +30,10 @@ static const struct regmap_config aw88261_remap_config = { static void aw88261_dev_set_volume(struct aw_device *aw_dev, unsigned int value) { - struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; - unsigned int real_value, volume; - unsigned int reg_value; - - volume = min((value + vol_desc->init_volume), (unsigned int)AW88261_MUTE_VOL); - real_value = DB_TO_REG_VAL(volume); - - regmap_read(aw_dev->regmap, AW88261_SYSCTRL2_REG, ®_value); - - real_value = (real_value | (reg_value & AW88261_VOL_START_MASK)); + unsigned int volume = min(value, (unsigned int)AW88261_MUTE_VOL); - dev_dbg(aw_dev->dev, "value 0x%x , real_value:0x%x", value, real_value); - - regmap_write(aw_dev->regmap, AW88261_SYSCTRL2_REG, real_value); + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL2_REG, + ~AW88261_VOL_MASK, DB_TO_REG_VAL(volume)); } static void aw88261_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) @@ -994,7 +985,8 @@ static int aw88261_volume_get(struct snd_kcontrol *kcontrol, struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; - ucontrol->value.integer.value[0] = vol_desc->ctl_volume; + ucontrol->value.integer.value[0] = + (AW88261_MUTE_VOL - vol_desc->ctl_volume) / 2; return 0; } @@ -1007,13 +999,13 @@ static int aw88261_volume_set(struct snd_kcontrol *kcontrol, struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int value; - - value = ucontrol->value.integer.value[0]; + int value = ucontrol->value.integer.value[0]; if (value < mc->min || value > mc->max) return -EINVAL; + value = AW88261_MUTE_VOL - (value * 2); + if (vol_desc->ctl_volume != value) { vol_desc->ctl_volume = value; aw88261_dev_set_volume(aw88261->aw_pa, vol_desc->ctl_volume); @@ -1024,10 +1016,18 @@ static int aw88261_volume_set(struct snd_kcontrol *kcontrol, return 0; } +/* + * The field contains 4 bits in units of 6dB + 6 bits in units of 0.125dB + * which is too precise for TLV (!) so we have to multiply the scale by 2. + * + * The range is clamped at -90dB to prevent overflowing the 4-bit part. + */ +static const DECLARE_TLV_DB_SCALE(volume_tlv, -9000, 25, 0); + static const struct snd_kcontrol_new aw88261_controls[] = { - SOC_SINGLE_EXT("PCM Playback Volume", AW88261_SYSCTRL2_REG, - 6, AW88261_MUTE_VOL, 0, aw88261_volume_get, - aw88261_volume_set), + SOC_SINGLE_EXT_TLV("PCM Playback Volume", AW88261_SYSCTRL2_REG, + 6, AW88261_CTL_MAX_VOL, 1, + aw88261_volume_get, aw88261_volume_set, volume_tlv), AW88261_PROFILE_EXT("Profile Set", aw88261_profile_info, aw88261_profile_get, aw88261_profile_set), }; @@ -1278,7 +1278,7 @@ static int aw88261_init(struct aw88261 *aw88261, struct i2c_client *i2c, struct aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; aw_dev->channel = 0; aw_dev->fw_status = AW88261_DEV_FW_FAILED; - aw_dev->volume_desc.ctl_volume = AW88261_VOL_DEFAULT_VALUE; + aw_dev->volume_desc.ctl_volume = AW88261_CTL_DEFAULT_VOL; aw_dev->volume_desc.mute_volume = AW88261_MUTE_VOL; aw88261_parse_channel_dt(aw88261); diff --git a/sound/soc/codecs/aw88261.h b/sound/soc/codecs/aw88261.h index 4be6ac02123e..270ccf375f36 100644 --- a/sound/soc/codecs/aw88261.h +++ b/sound/soc/codecs/aw88261.h @@ -262,7 +262,8 @@ #define AW88261_VOL_MASK \ (~(((1<<AW88261_VOL_BITS_LEN)-1) << AW88261_VOL_START_BIT)) -#define AW88261_VOL_DEFAULT_VALUE (0) +#define AW88261_CTL_MAX_VOL (AW88261_MUTE_VOL / 2) +#define AW88261_CTL_DEFAULT_VOL (AW88261_CTL_MAX_VOL / 2) #define AW88261_I2STXEN_START_BIT (6) #define AW88261_I2STXEN_BITS_LEN (1) @@ -538,7 +539,6 @@ #define AW88261_DEV_SYSST_CHECK_MAX (10) #define AW88261_SOFT_RESET_VALUE (0x55aa) #define AW88261_REG_TO_DB (0x3f) -#define AW88261_VOL_START_MASK (0xfc00) #define AW88261_INIT_PROFILE (0) #define REG_VAL_TO_DB(value) ((((value) >> AW88261_VOL_6DB_START) * \ |
