Skip to content

Commit 4897262

Browse files
committed
ASoC: SDCA: support Q7.8 volume format
The SDCA specification uses Q7.8 volume format. This patch adds a field to indicate whether it is SDCA volume control and supports the volume settings. Signed-off-by: Shuming Fan <shumingf@realtek.com>
1 parent b250b54 commit 4897262

3 files changed

Lines changed: 33 additions & 31 deletions

File tree

include/sound/soc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
555555
struct snd_ctl_elem_value *ucontrol);
556556
int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
557557
struct snd_ctl_elem_value *ucontrol);
558+
558559
#define snd_soc_get_volsw_2r snd_soc_get_volsw
559560
#define snd_soc_put_volsw_2r snd_soc_put_volsw
560561
int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
@@ -1225,6 +1226,7 @@ struct soc_mixer_control {
12251226
unsigned int sign_bit;
12261227
unsigned int invert:1;
12271228
unsigned int autodisable:1;
1229+
unsigned int sdca_vol_q7p8:1;
12281230
#ifdef CONFIG_SND_SOC_TOPOLOGY
12291231
struct snd_soc_dobj dobj;
12301232
#endif

sound/soc/sdca/sdca_asoc.c

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,6 @@ static int control_limit_kctl(struct device *dev,
795795
struct sdca_control_range *range;
796796
int min, max, step;
797797
unsigned int *tlv;
798-
int shift;
799798

800799
if (control->type != SDCA_CTL_DATATYPE_Q7P8DB)
801800
return 0;
@@ -814,37 +813,23 @@ static int control_limit_kctl(struct device *dev,
814813
min = sign_extend32(min, control->nbits - 1);
815814
max = sign_extend32(max, control->nbits - 1);
816815

817-
/*
818-
* FIXME: Only support power of 2 step sizes as this can be supported
819-
* by a simple shift.
820-
*/
821-
if (hweight32(step) != 1) {
822-
dev_err(dev, "%s: %s: currently unsupported step size\n",
823-
entity->label, control->label);
824-
return -EINVAL;
825-
}
826-
827-
/*
828-
* The SDCA volumes are in steps of 1/256th of a dB, a step down of
829-
* 64 (shift of 6) gives 1/4dB. 1/4dB is the smallest unit that is also
830-
* representable in the ALSA TLVs which are in 1/100ths of a dB.
831-
*/
832-
shift = max(ffs(step) - 1, 6);
833-
834816
tlv = devm_kcalloc(dev, 4, sizeof(*tlv), GFP_KERNEL);
835817
if (!tlv)
836818
return -ENOMEM;
837819

838-
tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
820+
tlv[0] = SNDRV_CTL_TLVT_DB_MINMAX;
839821
tlv[1] = 2 * sizeof(*tlv);
840822
tlv[2] = (min * 100) >> 8;
841-
tlv[3] = ((1 << shift) * 100) >> 8;
823+
tlv[3] = (max * 100) >> 8;
824+
825+
step = (step * 100) >> 8;
842826

843-
mc->min = min >> shift;
844-
mc->max = max >> shift;
845-
mc->shift = shift;
846-
mc->rshift = shift;
847-
mc->sign_bit = 15 - shift;
827+
mc->min = ((int)tlv[2] / step);
828+
mc->max = ((int)tlv[3] / step);
829+
mc->shift = step;
830+
mc->rshift = step;
831+
mc->sign_bit = 15;
832+
mc->sdca_vol_q7p8 = 1;
848833

849834
kctl->tlv.p = tlv;
850835
kctl->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;

sound/soc/soc-ops.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,19 @@ EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
113113
static int soc_mixer_reg_to_ctl(struct soc_mixer_control *mc, unsigned int reg_val,
114114
unsigned int mask, unsigned int shift, int max)
115115
{
116-
int val = (reg_val >> shift) & mask;
116+
int val = reg_val;
117+
118+
if (!mc->sdca_vol_q7p8)
119+
val = (reg_val >> shift) & mask;
117120

118121
if (mc->sign_bit)
119122
val = sign_extend32(val, mc->sign_bit);
120123

121124
val = clamp(val, mc->min, mc->max);
125+
126+
if (mc->sdca_vol_q7p8)
127+
val = (((val * 100) >> 8) / (int)shift);
128+
122129
val -= mc->min;
123130

124131
if (mc->invert)
@@ -131,14 +138,19 @@ static unsigned int soc_mixer_ctl_to_reg(struct soc_mixer_control *mc, int val,
131138
unsigned int mask, unsigned int shift,
132139
int max)
133140
{
134-
unsigned int reg_val;
141+
unsigned int reg_val, ret_val;
135142

136143
if (mc->invert)
137144
val = max - val;
138145

139146
reg_val = val + mc->min;
140147

141-
return (reg_val & mask) << shift;
148+
if (mc->sdca_vol_q7p8)
149+
ret_val = (((int)(((int)reg_val * shift) << 8)) / 100);
150+
else
151+
ret_val = (reg_val & mask) << shift;
152+
153+
return ret_val;
142154
}
143155

144156
static int soc_mixer_valid_ctl(struct soc_mixer_control *mc, long val, int max)
@@ -198,7 +210,7 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
198210
struct soc_mixer_control *mc, int mask, int max)
199211
{
200212
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
201-
unsigned int val1, val_mask;
213+
unsigned int val1, val_mask = mask;
202214
unsigned int val2 = 0;
203215
bool double_r = false;
204216
int ret;
@@ -209,7 +221,9 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
209221

210222
val1 = soc_mixer_ctl_to_reg(mc, ucontrol->value.integer.value[0],
211223
mask, mc->shift, max);
212-
val_mask = mask << mc->shift;
224+
225+
if (!mc->sdca_vol_q7p8)
226+
val_mask = mask << mc->shift;
213227

214228
if (snd_soc_volsw_is_stereo(mc)) {
215229
ret = soc_mixer_valid_ctl(mc, ucontrol->value.integer.value[1], max);
@@ -220,7 +234,8 @@ static int soc_put_volsw(struct snd_kcontrol *kcontrol,
220234
val1 |= soc_mixer_ctl_to_reg(mc,
221235
ucontrol->value.integer.value[1],
222236
mask, mc->rshift, max);
223-
val_mask |= mask << mc->rshift;
237+
if (!mc->sdca_vol_q7p8)
238+
val_mask |= mask << mc->rshift;
224239
} else {
225240
val2 = soc_mixer_ctl_to_reg(mc,
226241
ucontrol->value.integer.value[1],

0 commit comments

Comments
 (0)