public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] Improve SDCA support for duplicated features
@ 2026-04-30 10:21 Charles Keepax
  2026-04-30 10:21 ` [PATCH v2 1/3] ASoC: SDCA: Add correct masks whilst reporting SDCA jack status Charles Keepax
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Charles Keepax @ 2026-04-30 10:21 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
	niranjan.hy, kevin-lu, baojun.xu, linux-sound, linux-kernel,
	patches

There are some short comings of the current SDCA class driver with
respect to duplicated functions and jacks. Fix some issues in the
reporting of jacks when there are multiple jacks represented in the SDCA
topology. When a single device contains multiple instances of the same
type of SDCA function the current class driver will create duplicate
controls, update the code to fix this. Finally whilst working through
this also tidy up the handling of the sdca_function_desc pointers as it
turns out some duplication has crept into the code on that front.

Thanks,
Charles

Changes since v1:
 - Update tas2783 for API changes
 - Correct kernel doc

Charles Keepax (3):
  ASoC: SDCA: Add correct masks whilst reporting SDCA jack status
  ASoC: SDCA: Remove sdca_function_data duplication
  ASoC: SDCA: Support devices with multiple functions of identical type

 include/sound/sdca.h                 |  4 ++
 include/sound/sdca_function.h        |  1 -
 include/sound/sdca_jack.h            |  3 ++
 sound/soc/codecs/tas2783-sdw.c       |  4 +-
 sound/soc/sdca/sdca_class.c          |  7 ---
 sound/soc/sdca/sdca_class.h          |  1 -
 sound/soc/sdca/sdca_class_function.c | 23 ++-------
 sound/soc/sdca/sdca_functions.c      | 51 ++++++++++++-------
 sound/soc/sdca/sdca_interrupts.c     |  3 +-
 sound/soc/sdca/sdca_jack.c           | 75 ++++++++++++++++------------
 10 files changed, 92 insertions(+), 80 deletions(-)

-- 
2.47.3


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/3] ASoC: SDCA: Add correct masks whilst reporting SDCA jack status
  2026-04-30 10:21 [PATCH v2 0/3] Improve SDCA support for duplicated features Charles Keepax
@ 2026-04-30 10:21 ` Charles Keepax
  2026-04-30 10:21 ` [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication Charles Keepax
  2026-04-30 10:21 ` [PATCH v2 3/3] ASoC: SDCA: Support devices with multiple functions of identical type Charles Keepax
  2 siblings, 0 replies; 6+ messages in thread
From: Charles Keepax @ 2026-04-30 10:21 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
	niranjan.hy, kevin-lu, baojun.xu, linux-sound, linux-kernel,
	patches

Currently, all SDCA jacks simply report against a mask of 0xFFFF. This
works fine for system with a single SDCA jack control as the status
reflects that single control at all times. However, if two SDCA
jack controls exist in the system, such as a separate representation for
input and output, then the second control can cancel reports from the
other since it will only report its relevant bits and zero in all other
slots. This is exactly what the mask is for.

Build up a mask using all the possible states for an SCDA jack control
at registration time and use that mask when reporting a particular jack.
It is worth noting this still doesn't handle cases such as two headphone
jacks as that would require separate ALSA jacks to report to.

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

No changes since v1.

 include/sound/sdca_jack.h  |  3 ++
 sound/soc/sdca/sdca_jack.c | 75 ++++++++++++++++++++++----------------
 2 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h
index 3ec22046d3ebc..181541f0f4d8c 100644
--- a/include/sound/sdca_jack.h
+++ b/include/sound/sdca_jack.h
@@ -18,10 +18,13 @@ struct snd_soc_jack;
  * struct jack_state - Jack state structure to keep data between interrupts
  * @kctl: Pointer to the ALSA control attached to this jack
  * @jack: Pointer to the ASoC jack struct for this jack
+ * @mask: Possible reported jack status bits for this jack
  */
 struct jack_state {
 	struct snd_kcontrol *kctl;
 	struct snd_soc_jack *jack;
+
+	unsigned int mask;
 };
 
 int sdca_jack_alloc_state(struct sdca_interrupt *interrupt);
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 49d317d3b8c85..be2506f38c711 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -145,6 +145,32 @@ int sdca_jack_alloc_state(struct sdca_interrupt *interrupt)
 }
 EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA");
 
+static int type_get_mask(enum sdca_terminal_type type)
+{
+	switch (type) {
+	case SDCA_TERM_TYPE_LINEIN_STEREO:
+	case SDCA_TERM_TYPE_LINEIN_FRONT_LR:
+	case SDCA_TERM_TYPE_LINEIN_CENTER_LFE:
+	case SDCA_TERM_TYPE_LINEIN_SURROUND_LR:
+	case SDCA_TERM_TYPE_LINEIN_REAR_LR:
+		return SND_JACK_LINEIN;
+	case SDCA_TERM_TYPE_LINEOUT_STEREO:
+	case SDCA_TERM_TYPE_LINEOUT_FRONT_LR:
+	case SDCA_TERM_TYPE_LINEOUT_CENTER_LFE:
+	case SDCA_TERM_TYPE_LINEOUT_SURROUND_LR:
+	case SDCA_TERM_TYPE_LINEOUT_REAR_LR:
+		return SND_JACK_LINEOUT;
+	case SDCA_TERM_TYPE_MIC_JACK:
+		return SND_JACK_MICROPHONE;
+	case SDCA_TERM_TYPE_HEADPHONE_JACK:
+		return SND_JACK_HEADPHONE;
+	case SDCA_TERM_TYPE_HEADSET_JACK:
+		return SND_JACK_HEADSET;
+	default:
+		return 0;
+	}
+}
+
 /**
  * sdca_jack_set_jack - attach an ASoC jack to SDCA
  * @info: SDCA interrupt information.
@@ -154,7 +180,8 @@ EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA");
  */
 int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack)
 {
-	int i, ret;
+	int i, j;
+	int ret;
 
 	guard(mutex)(&info->irq_lock);
 
@@ -162,6 +189,7 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
 		struct sdca_interrupt *interrupt = &info->irqs[i];
 		struct sdca_control *control = interrupt->control;
 		struct sdca_entity *entity = interrupt->entity;
+		struct sdca_control_range *range;
 		struct jack_state *jack_state;
 
 		if (!interrupt->irq)
@@ -169,9 +197,23 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
 
 		switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
 		case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
+			range = sdca_selector_find_range(interrupt->dev, entity,
+							 SDCA_CTL_GE_SELECTED_MODE,
+							 SDCA_SELECTED_MODE_NCOLS, 0);
+			if (!range)
+				return -EINVAL;
+
 			jack_state = interrupt->priv;
 			jack_state->jack = jack;
 
+			for (j = 0; j < range->rows; j++) {
+				enum sdca_terminal_type type;
+
+				type = sdca_range(range, SDCA_SELECTED_MODE_TERM_TYPE, j);
+
+				jack_state->mask |= type_get_mask(type);
+			}
+
 			/* Report initial state in case IRQ was already handled */
 			ret = sdca_jack_report(interrupt);
 			if (ret)
@@ -191,7 +233,6 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
 	struct jack_state *jack_state = interrupt->priv;
 	struct sdca_control_range *range;
 	enum sdca_terminal_type type;
-	unsigned int report = 0;
 	unsigned int reg, val;
 	int ret;
 
@@ -213,35 +254,7 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
 	type = sdca_range_search(range, SDCA_SELECTED_MODE_INDEX,
 				 val, SDCA_SELECTED_MODE_TERM_TYPE);
 
-	switch (type) {
-	case SDCA_TERM_TYPE_LINEIN_STEREO:
-	case SDCA_TERM_TYPE_LINEIN_FRONT_LR:
-	case SDCA_TERM_TYPE_LINEIN_CENTER_LFE:
-	case SDCA_TERM_TYPE_LINEIN_SURROUND_LR:
-	case SDCA_TERM_TYPE_LINEIN_REAR_LR:
-		report = SND_JACK_LINEIN;
-		break;
-	case SDCA_TERM_TYPE_LINEOUT_STEREO:
-	case SDCA_TERM_TYPE_LINEOUT_FRONT_LR:
-	case SDCA_TERM_TYPE_LINEOUT_CENTER_LFE:
-	case SDCA_TERM_TYPE_LINEOUT_SURROUND_LR:
-	case SDCA_TERM_TYPE_LINEOUT_REAR_LR:
-		report = SND_JACK_LINEOUT;
-		break;
-	case SDCA_TERM_TYPE_MIC_JACK:
-		report = SND_JACK_MICROPHONE;
-		break;
-	case SDCA_TERM_TYPE_HEADPHONE_JACK:
-		report = SND_JACK_HEADPHONE;
-		break;
-	case SDCA_TERM_TYPE_HEADSET_JACK:
-		report = SND_JACK_HEADSET;
-		break;
-	default:
-		break;
-	}
-
-	snd_soc_jack_report(jack_state->jack, report, 0xFFFF);
+	snd_soc_jack_report(jack_state->jack, type_get_mask(type), jack_state->mask);
 
 	return 0;
 }
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication
  2026-04-30 10:21 [PATCH v2 0/3] Improve SDCA support for duplicated features Charles Keepax
  2026-04-30 10:21 ` [PATCH v2 1/3] ASoC: SDCA: Add correct masks whilst reporting SDCA jack status Charles Keepax
@ 2026-04-30 10:21 ` Charles Keepax
  2026-04-30 10:55   ` Mark Brown
  2026-04-30 10:21 ` [PATCH v2 3/3] ASoC: SDCA: Support devices with multiple functions of identical type Charles Keepax
  2 siblings, 1 reply; 6+ messages in thread
From: Charles Keepax @ 2026-04-30 10:21 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
	niranjan.hy, kevin-lu, baojun.xu, linux-sound, linux-kernel,
	patches

The class driver internally has an array of sdca_function_data pointers
that it uses to store the parsed DisCo data. However, there is already
an sdca_function_data attached to the auxdev device. It makes more sense
to use the one already provided in the auxdev device, as it could also
be used by custom drivers for parts that require those.

Using the auxdev copy also prevents the need for the class function
drivers to search through the array for the correct data, which
currently is based off matching the function type. This has problems
when two functions have the same type as the current code will find the
same data for both drivers, using the auxdev copy of the data avoids
this problem.

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

Changes since v1:
 - Update tas2783 for the API change (note this is untested although I
   am pretty confident it is fine, but Niranjan is CCed).

 include/sound/sdca_function.h        |  1 -
 sound/soc/codecs/tas2783-sdw.c       |  4 +---
 sound/soc/sdca/sdca_class.c          |  7 -------
 sound/soc/sdca/sdca_class.h          |  1 -
 sound/soc/sdca/sdca_class_function.c | 23 +++++------------------
 sound/soc/sdca/sdca_functions.c      | 25 ++++++++++---------------
 6 files changed, 16 insertions(+), 45 deletions(-)

diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h
index 0e871c786513f..b1489178b0ef8 100644
--- a/include/sound/sdca_function.h
+++ b/include/sound/sdca_function.h
@@ -1452,7 +1452,6 @@ static inline u32 sdca_range_search(struct sdca_control_range *range,
 }
 
 int sdca_parse_function(struct device *dev, struct sdw_slave *sdw,
-			struct sdca_function_desc *desc,
 			struct sdca_function_data *function);
 
 const char *sdca_find_terminal_name(enum sdca_terminal_type type);
diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index 90008d2d06e2c..810ddd40ecbee 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -1311,9 +1311,7 @@ static s32 tas_sdw_probe(struct sdw_slave *peripheral,
 					     "failed to parse sdca functions");
 
 		/* Parse the function */
-		ret = sdca_parse_function(dev, peripheral,
-					  &peripheral->sdca_data.function[i],
-					  function_data);
+		ret = sdca_parse_function(dev, peripheral, function_data);
 		if (!ret)
 			tas_dev->sa_func_data = function_data;
 		else
diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c
index 6e9b66f718019..a6a3da8de4371 100644
--- a/sound/soc/sdca/sdca_class.c
+++ b/sound/soc/sdca/sdca_class.c
@@ -183,7 +183,6 @@ static void class_boot_work(struct work_struct *work)
 static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id)
 {
 	struct device *dev = &sdw->dev;
-	struct sdca_device_data *data = &sdw->sdca_data;
 	struct regmap_config *dev_config;
 	struct sdca_class_drv *drv;
 	int ret;
@@ -199,12 +198,6 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id
 	if (!dev_config)
 		return -ENOMEM;
 
-	drv->functions = devm_kcalloc(dev, data->num_functions,
-				      sizeof(*drv->functions),
-				      GFP_KERNEL);
-	if (!drv->functions)
-		return -ENOMEM;
-
 	drv->dev = dev;
 	drv->sdw = sdw;
 	mutex_init(&drv->regmap_lock);
diff --git a/sound/soc/sdca/sdca_class.h b/sound/soc/sdca/sdca_class.h
index 6f24ea2bbd381..8b63e62485e64 100644
--- a/sound/soc/sdca/sdca_class.h
+++ b/sound/soc/sdca/sdca_class.h
@@ -24,7 +24,6 @@ struct sdca_class_drv {
 	struct regmap *dev_regmap;
 	struct sdw_slave *sdw;
 
-	struct sdca_function_data *functions;
 	struct sdca_interrupt_info *irq_info;
 
 	struct mutex regmap_lock;
diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 31fc08d513077..1496a15f7d2ac 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -27,6 +27,7 @@
 #include <sound/soc-dai.h>
 #include <sound/soc.h>
 #include "sdca_class.h"
+#include "sdca_function_device.h"
 
 struct class_function_drv {
 	struct device *dev;
@@ -294,8 +295,7 @@ static int class_function_probe(struct auxiliary_device *auxdev,
 {
 	struct device *dev = &auxdev->dev;
 	struct sdca_class_drv *core = dev_get_drvdata(dev->parent);
-	struct sdca_device_data *data = &core->sdw->sdca_data;
-	struct sdca_function_desc *desc;
+	struct sdca_dev *sdev = auxiliary_dev_to_sdca_dev(auxdev);
 	struct snd_soc_component_driver *cmp_drv;
 	struct snd_soc_dai_driver *dais;
 	struct class_function_drv *drv;
@@ -305,7 +305,6 @@ static int class_function_probe(struct auxiliary_device *auxdev,
 	int ndefaults;
 	int num_dais;
 	int ret;
-	int i;
 
 	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
 	if (!drv)
@@ -328,21 +327,9 @@ static int class_function_probe(struct auxiliary_device *auxdev,
 
 	drv->dev = dev;
 	drv->core = core;
+	drv->function = &sdev->function;
 
-	for (i = 0; i < data->num_functions; i++) {
-		desc = &data->function[i];
-
-		if (desc->type == aux_dev_id->driver_data)
-			break;
-	}
-	if (i == core->sdw->sdca_data.num_functions) {
-		dev_err(dev, "failed to locate function\n");
-		return -EINVAL;
-	}
-
-	drv->function = &core->functions[i];
-
-	ret = sdca_parse_function(dev, core->sdw, desc, drv->function);
+	ret = sdca_parse_function(dev, core->sdw, drv->function);
 	if (ret)
 		return ret;
 
@@ -377,7 +364,7 @@ static int class_function_probe(struct auxiliary_device *auxdev,
 		return dev_err_probe(dev, PTR_ERR(drv->regmap),
 				     "failed to create regmap");
 
-	switch (desc->type) {
+	switch (drv->function->desc->type) {
 	case SDCA_FUNCTION_TYPE_UAJ:
 	case SDCA_FUNCTION_TYPE_RJ:
 		cmp_drv->set_jack = class_function_set_jack;
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
index 196bade11ab5d..02abb7315b727 100644
--- a/sound/soc/sdca/sdca_functions.c
+++ b/sound/soc/sdca/sdca_functions.c
@@ -2158,27 +2158,22 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw,
  * sdca_parse_function - parse ACPI DisCo for a Function
  * @dev: Pointer to device against which function data will be allocated.
  * @sdw: SoundWire slave device to be processed.
- * @function_desc: Pointer to the Function short descriptor.
  * @function: Pointer to the Function information, to be populated.
  *
  * Return: Returns 0 for success.
  */
 int sdca_parse_function(struct device *dev, struct sdw_slave *sdw,
-			struct sdca_function_desc *function_desc,
 			struct sdca_function_data *function)
 {
+	struct fwnode_handle *node = function->desc->node;
 	u32 tmp;
 	int ret;
 
-	function->desc = function_desc;
-
-	ret = fwnode_property_read_u32(function_desc->node,
-				       "mipi-sdca-function-busy-max-delay", &tmp);
+	ret = fwnode_property_read_u32(node, "mipi-sdca-function-busy-max-delay", &tmp);
 	if (!ret)
 		function->busy_max_delay = tmp;
 
-	ret = fwnode_property_read_u32(function_desc->node,
-				       "mipi-sdca-function-reset-max-delay", &tmp);
+	ret = fwnode_property_read_u32(node, "mipi-sdca-function-reset-max-delay", &tmp);
 	if (ret || tmp == 0) {
 		dev_dbg(dev, "reset delay missing, defaulting to 100mS\n");
 		function->reset_max_delay = 100000;
@@ -2187,26 +2182,26 @@ int sdca_parse_function(struct device *dev, struct sdw_slave *sdw,
 	}
 
 	dev_dbg(dev, "%pfwP: name %s busy delay %dus reset delay %dus\n",
-		function->desc->node, function->desc->name,
-		function->busy_max_delay, function->reset_max_delay);
+		node, function->desc->name, function->busy_max_delay,
+		function->reset_max_delay);
 
-	ret = find_sdca_init_table(dev, function_desc->node, function);
+	ret = find_sdca_init_table(dev, node, function);
 	if (ret)
 		return ret;
 
-	ret = find_sdca_entities(dev, sdw, function_desc->node, function);
+	ret = find_sdca_entities(dev, sdw, node, function);
 	if (ret)
 		return ret;
 
-	ret = find_sdca_connections(dev, function_desc->node, function);
+	ret = find_sdca_connections(dev, node, function);
 	if (ret)
 		return ret;
 
-	ret = find_sdca_clusters(dev, function_desc->node, function);
+	ret = find_sdca_clusters(dev, node, function);
 	if (ret < 0)
 		return ret;
 
-	ret = find_sdca_filesets(dev, sdw, function_desc->node, function);
+	ret = find_sdca_filesets(dev, sdw, node, function);
 	if (ret)
 		return ret;
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/3] ASoC: SDCA: Support devices with multiple functions of identical type
  2026-04-30 10:21 [PATCH v2 0/3] Improve SDCA support for duplicated features Charles Keepax
  2026-04-30 10:21 ` [PATCH v2 1/3] ASoC: SDCA: Add correct masks whilst reporting SDCA jack status Charles Keepax
  2026-04-30 10:21 ` [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication Charles Keepax
@ 2026-04-30 10:21 ` Charles Keepax
  2 siblings, 0 replies; 6+ messages in thread
From: Charles Keepax @ 2026-04-30 10:21 UTC (permalink / raw)
  To: broonie
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
	niranjan.hy, kevin-lu, baojun.xu, linux-sound, linux-kernel,
	patches

It is possible that SDCAs devices might have multiple functions of
the same type, as the entity names within a function are defined by
the specification it is very likely such a device will have duplicate
entities. This causes problems where DAIs and ALSA controls end up
with clashing names.

This can be handled by adding the function address into the names to
ensure uniqueness, although, ideally this would have been included from
the start. User-space already has UCM using the current control names,
so as a compromise the first function of a given type will use the
raw entity names, then duplicates will get an added function address.

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---

Changes since v1:
 - Correct kernel doc.

 include/sound/sdca.h             |  4 ++++
 sound/soc/sdca/sdca_functions.c  | 26 ++++++++++++++++++++++++--
 sound/soc/sdca/sdca_interrupts.c |  3 +--
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/include/sound/sdca.h b/include/sound/sdca.h
index 67ff3c88705d5..2bdf4e333e044 100644
--- a/include/sound/sdca.h
+++ b/include/sound/sdca.h
@@ -26,6 +26,8 @@ struct sdca_dev;
  * @name: Human-readable string.
  * @type: Function topology type.
  * @adr: ACPI address (used for SDCA register access).
+ * @duplicate: Internal flag to indicate if other functions of the same type
+ * exist.
  */
 struct sdca_function_desc {
 	struct fwnode_handle *node;
@@ -33,6 +35,8 @@ struct sdca_function_desc {
 	const char *name;
 	u32 type;
 	u8 adr;
+
+	bool duplicate;
 };
 
 /**
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
index 02abb7315b727..77940bd6b33c9 100644
--- a/sound/soc/sdca/sdca_functions.c
+++ b/sound/soc/sdca/sdca_functions.c
@@ -98,7 +98,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
 	u32 function_type;
 	int function_index;
 	u64 addr;
-	int ret;
+	int i, ret;
 
 	if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) {
 		dev_err(dev, "maximum number of functions exceeded\n");
@@ -159,6 +159,14 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
 
 	/* store results */
 	function_index = sdca_data->num_functions;
+
+	for (i = 0; i < function_index; i++) {
+		if (sdca_data->function[i].type == function_type) {
+			sdca_data->function[function_index].duplicate = true;
+			break;
+		}
+	}
+
 	sdca_data->function[function_index].adr = addr;
 	sdca_data->function[function_index].type = function_type;
 	sdca_data->function[function_index].name = function_name;
@@ -1466,6 +1474,7 @@ static int find_sdca_entity_xu(struct device *dev,
 }
 
 static int find_sdca_entity(struct device *dev, struct sdw_slave *sdw,
+			    struct sdca_function_data *function,
 			    struct fwnode_handle *function_node,
 			    struct fwnode_handle *entity_node,
 			    struct sdca_entity *entity)
@@ -1481,6 +1490,13 @@ static int find_sdca_entity(struct device *dev, struct sdw_slave *sdw,
 		return ret;
 	}
 
+	if (function->desc->duplicate) {
+		entity->label = devm_kasprintf(dev, GFP_KERNEL, "%d %s",
+					       function->desc->adr, entity->label);
+		if (!entity->label)
+			return -ENOMEM;
+	}
+
 	ret = fwnode_property_read_u32(entity_node, "mipi-sdca-entity-type", &tmp);
 	if (ret) {
 		dev_err(dev, "%s: type missing: %d\n", entity->label, ret);
@@ -1578,7 +1594,7 @@ static int find_sdca_entities(struct device *dev, struct sdw_slave *sdw,
 			return -EINVAL;
 		}
 
-		ret = find_sdca_entity(dev, sdw, function_node,
+		ret = find_sdca_entity(dev, sdw, function, function_node,
 				       entity_node, &entities[i]);
 		fwnode_handle_put(entity_node);
 		if (ret)
@@ -1605,8 +1621,14 @@ static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data *
 						     const char *entity_label)
 {
 	struct sdca_entity *entity = NULL;
+	char tmp[64];
 	int i;
 
+	if (function->desc->duplicate) {
+		snprintf(tmp, sizeof(tmp), "%d %s", function->desc->adr, entity_label);
+		entity_label = tmp;
+	}
+
 	for (i = 0; i < function->num_entities; i++) {
 		entity = &function->entities[i];
 
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 6e10b4e660d96..4539a52a8e32b 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -375,8 +375,7 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap,
 	if (!dev)
 		return -ENODEV;
 
-	name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name,
-			 entity->label, control->label);
+	name = kasprintf(GFP_KERNEL, "%s %s", entity->label, control->label);
 	if (!name)
 		return -ENOMEM;
 
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication
  2026-04-30 10:21 ` [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication Charles Keepax
@ 2026-04-30 10:55   ` Mark Brown
  2026-04-30 12:03     ` Charles Keepax
  0 siblings, 1 reply; 6+ messages in thread
From: Mark Brown @ 2026-04-30 10:55 UTC (permalink / raw)
  To: Charles Keepax
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
	niranjan.hy, kevin-lu, baojun.xu, linux-sound, linux-kernel,
	patches

[-- Attachment #1: Type: text/plain, Size: 319 bytes --]

On Thu, Apr 30, 2026 at 11:21:19AM +0100, Charles Keepax wrote:

>  		/* Parse the function */
> -		ret = sdca_parse_function(dev, peripheral,
> -					  &peripheral->sdca_data.function[i],
> -					  function_data);
> +		ret = sdca_parse_function(dev, peripheral, function_data);

What sets up function_data->desc here?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication
  2026-04-30 10:55   ` Mark Brown
@ 2026-04-30 12:03     ` Charles Keepax
  0 siblings, 0 replies; 6+ messages in thread
From: Charles Keepax @ 2026-04-30 12:03 UTC (permalink / raw)
  To: Mark Brown
  Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
	niranjan.hy, kevin-lu, baojun.xu, linux-sound, linux-kernel,
	patches

On Thu, Apr 30, 2026 at 07:55:30PM +0900, Mark Brown wrote:
> On Thu, Apr 30, 2026 at 11:21:19AM +0100, Charles Keepax wrote:
> 
> >  		/* Parse the function */
> > -		ret = sdca_parse_function(dev, peripheral,
> > -					  &peripheral->sdca_data.function[i],
> > -					  function_data);
> > +		ret = sdca_parse_function(dev, peripheral, function_data);
> 
> What sets up function_data->desc here?

Ah shoot, thanks again Mark. Sorry about that I will do a new
spin and try to be a little more careful. Overlooked that this
driver doesn't call sdca_dev_register_functions().

Thanks,
Charles

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-04-30 12:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-30 10:21 [PATCH v2 0/3] Improve SDCA support for duplicated features Charles Keepax
2026-04-30 10:21 ` [PATCH v2 1/3] ASoC: SDCA: Add correct masks whilst reporting SDCA jack status Charles Keepax
2026-04-30 10:21 ` [PATCH v2 2/3] ASoC: SDCA: Remove sdca_function_data duplication Charles Keepax
2026-04-30 10:55   ` Mark Brown
2026-04-30 12:03     ` Charles Keepax
2026-04-30 10:21 ` [PATCH v2 3/3] ASoC: SDCA: Support devices with multiple functions of identical type Charles Keepax

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox