summaryrefslogtreecommitdiff
path: root/include/sound
diff options
context:
space:
mode:
Diffstat (limited to 'include/sound')
-rw-r--r--include/sound/asoundef.h9
-rw-r--r--include/sound/cs-amp-lib.h25
-rw-r--r--include/sound/cs35l56.h50
-rw-r--r--include/sound/sdca.h19
-rw-r--r--include/sound/sdca_fdl.h105
-rw-r--r--include/sound/sdca_function.h126
-rw-r--r--include/sound/sdca_hid.h21
-rw-r--r--include/sound/sdca_interrupts.h19
-rw-r--r--include/sound/sdca_regmap.h2
-rw-r--r--include/sound/sdca_ump.h50
-rw-r--r--include/sound/soc-acpi-intel-match.h2
-rw-r--r--include/sound/soc-acpi.h8
-rw-r--r--include/sound/soc.h39
-rw-r--r--include/sound/soc_sdw_utils.h19
-rw-r--r--include/sound/tas2781.h8
15 files changed, 462 insertions, 40 deletions
diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
index 09b2c3dffb30..c4a929d4fd51 100644
--- a/include/sound/asoundef.h
+++ b/include/sound/asoundef.h
@@ -12,6 +12,15 @@
* Digital audio interface *
* *
****************************************************************************/
+/* IEC958 subframe format */
+#define IEC958_SUBFRAME_PREAMBLE_MASK (0xfU)
+#define IEC958_SUBFRAME_AUXILIARY_MASK (0xfU << 4)
+#define IEC958_SUBFRAME_SAMPLE_24_MASK (0xffffffU << 4)
+#define IEC958_SUBFRAME_SAMPLE_20_MASK (0xfffffU << 8)
+#define IEC958_SUBFRAME_VALIDITY (0x1U << 28)
+#define IEC958_SUBFRAME_USER_DATA (0x1U << 29)
+#define IEC958_SUBFRAME_CHANNEL_STATUS (0x1U << 30)
+#define IEC958_SUBFRAME_PARITY (0x1U << 31)
/* AES/IEC958 channel status bits */
#define IEC958_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
diff --git a/include/sound/cs-amp-lib.h b/include/sound/cs-amp-lib.h
index 43a87a39110c..61e00017c9aa 100644
--- a/include/sound/cs-amp-lib.h
+++ b/include/sound/cs-amp-lib.h
@@ -47,21 +47,44 @@ struct cirrus_amp_cal_controls {
int cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
const struct cirrus_amp_cal_controls *controls,
const struct cirrus_amp_cal_data *data);
+int cs_amp_read_cal_coeffs(struct cs_dsp *dsp,
+ const struct cirrus_amp_cal_controls *controls,
+ struct cirrus_amp_cal_data *data);
+int cs_amp_write_ambient_temp(struct cs_dsp *dsp,
+ const struct cirrus_amp_cal_controls *controls,
+ u32 temp);
int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index,
struct cirrus_amp_cal_data *out_data);
+int cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, int num_amps,
+ const struct cirrus_amp_cal_data *in_data);
int cs_amp_get_vendor_spkid(struct device *dev);
+struct dentry *cs_amp_create_debugfs(struct device *dev);
+
+static inline u64 cs_amp_cal_target_u64(const struct cirrus_amp_cal_data *data)
+{
+ return ((u64)data->calTarget[1] << 32) | data->calTarget[0];
+}
struct cs_amp_test_hooks {
efi_status_t (*get_efi_variable)(efi_char16_t *name,
efi_guid_t *guid,
+ u32 *returned_attr,
unsigned long *size,
void *buf);
+ efi_status_t (*set_efi_variable)(efi_char16_t *name,
+ efi_guid_t *guid,
+ u32 attr,
+ unsigned long size,
+ void *buf);
int (*write_cal_coeff)(struct cs_dsp *dsp,
const struct cirrus_amp_cal_controls *controls,
const char *ctl_name, u32 val);
-};
+ int (*read_cal_coeff)(struct cs_dsp *dsp,
+ const struct cirrus_amp_cal_controls *controls,
+ const char *ctl_name, u32 *val);
+};
extern const struct cs_amp_test_hooks * const cs_amp_test_hooks;
#endif /* CS_AMP_LIB_H */
diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h
index ab044ce2aa8b..5928af539c46 100644
--- a/include/sound/cs35l56.h
+++ b/include/sound/cs35l56.h
@@ -9,12 +9,15 @@
#ifndef __CS35L56_H
#define __CS35L56_H
+#include <linux/debugfs.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/cs-amp-lib.h>
+struct snd_ctl_elem_value;
+
#define CS35L56_DEVID 0x0000000
#define CS35L56_REVID 0x0000004
#define CS35L56_RELID 0x000000C
@@ -62,6 +65,8 @@
#define CS35L56_IRQ1_MASK_8 0x000E0AC
#define CS35L56_IRQ1_MASK_18 0x000E0D4
#define CS35L56_IRQ1_MASK_20 0x000E0DC
+#define CS35L56_MIXER_NGATE_CH1_CFG 0x0010004
+#define CS35L56_MIXER_NGATE_CH2_CFG 0x0010008
#define CS35L56_DSP_MBOX_1_RAW 0x0011000
#define CS35L56_DSP_VIRTUAL1_MBOX_1 0x0011020
#define CS35L56_DSP_VIRTUAL1_MBOX_2 0x0011024
@@ -177,6 +182,9 @@
/* IRQ1_EINT_8 */
#define CS35L56_TEMP_ERR_EINT1_MASK 0x80000000
+/* MIXER_NGATE_CHn_CFG */
+#define CS35L56_AUX_NGATE_CHn_EN 0x00000001
+
/* Mixer input sources */
#define CS35L56_INPUT_SRC_NONE 0x00
#define CS35L56_INPUT_SRC_ASP1RX1 0x08
@@ -243,6 +251,7 @@
#define CS35L56_MBOX_CMD_AUDIO_PLAY 0x0B000001
#define CS35L56_MBOX_CMD_AUDIO_PAUSE 0x0B000002
#define CS35L56_MBOX_CMD_AUDIO_REINIT 0x0B000003
+#define CS35L56_MBOX_CMD_AUDIO_CALIBRATION 0x0B000006
#define CS35L56_MBOX_CMD_HIBERNATE_NOW 0x02000001
#define CS35L56_MBOX_CMD_WAKEUP 0x02000002
#define CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE 0x02000003
@@ -258,12 +267,22 @@
#define CS35L56_PS3_POLL_US 500
#define CS35L56_PS3_TIMEOUT_US 300000
+#define CS35L56_CAL_STATUS_SUCCESS 1
+#define CS35L56_CAL_STATUS_OUT_OF_RANGE 3
+
+#define CS35L56_CAL_SET_STATUS_UNKNOWN 0
+#define CS35L56_CAL_SET_STATUS_DEFAULT 1
+#define CS35L56_CAL_SET_STATUS_SET 2
+
#define CS35L56_CONTROL_PORT_READY_US 2200
#define CS35L56_HALO_STATE_POLL_US 1000
#define CS35L56_HALO_STATE_TIMEOUT_US 250000
#define CS35L56_RESET_PULSE_MIN_US 1100
#define CS35L56_WAKE_HOLD_TIME_US 1000
+#define CS35L56_CALIBRATION_POLL_US (100 * USEC_PER_MSEC)
+#define CS35L56_CALIBRATION_TIMEOUT_US (5 * USEC_PER_SEC)
+
#define CS35L56_SDW1_PLAYBACK_PORT 1
#define CS35L56_SDW1_CAPTURE_PORT 3
@@ -291,9 +310,16 @@ struct cs35l56_fw_reg {
unsigned int posture_number;
};
+struct cs35l56_cal_debugfs_fops {
+ const struct debugfs_short_fops calibrate;
+ const struct debugfs_short_fops cal_temperature;
+ const struct debugfs_short_fops cal_data;
+};
+
struct cs35l56_base {
struct device *dev;
struct regmap *regmap;
+ struct cs_dsp *dsp;
int irq;
struct mutex irq_lock;
u8 type;
@@ -304,11 +330,14 @@ struct cs35l56_base {
bool can_hibernate;
bool cal_data_valid;
s8 cal_index;
+ u8 num_amps;
struct cirrus_amp_cal_data cal_data;
struct gpio_desc *reset_gpio;
struct cs35l56_spi_payload *spi_payload_buf;
const struct cs35l56_fw_reg *fw_reg;
const struct cirrus_amp_cal_controls *calibration_controls;
+ struct dentry *debugfs;
+ u64 silicon_uid;
};
static inline bool cs35l56_is_otp_register(unsigned int reg)
@@ -340,6 +369,7 @@ extern const struct regmap_config cs35l63_regmap_i2c;
extern const struct regmap_config cs35l63_regmap_sdw;
extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls;
+extern const char * const cs35l56_cal_set_status_text[3];
extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC];
extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC];
@@ -358,8 +388,28 @@ int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base);
int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire);
void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp);
int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base);
+int cs35l56_stash_calibration(struct cs35l56_base *cs35l56_base,
+ const struct cirrus_amp_cal_data *data);
+ssize_t cs35l56_calibrate_debugfs_write(struct cs35l56_base *cs35l56_base,
+ const char __user *from, size_t count,
+ loff_t *ppos);
+ssize_t cs35l56_cal_ambient_debugfs_write(struct cs35l56_base *cs35l56_base,
+ const char __user *from, size_t count,
+ loff_t *ppos);
+ssize_t cs35l56_cal_data_debugfs_read(struct cs35l56_base *cs35l56_base,
+ char __user *to, size_t count,
+ loff_t *ppos);
+ssize_t cs35l56_cal_data_debugfs_write(struct cs35l56_base *cs35l56_base,
+ const char __user *from, size_t count,
+ loff_t *ppos);
+void cs35l56_create_cal_debugfs(struct cs35l56_base *cs35l56_base,
+ const struct cs35l56_cal_debugfs_fops *fops);
+void cs35l56_remove_cal_debugfs(struct cs35l56_base *cs35l56_base);
+int cs35l56_cal_set_status_get(struct cs35l56_base *cs35l56_base,
+ struct snd_ctl_elem_value *uvalue);
int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base,
bool *fw_missing, unsigned int *fw_version);
+void cs35l56_warn_if_firmware_missing(struct cs35l56_base *cs35l56_base);
void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp);
int cs35l56_hw_init(struct cs35l56_base *cs35l56_base);
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base);
diff --git a/include/sound/sdca.h b/include/sound/sdca.h
index 9c6a351c9d47..67ff3c88705d 100644
--- a/include/sound/sdca.h
+++ b/include/sound/sdca.h
@@ -12,19 +12,24 @@
#include <linux/types.h>
#include <linux/kconfig.h>
+struct acpi_table_swft;
+struct fwnode_handle;
struct sdw_slave;
+struct sdca_dev;
#define SDCA_MAX_FUNCTION_COUNT 8
/**
* struct sdca_function_desc - short descriptor for an SDCA Function
* @node: firmware node for the Function.
+ * @func_dev: pointer to SDCA function device.
* @name: Human-readable string.
* @type: Function topology type.
* @adr: ACPI address (used for SDCA register access).
*/
struct sdca_function_desc {
struct fwnode_handle *node;
+ struct sdca_dev *func_dev;
const char *name;
u32 type;
u8 adr;
@@ -37,11 +42,13 @@ struct sdca_function_desc {
* @num_functions: Total number of supported SDCA functions. Invalid/unsupported
* functions will be skipped.
* @function: Array of function descriptors.
+ * @swft: Pointer to the SWFT table, if available.
*/
struct sdca_device_data {
u32 interface_revision;
int num_functions;
struct sdca_function_desc function[SDCA_MAX_FUNCTION_COUNT];
+ struct acpi_table_swft *swft;
};
enum sdca_quirk {
@@ -52,17 +59,29 @@ enum sdca_quirk {
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)
void sdca_lookup_functions(struct sdw_slave *slave);
+void sdca_lookup_swft(struct sdw_slave *slave);
void sdca_lookup_interface_revision(struct sdw_slave *slave);
bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk);
+int sdca_dev_register_functions(struct sdw_slave *slave);
+void sdca_dev_unregister_functions(struct sdw_slave *slave);
#else
static inline void sdca_lookup_functions(struct sdw_slave *slave) {}
+static inline void sdca_lookup_swft(struct sdw_slave *slave) {}
static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {}
static inline bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
{
return false;
}
+
+static inline int sdca_dev_register_functions(struct sdw_slave *slave)
+{
+ return 0;
+}
+
+static inline void sdca_dev_unregister_functions(struct sdw_slave *slave) {}
+
#endif
#endif
diff --git a/include/sound/sdca_fdl.h b/include/sound/sdca_fdl.h
new file mode 100644
index 000000000000..fbaf4b384c8a
--- /dev/null
+++ b/include/sound/sdca_fdl.h
@@ -0,0 +1,105 @@
+/* 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_FDL_H__
+#define __SDCA_FDL_H__
+
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+
+struct device;
+struct regmap;
+struct sdca_fdl_set;
+struct sdca_function_data;
+struct sdca_interrupt;
+struct sdca_interrupt_info;
+
+/**
+ * struct fdl_state - FDL state structure to keep data between interrupts
+ * @begin: Completion indicating the start of an FDL download cycle.
+ * @done: Completion indicating the end of an FDL download cycle.
+ * @timeout: Delayed work used for timing out UMP transactions.
+ * @lock: Mutex to protect between the timeout work and IRQ handlers.
+ * @interrupt: Pointer to the interrupt struct to which this FDL is attached.
+ * @set: Pointer to the FDL set currently being downloaded.
+ * @file_index: Index of the current file being processed.
+ */
+struct fdl_state {
+ struct completion begin;
+ struct completion done;
+ struct delayed_work timeout;
+ struct mutex lock;
+
+ struct sdca_interrupt *interrupt;
+ struct sdca_fdl_set *set;
+ int file_index;
+};
+
+#define SDCA_CTL_XU_FDLH_COMPLETE 0
+#define SDCA_CTL_XU_FDLH_MORE_FILES SDCA_CTL_XU_FDLH_SET_IN_PROGRESS
+#define SDCA_CTL_XU_FDLH_FILE_AVAILABLE (SDCA_CTL_XU_FDLH_TRANSFERRED_FILE | \
+ SDCA_CTL_XU_FDLH_SET_IN_PROGRESS)
+#define SDCA_CTL_XU_FDLH_MASK (SDCA_CTL_XU_FDLH_TRANSFERRED_CHUNK | \
+ SDCA_CTL_XU_FDLH_TRANSFERRED_FILE | \
+ SDCA_CTL_XU_FDLH_SET_IN_PROGRESS | \
+ SDCA_CTL_XU_FDLH_RESET_ACK | \
+ SDCA_CTL_XU_FDLH_REQ_ABORT)
+
+#define SDCA_CTL_XU_FDLD_COMPLETE 0
+#define SDCA_CTL_XU_FDLD_FILE_OK (SDCA_CTL_XU_FDLH_TRANSFERRED_FILE | \
+ SDCA_CTL_XU_FDLH_SET_IN_PROGRESS | \
+ SDCA_CTL_XU_FDLD_ACK_TRANSFER | \
+ SDCA_CTL_XU_FDLD_NEEDS_SET)
+#define SDCA_CTL_XU_FDLD_MORE_FILES_OK (SDCA_CTL_XU_FDLH_SET_IN_PROGRESS | \
+ SDCA_CTL_XU_FDLD_ACK_TRANSFER | \
+ SDCA_CTL_XU_FDLD_NEEDS_SET)
+#define SDCA_CTL_XU_FDLD_MASK (SDCA_CTL_XU_FDLD_REQ_RESET | \
+ SDCA_CTL_XU_FDLD_REQ_ABORT | \
+ SDCA_CTL_XU_FDLD_ACK_TRANSFER | \
+ SDCA_CTL_XU_FDLD_NEEDS_SET)
+
+#if IS_ENABLED(CONFIG_SND_SOC_SDCA_FDL)
+
+int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt);
+int sdca_fdl_process(struct sdca_interrupt *interrupt);
+int sdca_fdl_sync(struct device *dev, struct sdca_function_data *function,
+ struct sdca_interrupt_info *info);
+
+int sdca_reset_function(struct device *dev, struct sdca_function_data *function,
+ struct regmap *regmap);
+
+#else
+
+static inline int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt)
+{
+ return 0;
+}
+
+static inline int sdca_fdl_process(struct sdca_interrupt *interrupt)
+{
+ return 0;
+}
+
+static inline int sdca_fdl_sync(struct device *dev,
+ struct sdca_function_data *function,
+ struct sdca_interrupt_info *info)
+{
+ return 0;
+}
+
+static inline int sdca_reset_function(struct device *dev,
+ struct sdca_function_data *function,
+ struct regmap *regmap)
+{
+ return 0;
+}
+
+#endif // CONFIG_SND_SOC_SDCA_FDL
+
+#endif // __SDCA_FDL_H__
diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h
index ea68856e4c8c..6e9391b3816c 100644
--- a/include/sound/sdca_function.h
+++ b/include/sound/sdca_function.h
@@ -13,6 +13,7 @@
#include <linux/types.h>
#include <linux/hid.h>
+struct acpi_table_swft;
struct device;
struct sdca_entity;
struct sdca_function_desc;
@@ -63,6 +64,7 @@ struct sdca_function_desc;
* @SDCA_FUNCTION_TYPE_RJ: Retaskable jack.
* @SDCA_FUNCTION_TYPE_SIMPLE_JACK: Subset of UAJ.
* @SDCA_FUNCTION_TYPE_HID: Human Interface Device, for e.g. buttons.
+ * @SDCA_FUNCTION_TYPE_COMPANION_AMP: Sources audio from another amp.
* @SDCA_FUNCTION_TYPE_IMP_DEF: Implementation-defined function.
*
* SDCA Function Types from SDCA specification v1.0a Section 5.1.2
@@ -82,6 +84,7 @@ enum sdca_function_type {
SDCA_FUNCTION_TYPE_RJ = 0x07,
SDCA_FUNCTION_TYPE_SIMPLE_JACK = 0x08,
SDCA_FUNCTION_TYPE_HID = 0x0A,
+ SDCA_FUNCTION_TYPE_COMPANION_AMP = 0x0B,
SDCA_FUNCTION_TYPE_IMP_DEF = 0x1F,
};
@@ -95,6 +98,7 @@ enum sdca_function_type {
#define SDCA_FUNCTION_TYPE_RJ_NAME "RJ"
#define SDCA_FUNCTION_TYPE_SIMPLE_NAME "SimpleJack"
#define SDCA_FUNCTION_TYPE_HID_NAME "HID"
+#define SDCA_FUNCTION_TYPE_COMPANION_AMP_NAME "CompanionAmp"
#define SDCA_FUNCTION_TYPE_IMP_DEF_NAME "ImplementationDefined"
/**
@@ -134,6 +138,32 @@ struct sdca_init_write {
SDCA_CTL_##ent##_##sel)
/**
+ * enum sdca_messageoffset_range - Column definitions UMP MessageOffset
+ */
+enum sdca_messageoffset_range {
+ SDCA_MESSAGEOFFSET_BUFFER_START_ADDRESS = 0,
+ SDCA_MESSAGEOFFSET_BUFFER_LENGTH = 1,
+ SDCA_MESSAGEOFFSET_UMP_MODE = 2,
+ SDCA_MESSAGEOFFSET_NCOLS = 3,
+};
+
+/**
+ * enum sdca_ump_mode - SDCA UMP Mode
+ */
+enum sdca_ump_mode {
+ SDCA_UMP_MODE_DIRECT = 0x00,
+ SDCA_UMP_MODE_INDIRECT = 0x01,
+};
+
+/**
+ * enum sdca_ump_owner - SDCA UMP Owner
+ */
+enum sdca_ump_owner {
+ SDCA_UMP_OWNER_HOST = 0x00,
+ SDCA_UMP_OWNER_DEVICE = 0x01,
+};
+
+/**
* enum sdca_it_controls - SDCA Controls for Input Terminal
*
* Control Selectors for Input Terminal from SDCA specification v1.0
@@ -258,6 +288,27 @@ enum sdca_xu_controls {
SDCA_CTL_XU_FDL_STATUS = 0x14,
SDCA_CTL_XU_FDL_SET_INDEX = 0x15,
SDCA_CTL_XU_FDL_HOST_REQUEST = 0x16,
+
+ /* FDL Status Host->Device bit definitions */
+ SDCA_CTL_XU_FDLH_TRANSFERRED_CHUNK = BIT(0),
+ SDCA_CTL_XU_FDLH_TRANSFERRED_FILE = BIT(1),
+ SDCA_CTL_XU_FDLH_SET_IN_PROGRESS = BIT(2),
+ SDCA_CTL_XU_FDLH_RESET_ACK = BIT(4),
+ SDCA_CTL_XU_FDLH_REQ_ABORT = BIT(5),
+ /* FDL Status Device->Host bit definitions */
+ SDCA_CTL_XU_FDLD_REQ_RESET = BIT(4),
+ SDCA_CTL_XU_FDLD_REQ_ABORT = BIT(5),
+ SDCA_CTL_XU_FDLD_ACK_TRANSFER = BIT(6),
+ SDCA_CTL_XU_FDLD_NEEDS_SET = BIT(7),
+};
+
+/**
+ * enum sdca_set_index_range - Column definitions UMP SetIndex
+ */
+enum sdca_fdl_set_index_range {
+ SDCA_FDL_SET_INDEX_SET_NUMBER = 0,
+ SDCA_FDL_SET_INDEX_FILE_SET_ID = 1,
+ SDCA_FDL_SET_INDEX_NCOLS = 2,
};
/**
@@ -542,6 +593,9 @@ enum sdca_entity0_controls {
SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION = BIT(5),
SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET = BIT(6),
SDCA_CTL_ENTITY_0_FUNCTION_BUSY = BIT(7),
+
+ /* Function Action Bits */
+ SDCA_CTL_ENTITY_0_RESET_FUNCTION_NOW = BIT(0),
};
#define SDCA_CTL_MIC_BIAS_NAME "Mic Bias"
@@ -557,7 +611,7 @@ enum sdca_entity0_controls {
#define SDCA_CTL_NDAI_PACKETTYPE_NAME "NDAI Packet Type"
#define SDCA_CTL_MIXER_NAME "Mixer"
#define SDCA_CTL_SELECTOR_NAME "Selector"
-#define SDCA_CTL_MUTE_NAME "Mute"
+#define SDCA_CTL_MUTE_NAME "Channel"
#define SDCA_CTL_CHANNEL_VOLUME_NAME "Channel Volume"
#define SDCA_CTL_AGC_NAME "AGC"
#define SDCA_CTL_BASS_BOOST_NAME "Bass Boost"
@@ -771,6 +825,7 @@ struct sdca_control {
u8 layers;
bool deferrable;
+ bool is_volatile;
bool has_default;
bool has_fixed;
};
@@ -1090,6 +1145,27 @@ struct sdca_entity_hide {
};
/**
+ * enum sdca_xu_reset_machanism - SDCA FDL Resets
+ */
+enum sdca_xu_reset_mechanism {
+ SDCA_XU_RESET_FUNCTION = 0x0,
+ SDCA_XU_RESET_DEVICE = 0x1,
+ SDCA_XU_RESET_BUS = 0x2,
+};
+
+/**
+ * struct sdca_entity_xu - information specific to XU Entities
+ * @max_delay: the maximum time in microseconds allowed for the Device
+ * to change the ownership from Device to Host
+ * @reset_mechanism: indicates the type of reset that can be requested
+ * the end of an FDL.
+ */
+struct sdca_entity_xu {
+ unsigned int max_delay;
+ enum sdca_xu_reset_mechanism reset_mechanism;
+};
+
+/**
* struct sdca_entity - information for one SDCA Entity
* @label: String such as "OT 12".
* @id: Identifier used for addressing.
@@ -1105,6 +1181,7 @@ struct sdca_entity_hide {
* @pde: Power Domain Entity specific Entity properties.
* @ge: Group Entity specific Entity properties.
* @hide: HIDE Entity specific Entity properties.
+ * @xu: XU Entity specific Entity properties.
*/
struct sdca_entity {
const char *label;
@@ -1122,6 +1199,7 @@ struct sdca_entity {
struct sdca_entity_pde pde;
struct sdca_entity_ge ge;
struct sdca_entity_hide hide;
+ struct sdca_entity_xu xu;
};
};
@@ -1289,6 +1367,42 @@ enum sdca_cluster_range {
};
/**
+ * struct sdca_fdl_file - information about a file from a fileset used in FDL
+ * @vendor_id: Vendor ID of the file.
+ * @file_id: File ID of the file.
+ * @fdl_offset: Offset information for FDL.
+ */
+struct sdca_fdl_file {
+ u16 vendor_id;
+ u32 file_id;
+ u32 fdl_offset;
+};
+
+/**
+ * struct sdca_fdl_set - information about a set of files used in FDL
+ * @files: Array of files in this FDL set.
+ * @num_files: Number of files in this FDL set.
+ * @id: ID of the FDL set.
+ */
+struct sdca_fdl_set {
+ struct sdca_fdl_file *files;
+ int num_files;
+ u32 id;
+};
+
+/**
+ * struct sdca_fdl_data - information about a function's FDL data
+ * @swft: Pointer to the SoundWire File Table.
+ * @sets: Array of FDL sets used by this function.
+ * @num_sets: Number of FDL sets used by this function.
+ */
+struct sdca_fdl_data {
+ struct acpi_table_swft *swft;
+ struct sdca_fdl_set *sets;
+ int num_sets;
+};
+
+/**
* struct sdca_function_data - top-level information for one SDCA function
* @desc: Pointer to short descriptor from initial parsing.
* @init_table: Pointer to a table of initialization writes.
@@ -1299,6 +1413,9 @@ enum sdca_cluster_range {
* @num_clusters: Number of Channel Clusters reported in this Function.
* @busy_max_delay: Maximum Function busy delay in microseconds, before an
* error should be reported.
+ * @reset_max_delay: Maximum Function reset delay in microseconds, before an
+ * error should be reported.
+ * @fdl_data: FDL data for this Function, if available.
*/
struct sdca_function_data {
struct sdca_function_desc *desc;
@@ -1311,6 +1428,9 @@ struct sdca_function_data {
int num_clusters;
unsigned int busy_max_delay;
+ unsigned int reset_max_delay;
+
+ struct sdca_fdl_data fdl_data;
};
static inline u32 sdca_range(struct sdca_control_range *range,
@@ -1332,10 +1452,12 @@ static inline u32 sdca_range_search(struct sdca_control_range *range,
return 0;
}
-int sdca_parse_function(struct device *dev,
+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);
+
struct sdca_control *sdca_selector_find_control(struct device *dev,
struct sdca_entity *entity,
const int sel);
diff --git a/include/sound/sdca_hid.h b/include/sound/sdca_hid.h
index 8ab3e498884e..18bebbe428c9 100644
--- a/include/sound/sdca_hid.h
+++ b/include/sound/sdca_hid.h
@@ -8,14 +8,27 @@
#ifndef __SDCA_HID_H__
#define __SDCA_HID_H__
-#include <linux/types.h>
-#include <linux/hid.h>
+struct device;
+struct sdw_slave;
+
+struct sdca_entity;
+struct sdca_interrupt;
#if IS_ENABLED(CONFIG_SND_SOC_SDCA_HID)
-int sdca_add_hid_device(struct device *dev, struct sdca_entity *entity);
+
+int sdca_add_hid_device(struct device *dev, struct sdw_slave *sdw,
+ struct sdca_entity *entity);
+int sdca_hid_process_report(struct sdca_interrupt *interrupt);
#else
-static inline int sdca_add_hid_device(struct device *dev, struct sdca_entity *entity)
+
+static inline int sdca_add_hid_device(struct device *dev, struct sdw_slave *sdw,
+ struct sdca_entity *entity)
+{
+ return 0;
+}
+
+static inline int sdca_hid_process_report(struct sdca_interrupt *interrupt)
{
return 0;
}
diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h
index bbbc3ab27eba..8f13417d129a 100644
--- a/include/sound/sdca_interrupts.h
+++ b/include/sound/sdca_interrupts.h
@@ -23,18 +23,23 @@ struct sdca_function_data;
/**
* struct sdca_interrupt - contains information about a single SDCA interrupt
* @name: The name of the interrupt.
+ * @dev: Pointer to the Function device.
+ * @device_regmap: Pointer to the IRQ regmap.
+ * @function_regmap: Pointer to the SDCA Function regmap.
* @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.
* @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.
+ * @irq: IRQ number allocated to this interrupt, also used internally to track
+ * the IRQ being assigned.
*/
struct sdca_interrupt {
const char *name;
+ struct device *dev;
+ struct regmap *device_regmap;
+ struct regmap *function_regmap;
struct snd_soc_component *component;
struct sdca_function_data *function;
struct sdca_entity *entity;
@@ -42,7 +47,7 @@ struct sdca_interrupt {
void *priv;
- bool externally_requested;
+ int irq;
};
/**
@@ -64,11 +69,15 @@ struct sdca_interrupt_info {
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,
+int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap,
+ 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_early(struct device *dev, struct regmap *function_regmap,
+ struct sdca_function_data *function,
+ struct sdca_interrupt_info *info);
int sdca_irq_populate(struct sdca_function_data *function,
struct snd_soc_component *component,
struct sdca_interrupt_info *info);
diff --git a/include/sound/sdca_regmap.h b/include/sound/sdca_regmap.h
index b2e3c2ad2bb8..792540a530fc 100644
--- a/include/sound/sdca_regmap.h
+++ b/include/sound/sdca_regmap.h
@@ -27,5 +27,7 @@ int sdca_regmap_populate_constants(struct device *dev, struct sdca_function_data
int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap,
struct sdca_function_data *function);
+int sdca_regmap_write_init(struct device *dev, struct regmap *regmap,
+ struct sdca_function_data *function);
#endif // __SDCA_REGMAP_H__
diff --git a/include/sound/sdca_ump.h b/include/sound/sdca_ump.h
new file mode 100644
index 000000000000..f54f9d48c64c
--- /dev/null
+++ b/include/sound/sdca_ump.h
@@ -0,0 +1,50 @@
+/* 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_UMP_H__
+#define __SDCA_UMP_H__
+
+struct regmap;
+struct sdca_control;
+struct sdca_entity;
+struct sdca_function_data;
+struct snd_soc_component;
+struct delayed_work;
+
+int sdca_ump_get_owner_host(struct device *dev,
+ struct regmap *function_regmap,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ struct sdca_control *control);
+int sdca_ump_set_owner_device(struct device *dev,
+ struct regmap *function_regmap,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ struct sdca_control *control);
+int sdca_ump_read_message(struct device *dev,
+ struct regmap *device_regmap,
+ struct regmap *function_regmap,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ unsigned int offset_sel, unsigned int length_sel,
+ void **msg);
+int sdca_ump_write_message(struct device *dev,
+ struct regmap *device_regmap,
+ struct regmap *function_regmap,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ unsigned int offset_sel, unsigned int msg_offset,
+ unsigned int length_sel,
+ void *msg, int msg_len);
+
+void sdca_ump_cancel_timeout(struct delayed_work *work);
+void sdca_ump_schedule_timeout(struct delayed_work *work,
+ unsigned int timeout_us);
+
+#endif // __SDCA_UMP_H__
diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h
index daed7123df9d..382029724e85 100644
--- a/include/sound/soc-acpi-intel-match.h
+++ b/include/sound/soc-acpi-intel-match.h
@@ -34,6 +34,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[];
+extern struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[];
@@ -46,6 +47,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[];
extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[];
+extern struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_sdw_machines[];
/*
* generic table used for HDA codec-based platforms, possibly with
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index b8af309c2683..90d73b9bddab 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -114,8 +114,8 @@ struct snd_soc_acpi_endpoint {
* @name_prefix: string used for codec controls
*/
struct snd_soc_acpi_adr_device {
- const u64 adr;
- const u8 num_endpoints;
+ u64 adr;
+ u8 num_endpoints;
const struct snd_soc_acpi_endpoint *endpoints;
const char *name_prefix;
};
@@ -131,8 +131,8 @@ struct snd_soc_acpi_adr_device {
*/
struct snd_soc_acpi_link_adr {
- const u32 mask;
- const u32 num_adr;
+ u32 mask;
+ u32 num_adr;
const struct snd_soc_acpi_adr_device *adr_d;
};
diff --git a/include/sound/soc.h b/include/sound/soc.h
index ddc508ff7b9b..aa0fe6b80293 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -319,6 +319,13 @@ struct platform_device;
#define SOC_VALUE_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put)
+#define SOC_ENUM_EXT_ACC(xname, xenum, xhandler_get, xhandler_put, xaccess) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .access = xaccess, \
+ .info = snd_soc_info_enum_double, \
+ .get = xhandler_get, .put = xhandler_put, \
+ .private_value = (unsigned long)&xenum }
+
#define SND_SOC_BYTES(xname, xbase, xregs) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \
@@ -331,6 +338,13 @@ struct platform_device;
.put = xhandler_put, .private_value = \
((unsigned long)&(struct soc_bytes) \
{.base = xbase, .num_regs = xregs }) }
+#define SND_SOC_BYTES_E_ACC(xname, xbase, xregs, xhandler_get, xhandler_put, xaccess) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .access = xaccess, \
+ .info = snd_soc_bytes_info, .get = xhandler_get, \
+ .put = xhandler_put, .private_value = \
+ ((unsigned long)&(struct soc_bytes) \
+ {.base = xbase, .num_regs = xregs }) }
#define SND_SOC_BYTES_MASK(xname, xbase, xregs, xmask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -1225,6 +1239,7 @@ struct soc_mixer_control {
unsigned int sign_bit;
unsigned int invert:1;
unsigned int autodisable:1;
+ unsigned int sdca_q78:1;
#ifdef CONFIG_SND_SOC_TOPOLOGY
struct snd_soc_dobj dobj;
#endif
@@ -1305,22 +1320,6 @@ static inline unsigned int snd_soc_enum_item_to_val(const struct soc_enum *e,
return e->values[item];
}
-/**
- * snd_soc_kcontrol_component() - Returns the component that registered the
- * control
- * @kcontrol: The control for which to get the component
- *
- * Note: This function will work correctly if the control has been registered
- * for a component. With snd_soc_add_codec_controls() or via table based
- * setup for either a CODEC or component driver. Otherwise the behavior is
- * undefined.
- */
-static inline struct snd_soc_component *snd_soc_kcontrol_component(
- struct snd_kcontrol *kcontrol)
-{
- return snd_kcontrol_chip(kcontrol);
-}
-
int snd_soc_util_init(void);
void snd_soc_util_exit(void);
@@ -1482,22 +1481,22 @@ static inline void _snd_soc_dapm_mutex_assert_held_c(struct snd_soc_card *card)
static inline void _snd_soc_dapm_mutex_lock_root_d(struct snd_soc_dapm_context *dapm)
{
- _snd_soc_dapm_mutex_lock_root_c(dapm->card);
+ _snd_soc_dapm_mutex_lock_root_c(snd_soc_dapm_to_card(dapm));
}
static inline void _snd_soc_dapm_mutex_lock_d(struct snd_soc_dapm_context *dapm)
{
- _snd_soc_dapm_mutex_lock_c(dapm->card);
+ _snd_soc_dapm_mutex_lock_c(snd_soc_dapm_to_card(dapm));
}
static inline void _snd_soc_dapm_mutex_unlock_d(struct snd_soc_dapm_context *dapm)
{
- _snd_soc_dapm_mutex_unlock_c(dapm->card);
+ _snd_soc_dapm_mutex_unlock_c(snd_soc_dapm_to_card(dapm));
}
static inline void _snd_soc_dapm_mutex_assert_held_d(struct snd_soc_dapm_context *dapm)
{
- _snd_soc_dapm_mutex_assert_held_c(dapm->card);
+ _snd_soc_dapm_mutex_assert_held_c(snd_soc_dapm_to_card(dapm));
}
#define snd_soc_dapm_mutex_lock_root(x) _Generic((x), \
diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h
index 3c5e9b2af7f1..227347c8f0b3 100644
--- a/include/sound/soc_sdw_utils.h
+++ b/include/sound/soc_sdw_utils.h
@@ -13,6 +13,7 @@
#include <sound/soc-acpi.h>
#define SOC_SDW_MAX_DAI_NUM 8
+#define SOC_SDW_MAX_AUX_NUM 2
#define SOC_SDW_MAX_NO_PROPS 2
#define SOC_SDW_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
@@ -45,6 +46,7 @@ struct asoc_sdw_codec_info;
struct asoc_sdw_dai_info {
const bool direction[2]; /* playback & capture support */
+ const char *codec_name;
const char *dai_name;
const char *component_name;
const int dai_type;
@@ -64,16 +66,22 @@ struct asoc_sdw_dai_info {
bool quirk_exclude;
};
+struct asoc_sdw_aux_info {
+ const char *codec_name;
+};
+
struct asoc_sdw_codec_info {
const int part_id;
const int version_id;
- const char *codec_name;
+ const char *name_prefix;
int amp_num;
const u8 acpi_id[ACPI_ID_LEN];
const bool ignore_internal_dmic;
const struct snd_soc_ops *ops;
struct asoc_sdw_dai_info dais[SOC_SDW_MAX_DAI_NUM];
const int dai_num;
+ struct asoc_sdw_aux_info auxs[SOC_SDW_MAX_AUX_NUM];
+ const int aux_num;
int (*codec_card_late_probe)(struct snd_soc_card *card);
@@ -130,7 +138,7 @@ int asoc_sdw_hw_free(struct snd_pcm_substream *substream);
void asoc_sdw_shutdown(struct snd_pcm_substream *substream);
const char *asoc_sdw_get_codec_name(struct device *dev,
- const struct asoc_sdw_codec_info *codec_info,
+ const struct asoc_sdw_dai_info *dai_info,
const struct snd_soc_acpi_link_adr *adr_link,
int adr_index);
@@ -164,12 +172,15 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
int no_pcm, int (*init)(struct snd_soc_pcm_runtime *rtd),
const struct snd_soc_ops *ops);
-int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends);
+int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card,
+ int *num_devs, int *num_ends, int *num_aux);
struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
const struct snd_soc_acpi_endpoint *new);
+int asoc_sdw_get_dai_type(u32 type);
int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
+ struct snd_soc_aux_dev *soc_aux,
struct asoc_sdw_dailink *soc_dais,
struct asoc_sdw_endpoint *soc_ends,
int *num_devs);
@@ -246,6 +257,8 @@ int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_da
int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
+int asoc_sdw_cs42l45_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
+int asoc_sdw_cs42l45_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai);
/* TI */
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index 0fbcdb15c74b..9d3c54cb8223 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -117,14 +117,20 @@ enum audio_device {
TAS2120,
TAS2320,
TAS2563,
+ TAS2568,
TAS2570,
TAS2572,
+ TAS2574,
TAS2781,
TAS5802,
+ TAS5806M,
+ TAS5806MD,
TAS5815,
+ TAS5822,
TAS5825,
TAS5827,
TAS5828,
+ TAS5830,
TAS_OTHERS,
};
@@ -197,7 +203,6 @@ struct tasdevice_priv {
struct acoustic_data acou_data;
#endif
struct tasdevice_fw *fmw;
- struct gpio_desc *speaker_id;
struct gpio_desc *reset;
struct mutex codec_lock;
struct regmap *regmap;
@@ -215,6 +220,7 @@ struct tasdevice_priv {
unsigned int magic_num;
unsigned int chip_id;
unsigned int sysclk;
+ int speaker_id;
int irq;
int cur_prog;