Skip to content

Commit 7a737b8

Browse files
committed
ASoC: SDCA: add put/get callback for Q7.8 volume format
This patch adds the put/get callback for Q7.8 volume format. Signed-off-by: Shuming Fan <shumingf@realtek.com>
1 parent 0d02a9c commit 7a737b8

1 file changed

Lines changed: 148 additions & 25 deletions

File tree

sound/soc/sdca/sdca_asoc.c

Lines changed: 148 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ int sdca_asoc_populate_dapm(struct device *dev, struct sdca_function_data *funct
834834
}
835835
EXPORT_SYMBOL_NS(sdca_asoc_populate_dapm, "SND_SOC_SDCA");
836836

837+
#define SCALE_FACTOR BIT(8)
838+
837839
static int control_limit_kctl(struct device *dev,
838840
struct sdca_entity *entity,
839841
struct sdca_control *control,
@@ -843,7 +845,6 @@ static int control_limit_kctl(struct device *dev,
843845
struct sdca_control_range *range;
844846
int min, max, step;
845847
unsigned int *tlv;
846-
int shift;
847848

848849
if (control->type != SDCA_CTL_DATATYPE_Q7P8DB)
849850
return 0;
@@ -863,43 +864,160 @@ static int control_limit_kctl(struct device *dev,
863864
max = sign_extend32(max, control->nbits - 1);
864865

865866
/*
866-
* FIXME: Only support power of 2 step sizes as this can be supported
867-
* by a simple shift.
867+
* The SDCA volumes are in steps of 1/256th of a dB, so we need to
868+
* scale them to 1/100ths of a dB for the ALSA TLV.
869+
* The min and max values are in Q7.8 format, so we need to scale
870+
* them to 1/100ths of a dB.
868871
*/
869-
if (hweight32(step) != 1) {
870-
dev_err(dev, "%s: %s: currently unsupported step size\n",
871-
entity->label, control->label);
872-
return -EINVAL;
873-
}
874-
875-
/*
876-
* The SDCA volumes are in steps of 1/256th of a dB, a step down of
877-
* 64 (shift of 6) gives 1/4dB. 1/4dB is the smallest unit that is also
878-
* representable in the ALSA TLVs which are in 1/100ths of a dB.
879-
*/
880-
shift = max(ffs(step) - 1, 6);
872+
min = min * 100 / SCALE_FACTOR;
873+
max = max * 100 / SCALE_FACTOR;
874+
step = step * 100 / SCALE_FACTOR;
881875

882876
tlv = devm_kcalloc(dev, 4, sizeof(*tlv), GFP_KERNEL);
883877
if (!tlv)
884878
return -ENOMEM;
885879

886880
tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
887881
tlv[1] = 2 * sizeof(*tlv);
888-
tlv[2] = (min * 100) >> 8;
889-
tlv[3] = ((1 << shift) * 100) >> 8;
882+
tlv[2] = min;
883+
tlv[3] = step;
890884

891-
mc->min = min >> shift;
892-
mc->max = max >> shift;
893-
mc->shift = shift;
894-
mc->rshift = shift;
895-
mc->sign_bit = 15 - shift;
885+
mc->min = 0;
886+
mc->max = (max - min) / step;
896887

897888
kctl->tlv.p = tlv;
898889
kctl->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
899890

900891
return 0;
901892
}
902893

894+
// Convert Q7.8 to tlv value
895+
static int q78_to_tlv_val(int16_t q78)
896+
{
897+
return (int)((q78 * 100) / SCALE_FACTOR);
898+
}
899+
900+
static short tlv_value_to_q78(int value)
901+
{
902+
short value16;
903+
int tmp;
904+
// Clamp value to representable range
905+
if (value > 127996)
906+
value = 127996;
907+
else if (value < -128000)
908+
value = -128000;
909+
910+
tmp = value * SCALE_FACTOR;
911+
value16 = (short)(tmp / 1000);
912+
913+
return value16;
914+
}
915+
916+
static unsigned int soc_mixer_q78_to_ctl(struct soc_mixer_control *mc,
917+
struct snd_kcontrol *kcontrol, int val, int max)
918+
{
919+
int reg_val = 0;
920+
const unsigned int *tlv;
921+
int min, step;
922+
923+
if (mc->invert)
924+
val = max - val;
925+
926+
tlv = kcontrol->tlv.p;
927+
min = tlv[2];
928+
step = tlv[3];
929+
930+
reg_val = q78_to_tlv_val(val);
931+
reg_val = reg_val - min;
932+
reg_val = reg_val / step;
933+
934+
return reg_val;
935+
}
936+
937+
static unsigned int soc_mixer_ctl_to_q78(struct soc_mixer_control *mc,
938+
struct snd_kcontrol *kcontrol, int val, int max)
939+
{
940+
unsigned int reg_val = 0;
941+
const unsigned int *tlv;
942+
int min, step, dB;
943+
944+
if (mc->invert)
945+
val = max - val;
946+
947+
tlv = kcontrol->tlv.p;
948+
min = tlv[2];
949+
step = tlv[3];
950+
951+
dB = min + (step * val);
952+
reg_val = tlv_value_to_q78(dB * 10);
953+
954+
return reg_val;
955+
}
956+
957+
static int sdca_get_volsw(struct snd_kcontrol *kcontrol,
958+
struct snd_ctl_elem_value *ucontrol)
959+
{
960+
struct soc_mixer_control *mc =
961+
(struct soc_mixer_control *)kcontrol->private_value;
962+
int max = mc->max - mc->min;
963+
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
964+
unsigned int reg_val;
965+
int val;
966+
967+
reg_val = snd_soc_component_read(component, mc->reg);
968+
val = soc_mixer_q78_to_ctl(mc, kcontrol, reg_val, max);
969+
970+
ucontrol->value.integer.value[0] = val;
971+
972+
if (mc->reg == mc->rreg) {
973+
val = soc_mixer_q78_to_ctl(mc, kcontrol, reg_val, max);
974+
} else {
975+
reg_val = snd_soc_component_read(component, mc->rreg);
976+
val = soc_mixer_q78_to_ctl(mc, kcontrol, reg_val, max);
977+
}
978+
979+
ucontrol->value.integer.value[1] = val;
980+
return 0;
981+
}
982+
983+
static int sdca_put_volsw(struct snd_kcontrol *kcontrol,
984+
struct snd_ctl_elem_value *ucontrol)
985+
{
986+
struct soc_mixer_control *mc =
987+
(struct soc_mixer_control *)kcontrol->private_value;
988+
int max = mc->max - mc->min;
989+
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
990+
unsigned int val1, val_mask = 0xffff;
991+
unsigned int val2 = 0;
992+
bool double_r = false;
993+
int ret;
994+
995+
val1 = soc_mixer_ctl_to_q78(mc, kcontrol, ucontrol->value.integer.value[0], max);
996+
997+
if (mc->reg == mc->rreg) {
998+
val1 |= soc_mixer_ctl_to_q78(mc, kcontrol,
999+
ucontrol->value.integer.value[1], max);
1000+
} else {
1001+
val2 = soc_mixer_ctl_to_q78(mc, kcontrol,
1002+
ucontrol->value.integer.value[1], max);
1003+
double_r = true;
1004+
}
1005+
1006+
ret = snd_soc_component_update_bits(component, mc->reg, val_mask, val1);
1007+
if (ret < 0)
1008+
return ret;
1009+
1010+
if (double_r) {
1011+
int err = snd_soc_component_update_bits(component, mc->rreg,
1012+
val_mask, val2);
1013+
/* Don't drop change flag */
1014+
if (err)
1015+
return err;
1016+
}
1017+
1018+
return ret;
1019+
}
1020+
9031021
static int populate_control(struct device *dev,
9041022
struct sdca_function_data *function,
9051023
struct sdca_entity *entity,
@@ -924,7 +1042,7 @@ static int populate_control(struct device *dev,
9241042
if (!control_name)
9251043
return -ENOMEM;
9261044

927-
mc = devm_kmalloc(dev, sizeof(*mc), GFP_KERNEL);
1045+
mc = devm_kzalloc(dev, sizeof(*mc), GFP_KERNEL);
9281046
if (!mc)
9291047
return -ENOMEM;
9301048

@@ -954,8 +1072,13 @@ static int populate_control(struct device *dev,
9541072
(*kctl)->private_value = (unsigned long)mc;
9551073
(*kctl)->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
9561074
(*kctl)->info = snd_soc_info_volsw;
957-
(*kctl)->get = snd_soc_get_volsw;
958-
(*kctl)->put = snd_soc_put_volsw;
1075+
if (strstr(control_name, "Volume")) {
1076+
(*kctl)->get = sdca_get_volsw;
1077+
(*kctl)->put = sdca_put_volsw;
1078+
} else {
1079+
(*kctl)->get = snd_soc_get_volsw;
1080+
(*kctl)->put = snd_soc_put_volsw;
1081+
}
9591082

9601083
if (readonly_control(control))
9611084
(*kctl)->access = SNDRV_CTL_ELEM_ACCESS_READ;

0 commit comments

Comments
 (0)