Skip to content

Commit 1f2e41b

Browse files
charleskeepaxgregkh
authored andcommitted
ASoC: SDCA: Update counting of SU/GE DAPM routes
[ Upstream commit 1fb720d ] Device Layer Selector Unit's are controlled by a Group Entity control rather than by the host directly. For the purposes of the ASoC class driver the number of input routes to the SU is controlled by the number of options within the Group Entity Selected Mode Control. ie. One valid DAPM route for each valid route defined in the Group Entity. Currently the code assumes that a Device Layer SU will have a number of routes equal to the number of potential sources for the SU. ie. it counts the routes using the SU, but then creates the routes using the GE. However, this isn't actually true, it is perfectly allowed for the GE to only define options for some of the potential sources of the SU.o In such a case the number of routes return will not match those created, leading to either an overflow of the routes array or undefined routes to be past to the ASoC core, both of which generally lead to the sound card failing to probe. Update the handling for the counting of routes to count the connected routes on the GE itself and then ignore the source routes on the SU. This makes it match the logic generating the routes and ensuring that both remain in sync. Fixes: 2c8b3a8 ("ASoC: SDCA: Create DAPM widgets and routes from DisCo") Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> Link: https://patch.msgid.link/20260225140118.402695-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 36a0dcd commit 1f2e41b

1 file changed

Lines changed: 34 additions & 7 deletions

File tree

sound/soc/sdca/sdca_asoc.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@ static bool readonly_control(struct sdca_control *control)
5151
return control->has_fixed || control->mode == SDCA_ACCESS_MODE_RO;
5252
}
5353

54+
static int ge_count_routes(struct sdca_entity *entity)
55+
{
56+
int count = 0;
57+
int i, j;
58+
59+
for (i = 0; i < entity->ge.num_modes; i++) {
60+
struct sdca_ge_mode *mode = &entity->ge.modes[i];
61+
62+
for (j = 0; j < mode->num_controls; j++) {
63+
struct sdca_ge_control *affected = &mode->controls[j];
64+
65+
if (affected->sel != SDCA_CTL_SU_SELECTOR || affected->val)
66+
count++;
67+
}
68+
}
69+
70+
return count;
71+
}
72+
5473
/**
5574
* sdca_asoc_count_component - count the various component parts
5675
* @dev: Pointer to the device against which allocations will be done.
@@ -74,6 +93,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
7493
int *num_widgets, int *num_routes, int *num_controls,
7594
int *num_dais)
7695
{
96+
struct sdca_control *control;
7797
int i, j;
7898

7999
*num_widgets = function->num_entities - 1;
@@ -83,6 +103,7 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
83103

84104
for (i = 0; i < function->num_entities - 1; i++) {
85105
struct sdca_entity *entity = &function->entities[i];
106+
bool skip_primary_routes = false;
86107

87108
/* Add supply/DAI widget connections */
88109
switch (entity->type) {
@@ -96,6 +117,17 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
96117
case SDCA_ENTITY_TYPE_PDE:
97118
*num_routes += entity->pde.num_managed;
98119
break;
120+
case SDCA_ENTITY_TYPE_GE:
121+
*num_routes += ge_count_routes(entity);
122+
skip_primary_routes = true;
123+
break;
124+
case SDCA_ENTITY_TYPE_SU:
125+
control = sdca_selector_find_control(dev, entity, SDCA_CTL_SU_SELECTOR);
126+
if (!control)
127+
return -EINVAL;
128+
129+
skip_primary_routes = (control->layers == SDCA_ACCESS_LAYER_DEVICE);
130+
break;
99131
default:
100132
break;
101133
}
@@ -104,7 +136,8 @@ int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *fun
104136
(*num_routes)++;
105137

106138
/* Add primary entity connections from DisCo */
107-
*num_routes += entity->num_sources;
139+
if (!skip_primary_routes)
140+
*num_routes += entity->num_sources;
108141

109142
for (j = 0; j < entity->num_controls; j++) {
110143
if (exported_control(entity, &entity->controls[j]))
@@ -451,7 +484,6 @@ static int entity_parse_su_device(struct device *dev,
451484
struct snd_soc_dapm_route **route)
452485
{
453486
struct sdca_control_range *range;
454-
int num_routes = 0;
455487
int i, j;
456488

457489
if (!entity->group) {
@@ -487,11 +519,6 @@ static int entity_parse_su_device(struct device *dev,
487519
return -EINVAL;
488520
}
489521

490-
if (++num_routes > entity->num_sources) {
491-
dev_err(dev, "%s: too many input routes\n", entity->label);
492-
return -EINVAL;
493-
}
494-
495522
term = sdca_range_search(range, SDCA_SELECTED_MODE_INDEX,
496523
mode->val, SDCA_SELECTED_MODE_TERM_TYPE);
497524
if (!term) {

0 commit comments

Comments
 (0)