Skip to content

Commit c3ca24e

Browse files
charleskeepaxbroonie
authored andcommitted
ASoC: SDCA: Create ALSA controls from DisCo
Use the previously parsed DisCo information from ACPI to create the ALSA controls required by an SDCA Function. This maps all User and Application level SDCA Controls to ALSA controls. Typically controls marked with those access levels are just volumes and mutes. SDCA defines volume controls as an integer in 1/256ths of a dB and then provides a mechanism to specify what values are valid (range templates). Currently only a simple case of a single linear volume range with a power of 2 step size is supported. This allows the code to expose the volume control using a simple shift. This will need expanded in the future, to support more complex ranges and probably also some additional control types but this should be sufficient to for a first pass. For non-dataport terminal widgets also add a pin switch to allow that endpoint to be turned on/off. Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> Link: https://patch.msgid.link/20250516131011.221310-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 2c8b3a8 commit c3ca24e

File tree

3 files changed

+267
-5
lines changed

3 files changed

+267
-5
lines changed

include/sound/sdca_asoc.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@
1212

1313
struct device;
1414
struct sdca_function_data;
15+
struct snd_kcontrol_new;
1516
struct snd_soc_component_driver;
1617
struct snd_soc_dapm_route;
1718
struct snd_soc_dapm_widget;
1819

1920
int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *function,
20-
int *num_widgets, int *num_routes);
21+
int *num_widgets, int *num_routes, int *num_controls);
2122

2223
int sdca_asoc_populate_dapm(struct device *dev, struct sdca_function_data *function,
2324
struct snd_soc_dapm_widget *widgets,
2425
struct snd_soc_dapm_route *routes);
26+
int sdca_asoc_populate_controls(struct device *dev,
27+
struct sdca_function_data *function,
28+
struct snd_kcontrol_new *kctl);
2529

2630
int sdca_asoc_populate_component(struct device *dev,
2731
struct sdca_function_data *function,

include/sound/sdca_function.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ enum sdca_fu_controls {
206206
SDCA_CTL_FU_LATENCY = 0x10,
207207
};
208208

209+
/**
210+
* enum sdca_volume_range - Column definitions for Q7.8dB volumes/gains
211+
*/
212+
enum sdca_volume_range {
213+
SDCA_VOLUME_LINEAR_MIN = 0,
214+
SDCA_VOLUME_LINEAR_MAX = 1,
215+
SDCA_VOLUME_LINEAR_STEP = 2,
216+
SDCA_VOLUME_LINEAR_NCOLS = 3,
217+
};
218+
209219
/**
210220
* enum sdca_xu_controls - SDCA Controls for Extension Unit
211221
*

sound/soc/sdca/sdca_asoc.c

Lines changed: 252 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#include <linux/delay.h>
1212
#include <linux/dev_printk.h>
1313
#include <linux/device.h>
14+
#include <linux/minmax.h>
1415
#include <linux/module.h>
16+
#include <linux/overflow.h>
1517
#include <linux/soundwire/sdw_registers.h>
1618
#include <linux/string_helpers.h>
1719
#include <sound/control.h>
@@ -21,6 +23,7 @@
2123
#include <sound/soc.h>
2224
#include <sound/soc-component.h>
2325
#include <sound/soc-dapm.h>
26+
#include <sound/tlv.h>
2427

2528
static struct sdca_control *selector_find_control(struct device *dev,
2629
struct sdca_entity *entity,
@@ -69,13 +72,33 @@ static struct sdca_control_range *selector_find_range(struct device *dev,
6972
return control_find_range(dev, entity, control, cols, rows);
7073
}
7174

75+
static bool exported_control(struct sdca_entity *entity, struct sdca_control *control)
76+
{
77+
switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
78+
case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
79+
return true;
80+
default:
81+
break;
82+
}
83+
84+
return control->layers & (SDCA_ACCESS_LAYER_USER |
85+
SDCA_ACCESS_LAYER_APPLICATION);
86+
}
87+
88+
static bool readonly_control(struct sdca_control *control)
89+
{
90+
return control->has_fixed || control->mode == SDCA_ACCESS_MODE_RO;
91+
}
92+
7293
/**
7394
* sdca_asoc_count_component - count the various component parts
7495
* @function: Pointer to the Function information.
7596
* @num_widgets: Output integer pointer, will be filled with the
7697
* required number of DAPM widgets for the Function.
7798
* @num_routes: Output integer pointer, will be filled with the
7899
* required number of DAPM routes for the Function.
100+
* @num_controls: Output integer pointer, will be filled with the
101+
* required number of ALSA controls for the Function.
79102
*
80103
* This function counts various things within the SDCA Function such
81104
* that the calling driver can allocate appropriate space before
@@ -84,12 +107,13 @@ static struct sdca_control_range *selector_find_range(struct device *dev,
84107
* Return: Returns zero on success, and a negative error code on failure.
85108
*/
86109
int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *function,
87-
int *num_widgets, int *num_routes)
110+
int *num_widgets, int *num_routes, int *num_controls)
88111
{
89-
int i;
112+
int i, j;
90113

91114
*num_widgets = function->num_entities - 1;
92115
*num_routes = 0;
116+
*num_controls = 0;
93117

94118
for (i = 0; i < function->num_entities - 1; i++) {
95119
struct sdca_entity *entity = &function->entities[i];
@@ -100,6 +124,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
100124
case SDCA_ENTITY_TYPE_OT:
101125
*num_routes += !!entity->iot.clock;
102126
*num_routes += !!entity->iot.is_dataport;
127+
*num_controls += !entity->iot.is_dataport;
103128
break;
104129
case SDCA_ENTITY_TYPE_PDE:
105130
*num_routes += entity->pde.num_managed;
@@ -113,6 +138,11 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
113138

114139
/* Add primary entity connections from DisCo */
115140
*num_routes += entity->num_sources;
141+
142+
for (j = 0; j < entity->num_controls; j++) {
143+
if (exported_control(entity, &entity->controls[j]))
144+
(*num_controls)++;
145+
}
116146
}
117147

118148
return 0;
@@ -797,6 +827,212 @@ int sdca_asoc_populate_dapm(struct device *dev, struct sdca_function_data *funct
797827
}
798828
EXPORT_SYMBOL_NS(sdca_asoc_populate_dapm, "SND_SOC_SDCA");
799829

830+
static int control_limit_kctl(struct device *dev,
831+
struct sdca_entity *entity,
832+
struct sdca_control *control,
833+
struct snd_kcontrol_new *kctl)
834+
{
835+
struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
836+
struct sdca_control_range *range;
837+
int min, max, step;
838+
unsigned int *tlv;
839+
int shift;
840+
841+
if (control->type != SDCA_CTL_DATATYPE_Q7P8DB)
842+
return 0;
843+
844+
/*
845+
* FIXME: For now only handle the simple case of a single linear range
846+
*/
847+
range = control_find_range(dev, entity, control, SDCA_VOLUME_LINEAR_NCOLS, 1);
848+
if (!range)
849+
return -EINVAL;
850+
851+
min = sdca_range(range, SDCA_VOLUME_LINEAR_MIN, 0);
852+
max = sdca_range(range, SDCA_VOLUME_LINEAR_MAX, 0);
853+
step = sdca_range(range, SDCA_VOLUME_LINEAR_STEP, 0);
854+
855+
min = sign_extend32(min, control->nbits - 1);
856+
max = sign_extend32(max, control->nbits - 1);
857+
858+
/*
859+
* FIXME: Only support power of 2 step sizes as this can be supported
860+
* by a simple shift.
861+
*/
862+
if (hweight32(step) != 1) {
863+
dev_err(dev, "%s: %s: currently unsupported step size\n",
864+
entity->label, control->label);
865+
return -EINVAL;
866+
}
867+
868+
/*
869+
* The SDCA volumes are in steps of 1/256th of a dB, a step down of
870+
* 64 (shift of 6) gives 1/4dB. 1/4dB is the smallest unit that is also
871+
* representable in the ALSA TLVs which are in 1/100ths of a dB.
872+
*/
873+
shift = max(ffs(step) - 1, 6);
874+
875+
tlv = devm_kcalloc(dev, 4, sizeof(*tlv), GFP_KERNEL);
876+
if (!tlv)
877+
return -ENOMEM;
878+
879+
tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
880+
tlv[1] = 2 * sizeof(*tlv);
881+
tlv[2] = (min * 100) >> 8;
882+
tlv[3] = ((1 << shift) * 100) >> 8;
883+
884+
mc->min = min >> shift;
885+
mc->max = max >> shift;
886+
mc->shift = shift;
887+
mc->rshift = shift;
888+
mc->sign_bit = 15 - shift;
889+
890+
kctl->tlv.p = tlv;
891+
kctl->access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
892+
893+
return 0;
894+
}
895+
896+
static int populate_control(struct device *dev,
897+
struct sdca_function_data *function,
898+
struct sdca_entity *entity,
899+
struct sdca_control *control,
900+
struct snd_kcontrol_new **kctl)
901+
{
902+
const char *control_suffix = "";
903+
const char *control_name;
904+
struct soc_mixer_control *mc;
905+
int index = 0;
906+
int ret;
907+
int cn;
908+
909+
if (!exported_control(entity, control))
910+
return 0;
911+
912+
if (control->type == SDCA_CTL_DATATYPE_ONEBIT)
913+
control_suffix = " Switch";
914+
915+
control_name = devm_kasprintf(dev, GFP_KERNEL, "%s %s%s", entity->label,
916+
control->label, control_suffix);
917+
if (!control_name)
918+
return -ENOMEM;
919+
920+
mc = devm_kmalloc(dev, sizeof(*mc), GFP_KERNEL);
921+
if (!mc)
922+
return -ENOMEM;
923+
924+
for_each_set_bit(cn, (unsigned long *)&control->cn_list,
925+
BITS_PER_TYPE(control->cn_list)) {
926+
switch (index++) {
927+
case 0:
928+
mc->reg = SDW_SDCA_CTL(function->desc->adr, entity->id,
929+
control->sel, cn);
930+
mc->rreg = mc->reg;
931+
break;
932+
case 1:
933+
mc->rreg = SDW_SDCA_CTL(function->desc->adr, entity->id,
934+
control->sel, cn);
935+
break;
936+
default:
937+
dev_err(dev, "%s: %s: only mono/stereo controls supported\n",
938+
entity->label, control->label);
939+
return -EINVAL;
940+
}
941+
}
942+
943+
mc->min = 0;
944+
mc->max = clamp((0x1ull << control->nbits) - 1, 0, type_max(mc->max));
945+
946+
(*kctl)->name = control_name;
947+
(*kctl)->private_value = (unsigned long)mc;
948+
(*kctl)->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
949+
(*kctl)->info = snd_soc_info_volsw;
950+
(*kctl)->get = snd_soc_get_volsw;
951+
(*kctl)->put = snd_soc_put_volsw;
952+
953+
if (readonly_control(control))
954+
(*kctl)->access = SNDRV_CTL_ELEM_ACCESS_READ;
955+
else
956+
(*kctl)->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
957+
958+
ret = control_limit_kctl(dev, entity, control, *kctl);
959+
if (ret)
960+
return ret;
961+
962+
(*kctl)++;
963+
964+
return 0;
965+
}
966+
967+
static int populate_pin_switch(struct device *dev,
968+
struct sdca_entity *entity,
969+
struct snd_kcontrol_new **kctl)
970+
{
971+
const char *control_name;
972+
973+
control_name = devm_kasprintf(dev, GFP_KERNEL, "%s Switch", entity->label);
974+
if (!control_name)
975+
return -ENOMEM;
976+
977+
(*kctl)->name = control_name;
978+
(*kctl)->private_value = (unsigned long)entity->label;
979+
(*kctl)->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
980+
(*kctl)->info = snd_soc_dapm_info_pin_switch;
981+
(*kctl)->get = snd_soc_dapm_get_component_pin_switch;
982+
(*kctl)->put = snd_soc_dapm_put_component_pin_switch;
983+
(*kctl)++;
984+
985+
return 0;
986+
}
987+
988+
/**
989+
* sdca_asoc_populate_controls - fill in an array of ALSA controls for a Function
990+
* @dev: Pointer to the device against which allocations will be done.
991+
* @function: Pointer to the Function information.
992+
* @route: Array of ALSA controls to be populated.
993+
*
994+
* This function populates an array of ALSA controls from the DisCo
995+
* information for a particular SDCA Function. Typically,
996+
* snd_soc_asoc_count_component will be used to allocate an
997+
* appropriately sized array before calling this function.
998+
*
999+
* Return: Returns zero on success, and a negative error code on failure.
1000+
*/
1001+
int sdca_asoc_populate_controls(struct device *dev,
1002+
struct sdca_function_data *function,
1003+
struct snd_kcontrol_new *kctl)
1004+
{
1005+
int i, j;
1006+
int ret;
1007+
1008+
for (i = 0; i < function->num_entities; i++) {
1009+
struct sdca_entity *entity = &function->entities[i];
1010+
1011+
switch (entity->type) {
1012+
case SDCA_ENTITY_TYPE_IT:
1013+
case SDCA_ENTITY_TYPE_OT:
1014+
if (!entity->iot.is_dataport) {
1015+
ret = populate_pin_switch(dev, entity, &kctl);
1016+
if (ret)
1017+
return ret;
1018+
}
1019+
break;
1020+
default:
1021+
break;
1022+
}
1023+
1024+
for (j = 0; j < entity->num_controls; j++) {
1025+
ret = populate_control(dev, function, entity,
1026+
&entity->controls[j], &kctl);
1027+
if (ret)
1028+
return ret;
1029+
}
1030+
}
1031+
1032+
return 0;
1033+
}
1034+
EXPORT_SYMBOL_NS(sdca_asoc_populate_controls, "SND_SOC_SDCA");
1035+
8001036
/**
8011037
* sdca_asoc_populate_component - fill in a component driver for a Function
8021038
* @dev: Pointer to the device against which allocations will be done.
@@ -815,10 +1051,12 @@ int sdca_asoc_populate_component(struct device *dev,
8151051
{
8161052
struct snd_soc_dapm_widget *widgets;
8171053
struct snd_soc_dapm_route *routes;
818-
int num_widgets, num_routes;
1054+
struct snd_kcontrol_new *controls;
1055+
int num_widgets, num_routes, num_controls;
8191056
int ret;
8201057

821-
ret = sdca_asoc_count_component(dev, function, &num_widgets, &num_routes);
1058+
ret = sdca_asoc_count_component(dev, function, &num_widgets, &num_routes,
1059+
&num_controls);
8221060
if (ret)
8231061
return ret;
8241062

@@ -830,14 +1068,24 @@ int sdca_asoc_populate_component(struct device *dev,
8301068
if (!routes)
8311069
return -ENOMEM;
8321070

1071+
controls = devm_kcalloc(dev, num_controls, sizeof(*controls), GFP_KERNEL);
1072+
if (!controls)
1073+
return -ENOMEM;
1074+
8331075
ret = sdca_asoc_populate_dapm(dev, function, widgets, routes);
8341076
if (ret)
8351077
return ret;
8361078

1079+
ret = sdca_asoc_populate_controls(dev, function, controls);
1080+
if (ret)
1081+
return ret;
1082+
8371083
component_drv->dapm_widgets = widgets;
8381084
component_drv->num_dapm_widgets = num_widgets;
8391085
component_drv->dapm_routes = routes;
8401086
component_drv->num_dapm_routes = num_routes;
1087+
component_drv->controls = controls;
1088+
component_drv->num_controls = num_controls;
8411089

8421090
return 0;
8431091
}

0 commit comments

Comments
 (0)