* [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups
@ 2025-06-24 12:28 Charles Keepax
2025-06-24 12:28 ` [PATCH v3 1/7] MAINTAINERS: Add SDCA maintainers entry Charles Keepax
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
Add a maintainers entry for SDCA, do a couple of small fixups for
previous chains, and then adding the beginnings of the SDCA IRQ
handling. This is based around a regmap IRQ chip and a few helper
functions that can be called from the client drivers to setup the
IRQs.
Thanks,
Charles
Changes since v2:
- Just a rebase to avoid a conflict with the recently merged SDCA HID
stuff.
Charles Keepax (6):
MAINTAINERS: Add SDCA maintainers entry
ASoC: SDCA: Add missing default in switch in entity_pde_event()
ASoC: SDCA: Fixup some kernel doc errors
ASoC: SDCA: Minor selected/detected mode control fixups
ASoC: SDCA: Add flag for unused IRQs
ASoC: SDCA: Add some initial IRQ handlers
Maciej Strozek (1):
ASoC: SDCA: Generic interrupt support
MAINTAINERS | 11 +
include/sound/sdca_function.h | 11 +
include/sound/sdca_interrupts.h | 78 ++++++
sound/soc/sdca/Kconfig | 7 +
sound/soc/sdca/Makefile | 5 +-
sound/soc/sdca/sdca_asoc.c | 19 +-
sound/soc/sdca/sdca_functions.c | 2 +
sound/soc/sdca/sdca_interrupts.c | 439 +++++++++++++++++++++++++++++++
8 files changed, 564 insertions(+), 8 deletions(-)
create mode 100644 include/sound/sdca_interrupts.h
create mode 100644 sound/soc/sdca/sdca_interrupts.c
--
2.39.5
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 1/7] MAINTAINERS: Add SDCA maintainers entry
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-24 12:28 ` [PATCH v3 2/7] ASoC: SDCA: Add missing default in switch in entity_pde_event() Charles Keepax
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
Add a maintainers entry for the new SDCA support code.
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
MAINTAINERS | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index c3f7fbd0d67af..669b28f696915 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22298,6 +22298,17 @@ M: Jim Cromie <jim.cromie@gmail.com>
S: Maintained
F: drivers/clocksource/scx200_hrt.c
+SDCA LIBRARY AND CLASS DRIVER
+M: Charles Keepax <ckeepax@opensource.cirrus.com>
+M: Maciej Strozek <mstrozek@opensource.cirrus.com>
+R: Bard Liao <yung-chuan.liao@linux.intel.com>
+R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
+L: linux-sound@vger.kernel.org
+L: patches@opensource.cirrus.com
+S: Maintained
+F: include/sound/sdca*
+F: sound/soc/sdca/*
+
SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
M: Sascha Sommer <saschasommer@freenet.de>
L: sdricohcs-devel@lists.sourceforge.net (subscribers-only)
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 2/7] ASoC: SDCA: Add missing default in switch in entity_pde_event()
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
2025-06-24 12:28 ` [PATCH v3 1/7] MAINTAINERS: Add SDCA maintainers entry Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-24 12:28 ` [PATCH v3 3/7] ASoC: SDCA: Fixup some kernel doc errors Charles Keepax
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
The current code should be safe as the PDE widget only registers for the
two events handled in the switch statement. However, it is causing a
smatch warning and also is a little fragile to future code changes, add
a default case to avoid the warning and make the code more robust.
Fixes: 2c8b3a8e6aa8 ("ASoC: SDCA: Create DAPM widgets and routes from DisCo")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
sound/soc/sdca/sdca_asoc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index 7bc8f6069f3d4..e96e696cb1079 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -397,6 +397,8 @@ static int entity_pde_event(struct snd_soc_dapm_widget *widget,
from = widget->off_val;
to = widget->on_val;
break;
+ default:
+ return 0;
}
for (i = 0; i < entity->pde.num_max_delay; i++) {
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/7] ASoC: SDCA: Fixup some kernel doc errors
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
2025-06-24 12:28 ` [PATCH v3 1/7] MAINTAINERS: Add SDCA maintainers entry Charles Keepax
2025-06-24 12:28 ` [PATCH v3 2/7] ASoC: SDCA: Add missing default in switch in entity_pde_event() Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-24 12:28 ` [PATCH v3 4/7] ASoC: SDCA: Minor selected/detected mode control fixups Charles Keepax
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
Correct some typos and omissions in the kernel doc for the ASoC SDCA
code.
Fixes: 2c8b3a8e6aa8 ("ASoC: SDCA: Create DAPM widgets and routes from DisCo")
Reported-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
sound/soc/sdca/sdca_asoc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index e96e696cb1079..83911dab73ae2 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -93,6 +93,7 @@ static bool readonly_control(struct sdca_control *control)
/**
* sdca_asoc_count_component - count the various component parts
+ * @dev: Pointer to the device against which allocations will be done.
* @function: Pointer to the Function information.
* @num_widgets: Output integer pointer, will be filled with the
* required number of DAPM widgets for the Function.
@@ -997,7 +998,7 @@ static int populate_pin_switch(struct device *dev,
* sdca_asoc_populate_controls - fill in an array of ALSA controls for a Function
* @dev: Pointer to the device against which allocations will be done.
* @function: Pointer to the Function information.
- * @route: Array of ALSA controls to be populated.
+ * @kctl: Array of ALSA controls to be populated.
*
* This function populates an array of ALSA controls from the DisCo
* information for a particular SDCA Function. Typically,
@@ -1244,7 +1245,11 @@ EXPORT_SYMBOL_NS(sdca_asoc_populate_dais, "SND_SOC_SDCA");
* sdca_asoc_populate_component - fill in a component driver for a Function
* @dev: Pointer to the device against which allocations will be done.
* @function: Pointer to the Function information.
- * @copmonent_drv: Pointer to the component driver to be populated.
+ * @component_drv: Pointer to the component driver to be populated.
+ * @dai_drv: Pointer to the DAI driver array to be allocated and populated.
+ * @num_dai_drv: Pointer to integer that will be populated with the number of
+ * DAI drivers.
+ * @ops: DAI ops pointer that will be used for each DAI driver.
*
* This function populates a snd_soc_component_driver structure based
* on the DisCo information for a particular SDCA Function. It does
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 4/7] ASoC: SDCA: Minor selected/detected mode control fixups
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
` (2 preceding siblings ...)
2025-06-24 12:28 ` [PATCH v3 3/7] ASoC: SDCA: Fixup some kernel doc errors Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-24 12:28 ` [PATCH v3 5/7] ASoC: SDCA: Add flag for unused IRQs Charles Keepax
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
Make the names a slightly better match for the specification and add
some constants for the values rather than hard coding.
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
include/sound/sdca_function.h | 9 +++++++++
sound/soc/sdca/sdca_asoc.c | 8 ++++----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h
index 856b0f40ce5eb..4b278513597e5 100644
--- a/include/sound/sdca_function.h
+++ b/include/sound/sdca_function.h
@@ -319,6 +319,15 @@ enum sdca_selected_mode_range {
SDCA_SELECTED_MODE_NCOLS = 2,
};
+/**
+ * enum sdca_detected_mode_values - Predefined GE Detected Mode values
+ */
+enum sdca_detected_mode_values {
+ SDCA_DETECTED_MODE_JACK_UNPLUGGED = 0,
+ SDCA_DETECTED_MODE_JACK_UNKNOWN = 1,
+ SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS = 2,
+};
+
/**
* enum sdca_spe_controls - SDCA Controls for Security & Privacy Unit
*
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index 83911dab73ae2..dd7b19083c85f 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -246,12 +246,12 @@ static int entity_early_parse_ge(struct device *dev,
if (!values)
return -ENOMEM;
- texts[0] = "No Jack";
+ texts[0] = "Jack Unplugged";
texts[1] = "Jack Unknown";
texts[2] = "Detection in Progress";
- values[0] = 0;
- values[1] = 1;
- values[2] = 2;
+ values[0] = SDCA_DETECTED_MODE_JACK_UNPLUGGED;
+ values[1] = SDCA_DETECTED_MODE_JACK_UNKNOWN;
+ values[2] = SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS;
for (i = 0; i < range->rows; i++) {
enum sdca_terminal_type type;
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 5/7] ASoC: SDCA: Add flag for unused IRQs
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
` (3 preceding siblings ...)
2025-06-24 12:28 ` [PATCH v3 4/7] ASoC: SDCA: Minor selected/detected mode control fixups Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-24 12:28 ` [PATCH v3 6/7] ASoC: SDCA: Generic interrupt support Charles Keepax
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
Zero is a valid SDCA IRQ interrupt position so add a special value to
indicate that the IRQ is not used.
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
include/sound/sdca_function.h | 2 ++
sound/soc/sdca/sdca_functions.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h
index 4b278513597e5..b4a97ff087294 100644
--- a/include/sound/sdca_function.h
+++ b/include/sound/sdca_function.h
@@ -17,6 +17,8 @@ struct device;
struct sdca_entity;
struct sdca_function_desc;
+#define SDCA_NO_INTERRUPT -1
+
/*
* The addressing space for SDCA relies on 7 bits for Entities, so a
* maximum of 128 Entities per function can be represented.
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
index 093c681e93879..c34f3bf629833 100644
--- a/sound/soc/sdca/sdca_functions.c
+++ b/sound/soc/sdca/sdca_functions.c
@@ -912,6 +912,8 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
&tmp);
if (!ret)
control->interrupt_position = tmp;
+ else
+ control->interrupt_position = SDCA_NO_INTERRUPT;
control->label = find_sdca_control_label(dev, entity, control);
if (!control->label)
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 6/7] ASoC: SDCA: Generic interrupt support
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
` (4 preceding siblings ...)
2025-06-24 12:28 ` [PATCH v3 5/7] ASoC: SDCA: Add flag for unused IRQs Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-24 12:28 ` [PATCH v3 7/7] ASoC: SDCA: Add some initial IRQ handlers Charles Keepax
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
From: Maciej Strozek <mstrozek@opensource.cirrus.com>
Add a library supporting usage of SDCA interrupts, using regmap irq
framework. The library adds functions for parsing ACPI for
interrupt-related information, configuring irq chip and requesting
individual irqs. Calling code (SDCA function code) is expected to also
substitute the library's base irq handler for its own, appropriate
callback.
Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
include/sound/sdca_interrupts.h | 75 ++++++++
sound/soc/sdca/Kconfig | 7 +
sound/soc/sdca/Makefile | 5 +-
sound/soc/sdca/sdca_interrupts.c | 284 +++++++++++++++++++++++++++++++
4 files changed, 369 insertions(+), 2 deletions(-)
create mode 100644 include/sound/sdca_interrupts.h
create mode 100644 sound/soc/sdca/sdca_interrupts.c
diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
new file mode 100644
index 0000000000000..4cda8b75bae0e
--- /dev/null
+++ b/include/sound/sdca_interrupts.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ *
+ * Copyright (C) 2025 Cirrus Logic, Inc. and
+ * Cirrus Logic International Semiconductor Ltd.
+ */
+
+#ifndef __SDCA_INTERRUPTS_H__
+#define __SDCA_INTERRUPTS_H__
+
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+
+struct device;
+struct snd_soc_component;
+struct sdca_function_data;
+
+#define SDCA_MAX_INTERRUPTS 31 /* the last bit is reserved for future extensions */
+
+/**
+ * struct sdca_interrupt - contains information about a single SDCA interrupt
+ * @name: The name of the interrupt.
+ * @component: Pointer to the ASoC component owns the interrupt.
+ * @function: Pointer to the Function that the interrupt is associated with.
+ * @entity: Pointer to the Entity that the interrupt is associated with.
+ * @control: Pointer to the Control that the interrupt is associated with.
+ * @externally_requested: Internal flag used to check if a client driver has
+ * already requested the interrupt, for custom handling, allowing the core to
+ * skip handling this interrupt.
+ */
+struct sdca_interrupt {
+ const char *name;
+
+ struct snd_soc_component *component;
+ struct sdca_function_data *function;
+ struct sdca_entity *entity;
+ struct sdca_control *control;
+
+ bool externally_requested;
+};
+
+/**
+ * struct sdca_interrupt_info - contains top-level SDCA interrupt information
+ * @irq_chip: regmap irq chip structure.
+ * @irq_data: regmap irq chip data structure.
+ * @irqs: Array of data for each individual IRQ.
+ * @irq_lock: Protects access to the list of sdca_interrupt structures.
+ */
+struct sdca_interrupt_info {
+ struct regmap_irq_chip irq_chip;
+ struct regmap_irq_chip_data *irq_data;
+
+ struct sdca_interrupt irqs[SDCA_MAX_INTERRUPTS];
+
+ struct mutex irq_lock; /* Protect irqs list across functions */
+};
+
+int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info,
+ int sdca_irq, const char *name, irq_handler_t handler,
+ void *data);
+int sdca_irq_data_populate(struct snd_soc_component *component,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ struct sdca_control *control,
+ struct sdca_interrupt *interrupt);
+int sdca_irq_populate(struct sdca_function_data *function,
+ struct snd_soc_component *component,
+ struct sdca_interrupt_info *info);
+struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev,
+ struct regmap *regmap, int irq);
+
+#endif
diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig
index ec28855fe3b09..a633d5a0fea51 100644
--- a/sound/soc/sdca/Kconfig
+++ b/sound/soc/sdca/Kconfig
@@ -13,3 +13,10 @@ config SND_SOC_SDCA_OPTIONAL
config SND_SOC_SDCA_HID
tristate "SDCA HID support"
depends on SND_SOC_SDCA && HID
+
+config SND_SOC_SDCA_IRQ
+ tristate
+ select REGMAP
+ select REGMAP_IRQ
+ help
+ This option enables support for SDCA IRQs.
diff --git a/sound/soc/sdca/Makefile b/sound/soc/sdca/Makefile
index 9af46e7edfd2a..2a3938d11ca90 100644
--- a/sound/soc/sdca/Makefile
+++ b/sound/soc/sdca/Makefile
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
snd-soc-sdca-y := sdca_functions.o sdca_device.o sdca_regmap.o sdca_asoc.o
-
snd-soc-sdca-hid-y := sdca_hid.o
+snd-soc-sdca-irq-y := sdca_interrupts.o
-obj-$(CONFIG_SND_SOC_SDCA_HID) += snd-soc-sdca-hid.o
obj-$(CONFIG_SND_SOC_SDCA) += snd-soc-sdca.o
+obj-$(CONFIG_SND_SOC_SDCA_HID) += snd-soc-sdca-hid.o
+obj-$(CONFIG_SND_SOC_SDCA_IRQ) += snd-soc-sdca-irq.o
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
new file mode 100644
index 0000000000000..7272d11cb6d49
--- /dev/null
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2025 Cirrus Logic, Inc. and
+// Cirrus Logic International Semiconductor Ltd.
+
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ */
+
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/sdca.h>
+#include <sound/sdca_function.h>
+#include <sound/sdca_interrupts.h>
+#include <sound/soc-component.h>
+
+#define IRQ_SDCA(number) REGMAP_IRQ_REG(number, ((number) / BITS_PER_BYTE), \
+ SDW_SCP_SDCA_INTMASK_SDCA_##number)
+
+static const struct regmap_irq regmap_irqs[SDCA_MAX_INTERRUPTS] = {
+ IRQ_SDCA(0),
+ IRQ_SDCA(1),
+ IRQ_SDCA(2),
+ IRQ_SDCA(3),
+ IRQ_SDCA(4),
+ IRQ_SDCA(5),
+ IRQ_SDCA(6),
+ IRQ_SDCA(7),
+ IRQ_SDCA(8),
+ IRQ_SDCA(9),
+ IRQ_SDCA(10),
+ IRQ_SDCA(11),
+ IRQ_SDCA(12),
+ IRQ_SDCA(13),
+ IRQ_SDCA(14),
+ IRQ_SDCA(15),
+ IRQ_SDCA(16),
+ IRQ_SDCA(17),
+ IRQ_SDCA(18),
+ IRQ_SDCA(19),
+ IRQ_SDCA(20),
+ IRQ_SDCA(21),
+ IRQ_SDCA(22),
+ IRQ_SDCA(23),
+ IRQ_SDCA(24),
+ IRQ_SDCA(25),
+ IRQ_SDCA(26),
+ IRQ_SDCA(27),
+ IRQ_SDCA(28),
+ IRQ_SDCA(29),
+ IRQ_SDCA(30),
+};
+
+static const struct regmap_irq_chip sdca_irq_chip = {
+ .name = "sdca_irq",
+
+ .status_base = SDW_SCP_SDCA_INT1,
+ .unmask_base = SDW_SCP_SDCA_INTMASK1,
+ .ack_base = SDW_SCP_SDCA_INT1,
+ .num_regs = 4,
+
+ .irqs = regmap_irqs,
+ .num_irqs = SDCA_MAX_INTERRUPTS,
+
+ .runtime_pm = true,
+};
+
+static irqreturn_t base_handler(int irq, void *data)
+{
+ struct sdca_interrupt *interrupt = data;
+ struct device *dev = interrupt->component->dev;
+
+ dev_info(dev, "%s irq without full handling\n", interrupt->name);
+
+ return IRQ_HANDLED;
+}
+
+static int sdca_irq_request_locked(struct device *dev,
+ struct sdca_interrupt_info *info,
+ int sdca_irq, const char *name,
+ irq_handler_t handler, void *data)
+{
+ int irq;
+ int ret;
+
+ irq = regmap_irq_get_virq(info->irq_data, sdca_irq);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, handler,
+ IRQF_ONESHOT, name, data);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "requested irq %d for %s\n", irq, name);
+
+ return 0;
+}
+
+/**
+ * sdca_request_irq - request an individual SDCA interrupt
+ * @dev: Pointer to the struct device against which things should be allocated.
+ * @interrupt_info: Pointer to the interrupt information structure.
+ * @sdca_irq: SDCA interrupt position.
+ * @name: Name to be given to the IRQ.
+ * @handler: A callback thread function to be called for the IRQ.
+ * @data: Private data pointer that will be passed to the handler.
+ *
+ * Typically this is handled internally by sdca_irq_populate, however if
+ * a device requires custom IRQ handling this can be called manually before
+ * calling sdca_irq_populate, which will then skip that IRQ whilst processing.
+ *
+ * Return: Zero on success, and a negative error code on failure.
+ */
+int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *info,
+ int sdca_irq, const char *name, irq_handler_t handler,
+ void *data)
+{
+ int ret;
+
+ if (sdca_irq < 0 || sdca_irq > SDCA_MAX_INTERRUPTS) {
+ dev_err(dev, "bad irq request: %d\n", sdca_irq);
+ return -EINVAL;
+ }
+
+ guard(mutex)(&info->irq_lock);
+
+ ret = sdca_irq_request_locked(dev, info, sdca_irq, name, handler, data);
+ if (ret) {
+ dev_err(dev, "failed to request irq %s: %d\n", name, ret);
+ return ret;
+ }
+
+ info->irqs[sdca_irq].externally_requested = true;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA_IRQ");
+
+/**
+ * sdca_irq_data_populate - Populate common interrupt data
+ * @component: Pointer to the ASoC component for the Function.
+ * @function: Pointer to the SDCA Function.
+ * @entity: Pointer to the SDCA Entity.
+ * @control: Pointer to the SDCA Control.
+ * @interrupt: Pointer to the SDCA interrupt for this IRQ.
+ *
+ * Return: Zero on success, and a negative error code on failure.
+ */
+int sdca_irq_data_populate(struct snd_soc_component *component,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ struct sdca_control *control,
+ struct sdca_interrupt *interrupt)
+{
+ struct device *dev = component->dev;
+ const char *name;
+
+ name = devm_kasprintf(dev, GFP_KERNEL, "%s %s %s", function->desc->name,
+ entity->label, control->label);
+ if (!name)
+ return -ENOMEM;
+
+ interrupt->name = name;
+ interrupt->component = component;
+ interrupt->function = function;
+ interrupt->entity = entity;
+ interrupt->control = control;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_irq_data_populate, "SND_SOC_SDCA_IRQ");
+
+/**
+ * sdca_irq_populate - Request all the individual IRQs for an SDCA Function
+ * @function: Pointer to the SDCA Function.
+ * @component: Pointer to the ASoC component for the Function.
+ * @info: Pointer to the SDCA interrupt info for this device.
+ *
+ * Typically this would be called from the driver for a single SDCA Function.
+ *
+ * Return: Zero on success, and a negative error code on failure.
+ */
+int sdca_irq_populate(struct sdca_function_data *function,
+ struct snd_soc_component *component,
+ struct sdca_interrupt_info *info)
+{
+ struct device *dev = component->dev;
+ int i, j;
+
+ guard(mutex)(&info->irq_lock);
+
+ for (i = 0; i < function->num_entities; i++) {
+ struct sdca_entity *entity = &function->entities[i];
+
+ for (j = 0; j < entity->num_controls; j++) {
+ struct sdca_control *control = &entity->controls[j];
+ int irq = control->interrupt_position;
+ struct sdca_interrupt *interrupt;
+ const char *name;
+ int ret;
+
+ if (irq == SDCA_NO_INTERRUPT) {
+ continue;
+ } else if (irq < 0 || irq >= SDCA_MAX_INTERRUPTS) {
+ dev_err(dev, "bad irq position: %d\n", irq);
+ return -EINVAL;
+ }
+
+ interrupt = &info->irqs[irq];
+
+ if (interrupt->externally_requested) {
+ dev_dbg(dev,
+ "skipping irq %d, externally requested\n",
+ irq);
+ continue;
+ }
+
+ ret = sdca_irq_data_populate(component, function, entity,
+ control, interrupt);
+ if (ret)
+ return ret;
+
+ ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
+ base_handler, interrupt);
+ if (ret) {
+ dev_err(dev, "failed to request irq %s: %d\n",
+ name, ret);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA_IRQ");
+
+/**
+ * sdca_irq_allocate - allocate an SDCA interrupt structure for a device
+ * @dev: Device pointer against which things should be allocated.
+ * @regmap: regmap to be used for accessing the SDCA IRQ registers.
+ * @irq: The interrupt number.
+ *
+ * Typically this would be called from the top level driver for the whole
+ * SDCA device, as only a single instance is required across all Functions
+ * on the device.
+ *
+ * Return: A pointer to the allocated sdca_interrupt_info struct, or an
+ * error code.
+ */
+struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev,
+ struct regmap *regmap, int irq)
+{
+ struct sdca_interrupt_info *info;
+ int ret;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return ERR_PTR(-ENOMEM);
+
+ info->irq_chip = sdca_irq_chip;
+
+ devm_mutex_init(dev, &info->irq_lock);
+
+ ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT, 0,
+ &info->irq_chip, &info->irq_data);
+ if (ret) {
+ dev_err(dev, "failed to register irq chip: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ dev_dbg(dev, "registered on irq %d\n", irq);
+
+ return info;
+}
+EXPORT_SYMBOL_NS_GPL(sdca_irq_allocate, "SND_SOC_SDCA_IRQ");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SDCA IRQ library");
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 7/7] ASoC: SDCA: Add some initial IRQ handlers
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
` (5 preceding siblings ...)
2025-06-24 12:28 ` [PATCH v3 6/7] ASoC: SDCA: Generic interrupt support Charles Keepax
@ 2025-06-24 12:28 ` Charles Keepax
2025-06-26 12:00 ` [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Pierre-Louis Bossart
2025-07-01 23:34 ` Mark Brown
8 siblings, 0 replies; 10+ messages in thread
From: Charles Keepax @ 2025-06-24 12:28 UTC (permalink / raw)
To: broonie
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
Add basic IRQ handlers for the function status and jack detection
interrupts.
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No change since v2.
include/sound/sdca_interrupts.h | 3 +
sound/soc/sdca/sdca_interrupts.c | 157 ++++++++++++++++++++++++++++++-
2 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
index 4cda8b75bae0e..bbbc3ab27ebae 100644
--- a/include/sound/sdca_interrupts.h
+++ b/include/sound/sdca_interrupts.h
@@ -27,6 +27,7 @@ struct sdca_function_data;
* @function: Pointer to the Function that the interrupt is associated with.
* @entity: Pointer to the Entity that the interrupt is associated with.
* @control: Pointer to the Control that the interrupt is associated with.
+ * @priv: Pointer to private data for use by the handler.
* @externally_requested: Internal flag used to check if a client driver has
* already requested the interrupt, for custom handling, allowing the core to
* skip handling this interrupt.
@@ -39,6 +40,8 @@ struct sdca_interrupt {
struct sdca_entity *entity;
struct sdca_control *control;
+ void *priv;
+
bool externally_requested;
};
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 7272d11cb6d49..edb045c7ebb08 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -7,6 +7,7 @@
* https://www.mipi.org/mipi-sdca-v1-0-download
*/
+#include <linux/bitmap.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/device.h>
@@ -18,6 +19,7 @@
#include <sound/sdca_function.h>
#include <sound/sdca_interrupts.h>
#include <sound/soc-component.h>
+#include <sound/soc.h>
#define IRQ_SDCA(number) REGMAP_IRQ_REG(number, ((number) / BITS_PER_BYTE), \
SDW_SCP_SDCA_INTMASK_SDCA_##number)
@@ -80,6 +82,143 @@ static irqreturn_t base_handler(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t function_status_handler(int irq, void *data)
+{
+ struct sdca_interrupt *interrupt = data;
+ struct device *dev = interrupt->component->dev;
+ unsigned int reg, val;
+ unsigned long status;
+ unsigned int mask;
+ int ret;
+
+ reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id,
+ interrupt->control->sel, 0);
+
+ ret = regmap_read(interrupt->component->regmap, reg, &val);
+ if (ret < 0) {
+ dev_err(dev, "failed to read function status: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ dev_dbg(dev, "function status: %#x\n", val);
+
+ status = val;
+ for_each_set_bit(mask, &status, BITS_PER_BYTE) {
+ mask = 1 << mask;
+
+ switch (mask) {
+ case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION:
+ //FIXME: Add init writes
+ break;
+ case SDCA_CTL_ENTITY_0_FUNCTION_FAULT:
+ dev_err(dev, "function fault\n");
+ break;
+ case SDCA_CTL_ENTITY_0_UMP_SEQUENCE_FAULT:
+ dev_err(dev, "ump sequence fault\n");
+ break;
+ case SDCA_CTL_ENTITY_0_FUNCTION_BUSY:
+ dev_info(dev, "unexpected function busy\n");
+ break;
+ case SDCA_CTL_ENTITY_0_DEVICE_NEWLY_ATTACHED:
+ case SDCA_CTL_ENTITY_0_INTS_DISABLED_ABNORMALLY:
+ case SDCA_CTL_ENTITY_0_STREAMING_STOPPED_ABNORMALLY:
+ case SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET:
+ break;
+ }
+ }
+
+ ret = regmap_write(interrupt->component->regmap, reg, val);
+ if (ret < 0) {
+ dev_err(dev, "failed to clear function status: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t detected_mode_handler(int irq, void *data)
+{
+ struct sdca_interrupt *interrupt = data;
+ struct snd_soc_component *component = interrupt->component;
+ struct device *dev = component->dev;
+ struct snd_soc_card *card = component->card;
+ struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem;
+ struct snd_kcontrol *kctl = interrupt->priv;
+ struct snd_ctl_elem_value ucontrol;
+ struct soc_enum *soc_enum;
+ unsigned int reg, val;
+ int ret;
+
+ if (!kctl) {
+ const char *name __free(kfree) = kasprintf(GFP_KERNEL, "%s %s",
+ interrupt->entity->label,
+ SDCA_CTL_SELECTED_MODE_NAME);
+
+ if (!name)
+ return -ENOMEM;
+
+ kctl = snd_soc_component_get_kcontrol(component, name);
+ if (!kctl) {
+ dev_dbg(dev, "control not found: %s\n", name);
+ return IRQ_NONE;
+ }
+
+ interrupt->priv = kctl;
+ }
+
+ soc_enum = (struct soc_enum *)kctl->private_value;
+
+ reg = SDW_SDCA_CTL(interrupt->function->desc->adr, interrupt->entity->id,
+ interrupt->control->sel, 0);
+
+ ret = regmap_read(component->regmap, reg, &val);
+ if (ret < 0) {
+ dev_err(dev, "failed to read detected mode: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ switch (val) {
+ case SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS:
+ case SDCA_DETECTED_MODE_JACK_UNKNOWN:
+ reg = SDW_SDCA_CTL(interrupt->function->desc->adr,
+ interrupt->entity->id,
+ SDCA_CTL_GE_SELECTED_MODE, 0);
+
+ /*
+ * Selected mode is not normally marked as volatile register
+ * (RW), but here force a read from the hardware. If the
+ * detected mode is unknown we need to see what the device
+ * selected as a "safe" option.
+ */
+ regcache_drop_region(component->regmap, reg, reg);
+
+ ret = regmap_read(component->regmap, reg, &val);
+ if (ret) {
+ dev_err(dev, "failed to re-check selected mode: %d\n", ret);
+ return IRQ_NONE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ dev_dbg(dev, "%s: %#x\n", interrupt->name, val);
+
+ ucontrol.value.enumerated.item[0] = snd_soc_enum_val_to_item(soc_enum, val);
+
+ down_write(rwsem);
+ ret = kctl->put(kctl, &ucontrol);
+ up_write(rwsem);
+ if (ret < 0) {
+ dev_err(dev, "failed to update selected mode: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ snd_ctl_notify(card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+
+ return IRQ_HANDLED;
+}
+
static int sdca_irq_request_locked(struct device *dev,
struct sdca_interrupt_info *info,
int sdca_irq, const char *name,
@@ -202,6 +341,7 @@ int sdca_irq_populate(struct sdca_function_data *function,
struct sdca_control *control = &entity->controls[j];
int irq = control->interrupt_position;
struct sdca_interrupt *interrupt;
+ irq_handler_t handler;
const char *name;
int ret;
@@ -226,8 +366,23 @@ int sdca_irq_populate(struct sdca_function_data *function,
if (ret)
return ret;
+ handler = base_handler;
+
+ switch (entity->type) {
+ case SDCA_ENTITY_TYPE_ENTITY_0:
+ if (control->sel == SDCA_CTL_ENTITY_0_FUNCTION_STATUS)
+ handler = function_status_handler;
+ break;
+ case SDCA_ENTITY_TYPE_GE:
+ if (control->sel == SDCA_CTL_GE_DETECTED_MODE)
+ handler = detected_mode_handler;
+ break;
+ default:
+ break;
+ }
+
ret = sdca_irq_request_locked(dev, info, irq, interrupt->name,
- base_handler, interrupt);
+ handler, interrupt);
if (ret) {
dev_err(dev, "failed to request irq %s: %d\n",
name, ret);
--
2.39.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
` (6 preceding siblings ...)
2025-06-24 12:28 ` [PATCH v3 7/7] ASoC: SDCA: Add some initial IRQ handlers Charles Keepax
@ 2025-06-26 12:00 ` Pierre-Louis Bossart
2025-07-01 23:34 ` Mark Brown
8 siblings, 0 replies; 10+ messages in thread
From: Pierre-Louis Bossart @ 2025-06-26 12:00 UTC (permalink / raw)
To: Charles Keepax, broonie
Cc: lgirdwood, yung-chuan.liao, peter.ujfalusi, patches, linux-sound
On 6/24/25 14:28, Charles Keepax wrote:
> Add a maintainers entry for SDCA, do a couple of small fixups for
> previous chains, and then adding the beginnings of the SDCA IRQ
> handling. This is based around a regmap IRQ chip and a few helper
> functions that can be called from the client drivers to setup the
> IRQs.
>
> Thanks,
> Charles
>
> Changes since v2:
> - Just a rebase to avoid a conflict with the recently merged SDCA HID
> stuff.
For the series:
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
> Charles Keepax (6):
> MAINTAINERS: Add SDCA maintainers entry
> ASoC: SDCA: Add missing default in switch in entity_pde_event()
> ASoC: SDCA: Fixup some kernel doc errors
> ASoC: SDCA: Minor selected/detected mode control fixups
> ASoC: SDCA: Add flag for unused IRQs
> ASoC: SDCA: Add some initial IRQ handlers
>
> Maciej Strozek (1):
> ASoC: SDCA: Generic interrupt support
>
> MAINTAINERS | 11 +
> include/sound/sdca_function.h | 11 +
> include/sound/sdca_interrupts.h | 78 ++++++
> sound/soc/sdca/Kconfig | 7 +
> sound/soc/sdca/Makefile | 5 +-
> sound/soc/sdca/sdca_asoc.c | 19 +-
> sound/soc/sdca/sdca_functions.c | 2 +
> sound/soc/sdca/sdca_interrupts.c | 439 +++++++++++++++++++++++++++++++
> 8 files changed, 564 insertions(+), 8 deletions(-)
> create mode 100644 include/sound/sdca_interrupts.h
> create mode 100644 sound/soc/sdca/sdca_interrupts.c
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
` (7 preceding siblings ...)
2025-06-26 12:00 ` [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Pierre-Louis Bossart
@ 2025-07-01 23:34 ` Mark Brown
8 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2025-07-01 23:34 UTC (permalink / raw)
To: Charles Keepax
Cc: lgirdwood, yung-chuan.liao, pierre-louis.bossart, peter.ujfalusi,
patches, linux-sound
On Tue, 24 Jun 2025 13:28:37 +0100, Charles Keepax wrote:
> Add a maintainers entry for SDCA, do a couple of small fixups for
> previous chains, and then adding the beginnings of the SDCA IRQ
> handling. This is based around a regmap IRQ chip and a few helper
> functions that can be called from the client drivers to setup the
> IRQs.
>
> Thanks,
> Charles
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/7] MAINTAINERS: Add SDCA maintainers entry
commit: 0383a710d28dd5dc43d26ccf9fc74e1ba41868fd
[2/7] ASoC: SDCA: Add missing default in switch in entity_pde_event()
commit: 2ed526bf04a6d81592b314f81e7719a14048f732
[3/7] ASoC: SDCA: Fixup some kernel doc errors
commit: b4515fd87cc9a260ae89fb81ca2aa928d496ac86
[4/7] ASoC: SDCA: Minor selected/detected mode control fixups
commit: 37d2aa62138daa8ecb6442ae4753704e9c92346f
[5/7] ASoC: SDCA: Add flag for unused IRQs
commit: 775f5729b47d8737f4f98e0141f61b3358245398
[6/7] ASoC: SDCA: Generic interrupt support
commit: b126394d9ec6f9d8322cf392ba23d4a5f96faf5a
[7/7] ASoC: SDCA: Add some initial IRQ handlers
commit: b9ab3b61824190b1c6b2c59e7ba4de591f24eb92
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-07-01 23:34 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-24 12:28 [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Charles Keepax
2025-06-24 12:28 ` [PATCH v3 1/7] MAINTAINERS: Add SDCA maintainers entry Charles Keepax
2025-06-24 12:28 ` [PATCH v3 2/7] ASoC: SDCA: Add missing default in switch in entity_pde_event() Charles Keepax
2025-06-24 12:28 ` [PATCH v3 3/7] ASoC: SDCA: Fixup some kernel doc errors Charles Keepax
2025-06-24 12:28 ` [PATCH v3 4/7] ASoC: SDCA: Minor selected/detected mode control fixups Charles Keepax
2025-06-24 12:28 ` [PATCH v3 5/7] ASoC: SDCA: Add flag for unused IRQs Charles Keepax
2025-06-24 12:28 ` [PATCH v3 6/7] ASoC: SDCA: Generic interrupt support Charles Keepax
2025-06-24 12:28 ` [PATCH v3 7/7] ASoC: SDCA: Add some initial IRQ handlers Charles Keepax
2025-06-26 12:00 ` [PATCH v3 0/7] Add SDCA IRQ support and some misc fixups Pierre-Louis Bossart
2025-07-01 23:34 ` Mark Brown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.