Skip to content

Commit d1cd13f

Browse files
charleskeepaxbroonie
authored andcommitted
ASoC: SDCA: Add support for GE Entity properties
Add support for parsing the Group Entity properties from DisCo/ACPI. Group Entities allow control of several other Entities, typically Selector Units, from a single control. Signed-off-by: Charles Keepax <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 1bcbb88 commit d1cd13f

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

include/sound/sdca_function.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ struct sdca_function_desc;
4444
*/
4545
#define SDCA_MAX_DELAY_COUNT 256
4646

47+
/*
48+
* Sanity check on size of affected controls data, can be expanded if needed.
49+
*/
50+
#define SDCA_MAX_AFFECTED_COUNT 2048
51+
4752
/**
4853
* enum sdca_function_type - SDCA Function Type codes
4954
* @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features.
@@ -927,11 +932,51 @@ enum sdca_entity_type {
927932
SDCA_ENTITY_TYPE_HIDE = 0x31,
928933
};
929934

935+
/**
936+
* struct sdca_ge_control - control entry in the affected controls list
937+
* @id: Entity ID of the Control affected.
938+
* @sel: Control Selector of the Control affected.
939+
* @cn: Control Number of the Control affected.
940+
* @val: Value written to Control for this Mode.
941+
*/
942+
struct sdca_ge_control {
943+
int id;
944+
int sel;
945+
int cn;
946+
int val;
947+
};
948+
949+
/**
950+
* struct sdca_ge_mode - mode entry in the affected controls list
951+
* @controls: Dynamically allocated array of controls written for this Mode.
952+
* @num_controls: Number of controls written in this Mode.
953+
* @val: GE Selector Mode value.
954+
*/
955+
struct sdca_ge_mode {
956+
struct sdca_ge_control *controls;
957+
int num_controls;
958+
int val;
959+
};
960+
961+
/**
962+
* struct sdca_entity_ge - information specific to Group Entities
963+
* @kctl: ALSA control pointer that can be used by linked Entities.
964+
* @modes: Dynamically allocated array of Modes and the Controls written
965+
* in each mode.
966+
* @num_modes: Number of Modes.
967+
*/
968+
struct sdca_entity_ge {
969+
struct snd_kcontrol_new *kctl;
970+
struct sdca_ge_mode *modes;
971+
int num_modes;
972+
};
973+
930974
/**
931975
* struct sdca_entity - information for one SDCA Entity
932976
* @label: String such as "OT 12".
933977
* @id: Identifier used for addressing.
934978
* @type: Type code for the Entity.
979+
* @group: Pointer to Group Entity controlling this one, NULL if N/A.
935980
* @sources: Dynamically allocated array pointing to each input Entity
936981
* connected to this Entity.
937982
* @controls: Dynamically allocated array of Controls.
@@ -940,12 +985,14 @@ enum sdca_entity_type {
940985
* @iot: Input/Output Terminal specific Entity properties.
941986
* @cs: Clock Source specific Entity properties.
942987
* @pde: Power Domain Entity specific Entity properties.
988+
* @ge: Group Entity specific Entity properties.
943989
*/
944990
struct sdca_entity {
945991
const char *label;
946992
int id;
947993
enum sdca_entity_type type;
948994

995+
struct sdca_entity *group;
949996
struct sdca_entity **sources;
950997
struct sdca_control *controls;
951998
int num_sources;
@@ -954,6 +1001,7 @@ struct sdca_entity {
9541001
struct sdca_entity_iot iot;
9551002
struct sdca_entity_cs cs;
9561003
struct sdca_entity_pde pde;
1004+
struct sdca_entity_ge ge;
9571005
};
9581006
};
9591007

sound/soc/sdca/sdca_functions.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,92 @@ static int find_sdca_entity_pde(struct device *dev,
11361136
return 0;
11371137
}
11381138

1139+
struct raw_ge_mode {
1140+
u8 val;
1141+
u8 num_controls;
1142+
struct {
1143+
u8 id;
1144+
u8 sel;
1145+
u8 cn;
1146+
__le32 val;
1147+
} __packed controls[] __counted_by(num_controls);
1148+
} __packed;
1149+
1150+
static int find_sdca_entity_ge(struct device *dev,
1151+
struct fwnode_handle *entity_node,
1152+
struct sdca_entity *entity)
1153+
{
1154+
struct sdca_entity_ge *group = &entity->ge;
1155+
u8 *affected_list __free(kfree) = NULL;
1156+
u8 *affected_iter;
1157+
int num_affected;
1158+
int i, j;
1159+
1160+
num_affected = fwnode_property_count_u8(entity_node,
1161+
"mipi-sdca-ge-selectedmode-controls-affected");
1162+
if (!num_affected || num_affected == -EINVAL) {
1163+
return 0;
1164+
} else if (num_affected < 0) {
1165+
dev_err(dev, "%s: failed to read affected controls: %d\n",
1166+
entity->label, num_affected);
1167+
return num_affected;
1168+
} else if (num_affected > SDCA_MAX_AFFECTED_COUNT) {
1169+
dev_err(dev, "%s: maximum affected controls size exceeded\n",
1170+
entity->label);
1171+
return -EINVAL;
1172+
}
1173+
1174+
affected_list = kcalloc(num_affected, sizeof(*affected_list), GFP_KERNEL);
1175+
if (!affected_list)
1176+
return -ENOMEM;
1177+
1178+
fwnode_property_read_u8_array(entity_node,
1179+
"mipi-sdca-ge-selectedmode-controls-affected",
1180+
affected_list, num_affected);
1181+
1182+
group->num_modes = *affected_list;
1183+
affected_iter = affected_list + 1;
1184+
1185+
group->modes = devm_kcalloc(dev, group->num_modes, sizeof(*group->modes),
1186+
GFP_KERNEL);
1187+
if (!group->modes)
1188+
return -ENOMEM;
1189+
1190+
for (i = 0; i < group->num_modes; i++) {
1191+
struct raw_ge_mode *raw = (struct raw_ge_mode *)affected_iter;
1192+
struct sdca_ge_mode *mode = &group->modes[i];
1193+
1194+
affected_iter += sizeof(*raw);
1195+
if (affected_iter > affected_list + num_affected)
1196+
goto bad_list;
1197+
1198+
mode->val = raw->val;
1199+
mode->num_controls = raw->num_controls;
1200+
1201+
affected_iter += mode->num_controls * sizeof(raw->controls[0]);
1202+
if (affected_iter > affected_list + num_affected)
1203+
goto bad_list;
1204+
1205+
mode->controls = devm_kcalloc(dev, mode->num_controls,
1206+
sizeof(*mode->controls), GFP_KERNEL);
1207+
if (!mode->controls)
1208+
return -ENOMEM;
1209+
1210+
for (j = 0; j < mode->num_controls; j++) {
1211+
mode->controls[j].id = raw->controls[j].id;
1212+
mode->controls[j].sel = raw->controls[j].sel;
1213+
mode->controls[j].cn = raw->controls[j].cn;
1214+
mode->controls[j].val = le32_to_cpu(raw->controls[j].val);
1215+
}
1216+
}
1217+
1218+
return 0;
1219+
1220+
bad_list:
1221+
dev_err(dev, "%s: malformed affected controls list\n", entity->label);
1222+
return -EINVAL;
1223+
}
1224+
11391225
static int find_sdca_entity(struct device *dev,
11401226
struct fwnode_handle *function_node,
11411227
struct fwnode_handle *entity_node,
@@ -1174,6 +1260,9 @@ static int find_sdca_entity(struct device *dev,
11741260
case SDCA_ENTITY_TYPE_PDE:
11751261
ret = find_sdca_entity_pde(dev, entity_node, entity);
11761262
break;
1263+
case SDCA_ENTITY_TYPE_GE:
1264+
ret = find_sdca_entity_ge(dev, entity_node, entity);
1265+
break;
11771266
default:
11781267
break;
11791268
}
@@ -1384,6 +1473,42 @@ static int find_sdca_entity_connection_pde(struct device *dev,
13841473
return 0;
13851474
}
13861475

1476+
static int find_sdca_entity_connection_ge(struct device *dev,
1477+
struct sdca_function_data *function,
1478+
struct fwnode_handle *entity_node,
1479+
struct sdca_entity *entity)
1480+
{
1481+
int i, j;
1482+
1483+
for (i = 0; i < entity->ge.num_modes; i++) {
1484+
struct sdca_ge_mode *mode = &entity->ge.modes[i];
1485+
1486+
for (j = 0; j < mode->num_controls; j++) {
1487+
struct sdca_ge_control *affected = &mode->controls[j];
1488+
struct sdca_entity *managed;
1489+
1490+
managed = find_sdca_entity_by_id(function, affected->id);
1491+
if (!managed) {
1492+
dev_err(dev, "%s: failed to find entity with id %#x\n",
1493+
entity->label, affected->id);
1494+
return -EINVAL;
1495+
}
1496+
1497+
if (managed->group && managed->group != entity) {
1498+
dev_err(dev,
1499+
"%s: entity controlled by two groups %s, %s\n",
1500+
managed->label, managed->group->label,
1501+
entity->label);
1502+
return -EINVAL;
1503+
}
1504+
1505+
managed->group = entity;
1506+
}
1507+
}
1508+
1509+
return 0;
1510+
}
1511+
13871512
static int find_sdca_entity_connection(struct device *dev,
13881513
struct sdca_function_data *function,
13891514
struct fwnode_handle *entity_node,
@@ -1404,6 +1529,10 @@ static int find_sdca_entity_connection(struct device *dev,
14041529
ret = find_sdca_entity_connection_pde(dev, function,
14051530
entity_node, entity);
14061531
break;
1532+
case SDCA_ENTITY_TYPE_GE:
1533+
ret = find_sdca_entity_connection_ge(dev, function,
1534+
entity_node, entity);
1535+
break;
14071536
default:
14081537
ret = 0;
14091538
break;

0 commit comments

Comments
 (0)