summaryrefslogtreecommitdiff
path: root/sound/soc/intel
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel')
-rw-r--r--sound/soc/intel/atom/sst/sst_ipc.c3
-rw-r--r--sound/soc/intel/avs/Makefile5
-rw-r--r--sound/soc/intel/avs/apl.c58
-rw-r--r--sound/soc/intel/avs/avs.h70
-rw-r--r--sound/soc/intel/avs/board_selection.c85
-rw-r--r--sound/soc/intel/avs/cnl.c61
-rw-r--r--sound/soc/intel/avs/core.c161
-rw-r--r--sound/soc/intel/avs/icl.c197
-rw-r--r--sound/soc/intel/avs/ipc.c66
-rw-r--r--sound/soc/intel/avs/loader.c2
-rw-r--r--sound/soc/intel/avs/messages.c1
-rw-r--r--sound/soc/intel/avs/messages.h38
-rw-r--r--sound/soc/intel/avs/path.c33
-rw-r--r--sound/soc/intel/avs/pcm.c77
-rw-r--r--sound/soc/intel/avs/registers.h21
-rw-r--r--sound/soc/intel/avs/skl.c59
-rw-r--r--sound/soc/intel/avs/sysfs.c35
-rw-r--r--sound/soc/intel/avs/tgl.c54
-rw-r--r--sound/soc/intel/avs/topology.c164
-rw-r--r--sound/soc/intel/avs/topology.h13
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c249
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.h29
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c236
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c151
-rw-r--r--sound/soc/intel/boards/sof_sdw.c106
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h82
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l42.c35
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs42l43.c25
-rw-r--r--sound/soc/intel/boards/sof_sdw_cs_amp.c3
-rw-r--r--sound/soc/intel/boards/sof_sdw_maxim.c4
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt5682.c35
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt700.c35
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt711.c19
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt712_sdca.c39
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715.c12
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt715_sdca.c12
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_amp.c53
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c19
-rw-r--r--sound/soc/intel/boards/sof_ssp_common.h8
-rw-r--r--sound/soc/intel/catpt/dsp.c4
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c12
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-jsl-match.c10
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-lnl-match.c102
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c61
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-rpl-match.c4
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-tgl-match.c6
47 files changed, 1711 insertions, 844 deletions
diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c
index 3fc2c9a6c44d..0630e58b9d6b 100644
--- a/sound/soc/intel/atom/sst/sst_ipc.c
+++ b/sound/soc/intel/atom/sst/sst_ipc.c
@@ -19,8 +19,9 @@
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/compress_driver.h>
-#include <asm/intel-mid.h>
+
#include <asm/platform_sst_audio.h>
+
#include "../sst-mfld-platform.h"
#include "sst.h"
diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
index 460ee6599daf..5480500337f8 100644
--- a/sound/soc/intel/avs/Makefile
+++ b/sound/soc/intel/avs/Makefile
@@ -1,9 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o core.o loader.o \
- topology.o path.o pcm.o board_selection.o control.o
+ topology.o path.o pcm.o board_selection.o control.o \
+ sysfs.o
snd-soc-avs-objs += cldma.o
-snd-soc-avs-objs += skl.o apl.o
+snd-soc-avs-objs += skl.o apl.o cnl.o icl.o tgl.o
snd-soc-avs-objs += trace.o
# tell define_trace.h where to find the trace header
diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c
index 1860099c782a..c21ecaef9eba 100644
--- a/sound/soc/intel/avs/apl.c
+++ b/sound/soc/intel/avs/apl.c
@@ -13,11 +13,11 @@
#include "path.h"
#include "topology.h"
-static int __maybe_unused
-apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
- u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
+#ifdef CONFIG_DEBUG_FS
+int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
+ u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
{
- struct apl_log_state_info *info;
+ struct avs_apl_log_state_info *info;
u32 size, num_cores = adev->hw_cfg.dsp_cores;
int ret, i;
@@ -47,10 +47,11 @@ apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_peri
return 0;
}
+#endif
-static int apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
+int avs_apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
{
- struct apl_log_buffer_layout layout;
+ struct avs_apl_log_buffer_layout layout;
void __iomem *addr, *buf;
addr = avs_log_buffer_addr(adev, msg->log.core);
@@ -63,11 +64,11 @@ static int apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg
/* consume the logs regardless of consumer presence */
goto update_read_ptr;
- buf = apl_log_payload_addr(addr);
+ buf = avs_apl_log_payload_addr(addr);
if (layout.read_ptr > layout.write_ptr) {
avs_dump_fw_log(adev, buf + layout.read_ptr,
- apl_log_payload_size(adev) - layout.read_ptr);
+ avs_apl_log_payload_size(adev) - layout.read_ptr);
layout.read_ptr = 0;
}
avs_dump_fw_log_wakeup(adev, buf + layout.read_ptr, layout.write_ptr - layout.read_ptr);
@@ -77,7 +78,8 @@ update_read_ptr:
return 0;
}
-static int apl_wait_log_entry(struct avs_dev *adev, u32 core, struct apl_log_buffer_layout *layout)
+static int avs_apl_wait_log_entry(struct avs_dev *adev, u32 core,
+ struct avs_apl_log_buffer_layout *layout)
{
unsigned long timeout;
void __iomem *addr;
@@ -99,11 +101,11 @@ static int apl_wait_log_entry(struct avs_dev *adev, u32 core, struct apl_log_buf
}
/* reads log header and tests its type */
-#define apl_is_entry_stackdump(addr) ((readl(addr) >> 30) & 0x1)
+#define avs_apl_is_entry_stackdump(addr) ((readl(addr) >> 30) & 0x1)
-static int apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
+int avs_apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
{
- struct apl_log_buffer_layout layout;
+ struct avs_apl_log_buffer_layout layout;
void __iomem *addr, *buf;
size_t dump_size;
u16 offset = 0;
@@ -124,9 +126,9 @@ static int apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
if (!addr)
goto exit;
- buf = apl_log_payload_addr(addr);
+ buf = avs_apl_log_payload_addr(addr);
memcpy_fromio(&layout, addr, sizeof(layout));
- if (!apl_is_entry_stackdump(buf + layout.read_ptr)) {
+ if (!avs_apl_is_entry_stackdump(buf + layout.read_ptr)) {
union avs_notify_msg lbs_msg = AVS_NOTIFICATION(LOG_BUFFER_STATUS);
/*
@@ -142,11 +144,11 @@ static int apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
do {
u32 count;
- if (apl_wait_log_entry(adev, msg->ext.coredump.core_id, &layout))
+ if (avs_apl_wait_log_entry(adev, msg->ext.coredump.core_id, &layout))
break;
if (layout.read_ptr > layout.write_ptr) {
- count = apl_log_payload_size(adev) - layout.read_ptr;
+ count = avs_apl_log_payload_size(adev) - layout.read_ptr;
memcpy_fromio(pos + offset, buf + layout.read_ptr, count);
layout.read_ptr = 0;
offset += count;
@@ -165,7 +167,7 @@ exit:
return 0;
}
-static bool apl_lp_streaming(struct avs_dev *adev)
+static bool avs_apl_lp_streaming(struct avs_dev *adev)
{
struct avs_path *path;
@@ -201,7 +203,7 @@ static bool apl_lp_streaming(struct avs_dev *adev)
return true;
}
-static bool apl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
+bool avs_apl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
{
/* wake in all cases */
if (wake)
@@ -215,10 +217,10 @@ static bool apl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool w
* Note: for cAVS 1.5+ and 1.8, D0IX is LP-firmware transition,
* not the power-gating mechanism known from cAVS 2.0.
*/
- return apl_lp_streaming(adev);
+ return avs_apl_lp_streaming(adev);
}
-static int apl_set_d0ix(struct avs_dev *adev, bool enable)
+int avs_apl_set_d0ix(struct avs_dev *adev, bool enable)
{
bool streaming = false;
int ret;
@@ -231,20 +233,20 @@ static int apl_set_d0ix(struct avs_dev *adev, bool enable)
return AVS_IPC_RET(ret);
}
-const struct avs_dsp_ops apl_dsp_ops = {
+const struct avs_dsp_ops avs_apl_dsp_ops = {
.power = avs_dsp_core_power,
.reset = avs_dsp_core_reset,
.stall = avs_dsp_core_stall,
- .irq_handler = avs_dsp_irq_handler,
- .irq_thread = avs_dsp_irq_thread,
+ .irq_handler = avs_irq_handler,
+ .irq_thread = avs_skl_irq_thread,
.int_control = avs_dsp_interrupt_control,
.load_basefw = avs_hda_load_basefw,
.load_lib = avs_hda_load_library,
.transfer_mods = avs_hda_transfer_modules,
- .log_buffer_offset = skl_log_buffer_offset,
- .log_buffer_status = apl_log_buffer_status,
- .coredump = apl_coredump,
- .d0ix_toggle = apl_d0ix_toggle,
- .set_d0ix = apl_set_d0ix,
+ .log_buffer_offset = avs_skl_log_buffer_offset,
+ .log_buffer_status = avs_apl_log_buffer_status,
+ .coredump = avs_apl_coredump,
+ .d0ix_toggle = avs_apl_d0ix_toggle,
+ .set_d0ix = avs_apl_set_d0ix,
AVS_SET_ENABLE_LOGS_OP(apl)
};
diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index d694e08e44e1..f80f79415344 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -46,8 +46,8 @@ struct avs_dsp_ops {
int (* const power)(struct avs_dev *, u32, bool);
int (* const reset)(struct avs_dev *, u32, bool);
int (* const stall)(struct avs_dev *, u32, bool);
- irqreturn_t (* const irq_handler)(int, void *);
- irqreturn_t (* const irq_thread)(int, void *);
+ irqreturn_t (* const irq_handler)(struct avs_dev *);
+ irqreturn_t (* const irq_thread)(struct avs_dev *);
void (* const int_control)(struct avs_dev *, bool);
int (* const load_basefw)(struct avs_dev *, struct firmware *);
int (* const load_lib)(struct avs_dev *, struct firmware *, u32);
@@ -64,8 +64,11 @@ struct avs_dsp_ops {
#define avs_dsp_op(adev, op, ...) \
((adev)->spec->dsp_ops->op(adev, ## __VA_ARGS__))
-extern const struct avs_dsp_ops skl_dsp_ops;
-extern const struct avs_dsp_ops apl_dsp_ops;
+extern const struct avs_dsp_ops avs_skl_dsp_ops;
+extern const struct avs_dsp_ops avs_apl_dsp_ops;
+extern const struct avs_dsp_ops avs_cnl_dsp_ops;
+extern const struct avs_dsp_ops avs_icl_dsp_ops;
+extern const struct avs_dsp_ops avs_tgl_dsp_ops;
#define AVS_PLATATTR_CLDMA BIT_ULL(0)
#define AVS_PLATATTR_IMR BIT_ULL(1)
@@ -73,6 +76,23 @@ extern const struct avs_dsp_ops apl_dsp_ops;
#define avs_platattr_test(adev, attr) \
((adev)->spec->attributes & AVS_PLATATTR_##attr)
+struct avs_sram_spec {
+ const u32 base_offset;
+ const u32 window_size;
+ const u32 rom_status_offset;
+};
+
+struct avs_hipc_spec {
+ const u32 req_offset;
+ const u32 req_ext_offset;
+ const u32 req_busy_mask;
+ const u32 ack_offset;
+ const u32 ack_done_mask;
+ const u32 rsp_offset;
+ const u32 rsp_busy_mask;
+ const u32 ctl_offset;
+};
+
/* Platform specific descriptor */
struct avs_spec {
const char *name;
@@ -82,9 +102,8 @@ struct avs_spec {
const u32 core_init_mask; /* used during DSP boot */
const u64 attributes; /* bitmask of AVS_PLATATTR_* */
- const u32 sram_base_offset;
- const u32 sram_window_size;
- const u32 rom_status;
+ const struct avs_sram_spec *sram;
+ const struct avs_hipc_spec *hipc;
};
struct avs_fw_entry {
@@ -127,6 +146,7 @@ struct avs_dev {
int *core_refs; /* reference count per core */
char **lib_names;
int num_lp_paths;
+ atomic_t l1sen_counter; /* controls whether L1SEN should be disabled */
struct completion fw_ready;
struct work_struct probe_work;
@@ -225,8 +245,7 @@ struct avs_ipc {
#define AVS_IPC_RET(ret) \
(((ret) <= 0) ? (ret) : -AVS_EIPC)
-irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id);
-irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id);
+irqreturn_t avs_irq_handler(struct avs_dev *adev);
void avs_dsp_process_response(struct avs_dev *adev, u64 header);
int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request,
struct avs_ipc_msg *reply, int timeout, const char *name);
@@ -248,7 +267,20 @@ void avs_ipc_block(struct avs_ipc *ipc);
int avs_dsp_disable_d0ix(struct avs_dev *adev);
int avs_dsp_enable_d0ix(struct avs_dev *adev);
-int skl_log_buffer_offset(struct avs_dev *adev, u32 core);
+irqreturn_t avs_skl_irq_thread(struct avs_dev *adev);
+irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev);
+int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
+ u32 fifo_full_period, unsigned long resource_mask, u32 *priorities);
+int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
+ u32 fifo_full_period, unsigned long resource_mask, u32 *priorities);
+int avs_skl_log_buffer_offset(struct avs_dev *adev, u32 core);
+int avs_icl_log_buffer_offset(struct avs_dev *adev, u32 core);
+int avs_apl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg);
+int avs_apl_coredump(struct avs_dev *adev, union avs_notify_msg *msg);
+bool avs_apl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake);
+bool avs_icl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake);
+int avs_apl_set_d0ix(struct avs_dev *adev, bool enable);
+int avs_icl_set_d0ix(struct avs_dev *adev, bool enable);
/* Firmware resources management */
@@ -293,6 +325,8 @@ int avs_hda_load_library(struct avs_dev *adev, struct firmware *lib, u32 id);
int avs_hda_transfer_modules(struct avs_dev *adev, bool load,
struct avs_module_entry *mods, u32 num_mods);
+int avs_icl_load_basefw(struct avs_dev *adev, struct firmware *fw);
+
/* Soc component members */
struct avs_soc_component {
@@ -342,21 +376,21 @@ static inline int avs_log_buffer_status_locked(struct avs_dev *adev, union avs_n
return ret;
}
-struct apl_log_buffer_layout {
+struct avs_apl_log_buffer_layout {
u32 read_ptr;
u32 write_ptr;
u8 buffer[];
} __packed;
-#define apl_log_payload_size(adev) \
- (avs_log_buffer_size(adev) - sizeof(struct apl_log_buffer_layout))
+#define avs_apl_log_payload_size(adev) \
+ (avs_log_buffer_size(adev) - sizeof(struct avs_apl_log_buffer_layout))
-#define apl_log_payload_addr(addr) \
- (addr + sizeof(struct apl_log_buffer_layout))
+#define avs_apl_log_payload_addr(addr) \
+ (addr + sizeof(struct avs_apl_log_buffer_layout))
#ifdef CONFIG_DEBUG_FS
#define AVS_SET_ENABLE_LOGS_OP(name) \
- .enable_logs = name##_enable_logs
+ .enable_logs = avs_##name##_enable_logs
bool avs_logging_fw(struct avs_dev *adev);
void avs_dump_fw_log(struct avs_dev *adev, const void __iomem *src, unsigned int len);
@@ -392,4 +426,8 @@ static inline void avs_debugfs_init(struct avs_dev *adev) { }
static inline void avs_debugfs_exit(struct avs_dev *adev) { }
#endif
+/* Filesystems integration */
+
+extern const struct attribute_group *avs_attr_groups[];
+
#endif /* __SOUND_SOC_INTEL_AVS_H */
diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c
index 8e91eece992d..8360ce557401 100644
--- a/sound/soc/intel/avs/board_selection.c
+++ b/sound/soc/intel/avs/board_selection.c
@@ -236,6 +236,82 @@ static struct snd_soc_acpi_mach avs_gml_i2s_machines[] = {
{},
};
+static struct snd_soc_acpi_mach avs_cnl_i2s_machines[] = {
+ {
+ .id = "INT34C2",
+ .drv_name = "avs_rt274",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(0),
+ },
+ .tplg_filename = "rt274-tplg.bin",
+ },
+ {
+ .id = "10EC5682",
+ .drv_name = "avs_rt5682",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(1),
+ },
+ .tplg_filename = "rt5682-tplg.bin",
+ },
+ {},
+};
+
+static struct snd_soc_acpi_mach avs_icl_i2s_machines[] = {
+ {
+ .id = "INT343A",
+ .drv_name = "avs_rt298",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(0),
+ },
+ .tplg_filename = "rt298-tplg.bin",
+ },
+ {
+ .id = "INT34C2",
+ .drv_name = "avs_rt274",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(0),
+ },
+ .tplg_filename = "rt274-tplg.bin",
+ },
+ {},
+};
+
+static struct snd_soc_acpi_mach avs_tgl_i2s_machines[] = {
+ {
+ .id = "INT34C2",
+ .drv_name = "avs_rt274",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(0),
+ },
+ .tplg_filename = "rt274-tplg.bin",
+ },
+ {
+ .id = "10EC0298",
+ .drv_name = "avs_rt298",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(0),
+ },
+ .tplg_filename = "rt298-tplg.bin",
+ },
+ {
+ .id = "10EC1308",
+ .drv_name = "avs_rt1308",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(1),
+ },
+ .tplg_filename = "rt1308-tplg.bin",
+ },
+ {
+ .id = "ESSX8336",
+ .drv_name = "avs_es8336",
+ .mach_params = {
+ .i2s_link_mask = AVS_SSP(0),
+ },
+ .tplg_filename = "es8336-tplg.bin",
+ },
+ {},
+};
+
static struct snd_soc_acpi_mach avs_test_i2s_machines[] = {
{
.drv_name = "avs_i2s_test",
@@ -296,6 +372,15 @@ static const struct avs_acpi_boards i2s_boards[] = {
AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines),
AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines),
AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines),
+ AVS_MACH_ENTRY(HDA_CNL_LP, avs_cnl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_CNL_H, avs_cnl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_CML_LP, avs_cnl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_ICL_LP, avs_icl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_TGL_LP, avs_tgl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_EHL_0, avs_tgl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_ADL_P, avs_tgl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_RPL_P_0, avs_tgl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_RPL_M, avs_tgl_i2s_machines),
{},
};
diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c
new file mode 100644
index 000000000000..5423c29ecc4e
--- /dev/null
+++ b/sound/soc/intel/avs/cnl.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021-2024 Intel Corporation. All rights reserved.
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#include <sound/hdaudio_ext.h>
+#include "avs.h"
+#include "messages.h"
+
+irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev)
+{
+ union avs_reply_msg msg;
+ u32 hipctdr, hipctdd, hipctda;
+
+ hipctdr = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDR);
+ hipctdd = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDD);
+
+ /* Ensure DSP sent new response to process. */
+ if (!(hipctdr & CNL_ADSP_HIPCTDR_BUSY))
+ return IRQ_NONE;
+
+ msg.primary = hipctdr;
+ msg.ext.val = hipctdd;
+ avs_dsp_process_response(adev, msg.val);
+
+ /* Tell DSP we accepted its message. */
+ snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDR,
+ CNL_ADSP_HIPCTDR_BUSY, CNL_ADSP_HIPCTDR_BUSY);
+ /* Ack this response. */
+ snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDA,
+ CNL_ADSP_HIPCTDA_DONE, CNL_ADSP_HIPCTDA_DONE);
+ /* HW might have been clock gated, give some time for change to propagate. */
+ snd_hdac_adsp_readl_poll(adev, CNL_ADSP_REG_HIPCTDA, hipctda,
+ !(hipctda & CNL_ADSP_HIPCTDA_DONE), 10, 1000);
+ /* Unmask busy interrupt. */
+ snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCCTL,
+ AVS_ADSP_HIPCCTL_BUSY, AVS_ADSP_HIPCCTL_BUSY);
+
+ return IRQ_HANDLED;
+}
+
+const struct avs_dsp_ops avs_cnl_dsp_ops = {
+ .power = avs_dsp_core_power,
+ .reset = avs_dsp_core_reset,
+ .stall = avs_dsp_core_stall,
+ .irq_handler = avs_irq_handler,
+ .irq_thread = avs_cnl_irq_thread,
+ .int_control = avs_dsp_interrupt_control,
+ .load_basefw = avs_hda_load_basefw,
+ .load_lib = avs_hda_load_library,
+ .transfer_mods = avs_hda_transfer_modules,
+ .log_buffer_offset = avs_skl_log_buffer_offset,
+ .log_buffer_status = avs_apl_log_buffer_status,
+ .coredump = avs_apl_coredump,
+ .d0ix_toggle = avs_apl_d0ix_toggle,
+ .set_d0ix = avs_apl_set_d0ix,
+ AVS_SET_ENABLE_LOGS_OP(apl)
+};
diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c
index 565878eb42cd..d7f8940099ce 100644
--- a/sound/soc/intel/avs/core.c
+++ b/sound/soc/intel/avs/core.c
@@ -69,9 +69,14 @@ void avs_hda_clock_gating_enable(struct avs_dev *adev, bool enable)
void avs_hda_l1sen_enable(struct avs_dev *adev, bool enable)
{
- u32 value = enable ? AZX_VS_EM2_L1SEN : 0;
-
- snd_hdac_chip_updatel(&adev->base.core, VS_EM2, AZX_VS_EM2_L1SEN, value);
+ if (enable) {
+ if (atomic_inc_and_test(&adev->l1sen_counter))
+ snd_hdac_chip_updatel(&adev->base.core, VS_EM2, AZX_VS_EM2_L1SEN,
+ AZX_VS_EM2_L1SEN);
+ } else {
+ if (atomic_dec_return(&adev->l1sen_counter) == -1)
+ snd_hdac_chip_updatel(&adev->base.core, VS_EM2, AZX_VS_EM2_L1SEN, 0);
+ }
}
static int avs_hdac_bus_init_streams(struct hdac_bus *bus)
@@ -317,6 +322,20 @@ static irqreturn_t hdac_bus_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
+static irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id)
+{
+ struct avs_dev *adev = dev_id;
+
+ return avs_dsp_op(adev, irq_handler);
+}
+
+static irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id)
+{
+ struct avs_dev *adev = dev_id;
+
+ return avs_dsp_op(adev, irq_thread);
+}
+
static int avs_hdac_acquire_irq(struct avs_dev *adev)
{
struct hdac_bus *bus = &adev->base.core;
@@ -726,38 +745,107 @@ static const struct dev_pm_ops avs_dev_pm = {
SET_RUNTIME_PM_OPS(avs_runtime_suspend, avs_runtime_resume, NULL)
};
+static const struct avs_sram_spec skl_sram_spec = {
+ .base_offset = SKL_ADSP_SRAM_BASE_OFFSET,
+ .window_size = SKL_ADSP_SRAM_WINDOW_SIZE,
+ .rom_status_offset = SKL_ADSP_SRAM_BASE_OFFSET,
+};
+
+static const struct avs_sram_spec apl_sram_spec = {
+ .base_offset = APL_ADSP_SRAM_BASE_OFFSET,
+ .window_size = APL_ADSP_SRAM_WINDOW_SIZE,
+ .rom_status_offset = APL_ADSP_SRAM_BASE_OFFSET,
+};
+
+static const struct avs_hipc_spec skl_hipc_spec = {
+ .req_offset = SKL_ADSP_REG_HIPCI,
+ .req_ext_offset = SKL_ADSP_REG_HIPCIE,
+ .req_busy_mask = SKL_ADSP_HIPCI_BUSY,
+ .ack_offset = SKL_ADSP_REG_HIPCIE,
+ .ack_done_mask = SKL_ADSP_HIPCIE_DONE,
+ .rsp_offset = SKL_ADSP_REG_HIPCT,
+ .rsp_busy_mask = SKL_ADSP_HIPCT_BUSY,
+ .ctl_offset = SKL_ADSP_REG_HIPCCTL,
+};
+
+static const struct avs_hipc_spec cnl_hipc_spec = {
+ .req_offset = CNL_ADSP_REG_HIPCIDR,
+ .req_ext_offset = CNL_ADSP_REG_HIPCIDD,
+ .req_busy_mask = CNL_ADSP_HIPCIDR_BUSY,
+ .ack_offset = CNL_ADSP_REG_HIPCIDA,
+ .ack_done_mask = CNL_ADSP_HIPCIDA_DONE,
+ .rsp_offset = CNL_ADSP_REG_HIPCTDR,
+ .rsp_busy_mask = CNL_ADSP_HIPCTDR_BUSY,
+ .ctl_offset = CNL_ADSP_REG_HIPCCTL,
+};
+
static const struct avs_spec skl_desc = {
.name = "skl",
- .min_fw_version = {
- .major = 9,
- .minor = 21,
- .hotfix = 0,
- .build = 4732,
- },
- .dsp_ops = &skl_dsp_ops,
+ .min_fw_version = { 9, 21, 0, 4732 },
+ .dsp_ops = &avs_skl_dsp_ops,
.core_init_mask = 1,
.attributes = AVS_PLATATTR_CLDMA,
- .sram_base_offset = SKL_ADSP_SRAM_BASE_OFFSET,
- .sram_window_size = SKL_ADSP_SRAM_WINDOW_SIZE,
- .rom_status = SKL_ADSP_SRAM_BASE_OFFSET,
+ .sram = &skl_sram_spec,
+ .hipc = &skl_hipc_spec,
};
static const struct avs_spec apl_desc = {
.name = "apl",
- .min_fw_version = {
- .major = 9,
- .minor = 22,
- .hotfix = 1,
- .build = 4323,
- },
- .dsp_ops = &apl_dsp_ops,
+ .min_fw_version = { 9, 22, 1, 4323 },
+ .dsp_ops = &avs_apl_dsp_ops,
.core_init_mask = 3,
.attributes = AVS_PLATATTR_IMR,
- .sram_base_offset = APL_ADSP_SRAM_BASE_OFFSET,
- .sram_window_size = APL_ADSP_SRAM_WINDOW_SIZE,
- .rom_status = APL_ADSP_SRAM_BASE_OFFSET,
+ .sram = &apl_sram_spec,
+ .hipc = &skl_hipc_spec,
+};
+
+static const struct avs_spec cnl_desc = {
+ .name = "cnl",
+ .min_fw_version = { 10, 23, 0, 5314 },
+ .dsp_ops = &avs_cnl_dsp_ops,
+ .core_init_mask = 1,
+ .attributes = AVS_PLATATTR_IMR,
+ .sram = &apl_sram_spec,
+ .hipc = &cnl_hipc_spec,
+};
+
+static const struct avs_spec icl_desc = {
+ .name = "icl",
+ .min_fw_version = { 10, 23, 0, 5040 },
+ .dsp_ops = &avs_icl_dsp_ops,
+ .core_init_mask = 1,
+ .attributes = AVS_PLATATTR_IMR,
+ .sram = &apl_sram_spec,
+ .hipc = &cnl_hipc_spec,
};
+static const struct avs_spec jsl_desc = {
+ .name = "jsl",
+ .min_fw_version = { 10, 26, 0, 5872 },
+ .dsp_ops = &avs_icl_dsp_ops,
+ .core_init_mask = 1,
+ .attributes = AVS_PLATATTR_IMR,
+ .sram = &apl_sram_spec,
+ .hipc = &cnl_hipc_spec,
+};
+
+#define AVS_TGL_BASED_SPEC(sname) \
+static const struct avs_spec sname##_desc = { \
+ .name = #sname, \
+ .min_fw_version = { 10, 29, 0, 5646 }, \
+ .dsp_ops = &avs_tgl_dsp_ops, \
+ .core_init_mask = 1, \
+ .attributes = AVS_PLATATTR_IMR, \
+ .sram = &apl_sram_spec, \
+ .hipc = &cnl_hipc_spec, \
+}
+
+AVS_TGL_BASED_SPEC(lkf);
+AVS_TGL_BASED_SPEC(tgl);
+AVS_TGL_BASED_SPEC(ehl);
+AVS_TGL_BASED_SPEC(adl);
+AVS_TGL_BASED_SPEC(adl_n);
+
static const struct pci_device_id avs_ids[] = {
{ PCI_DEVICE_DATA(INTEL, HDA_SKL_LP, &skl_desc) },
{ PCI_DEVICE_DATA(INTEL, HDA_SKL, &skl_desc) },
@@ -767,6 +855,32 @@ static const struct pci_device_id avs_ids[] = {
{ PCI_DEVICE_DATA(INTEL, HDA_CML_S, &skl_desc) },
{ PCI_DEVICE_DATA(INTEL, HDA_APL, &apl_desc) },
{ PCI_DEVICE_DATA(INTEL, HDA_GML, &apl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_CNL_LP, &cnl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_CNL_H, &cnl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_CML_LP, &cnl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_CML_H, &cnl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_RKL_S, &cnl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ICL_LP, &icl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ICL_N, &icl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ICL_H, &icl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_JSL_N, &jsl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_LKF, &lkf_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_TGL_LP, &tgl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_TGL_H, &tgl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_CML_R, &tgl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_EHL_0, &ehl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_EHL_3, &ehl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ADL_S, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ADL_P, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ADL_PS, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ADL_M, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ADL_PX, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_ADL_N, &adl_n_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_RPL_S, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_0, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_RPL_P_1, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_RPL_M, &adl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, &adl_desc) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, avs_ids);
@@ -777,6 +891,7 @@ static struct pci_driver avs_pci_driver = {
.probe = avs_pci_probe,
.remove = avs_pci_remove,
.shutdown = avs_pci_shutdown,
+ .dev_groups = avs_attr_groups,
.driver = {
.pm = &avs_dev_pm,
},
diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c
new file mode 100644
index 000000000000..9d9921e1cd4d
--- /dev/null
+++ b/sound/soc/intel/avs/icl.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021-2024 Intel Corporation. All rights reserved.
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#include <linux/slab.h>
+#include <sound/hdaudio.h>
+#include <sound/hdaudio_ext.h>
+#include "avs.h"
+#include "messages.h"
+
+#define ICL_VS_LTRP_GB_ICCMAX 95
+
+#ifdef CONFIG_DEBUG_FS
+int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
+ u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
+{
+ struct avs_icl_log_state_info *info;
+ u32 size, num_libs = adev->fw_cfg.max_libs_count;
+ int i, ret;
+
+ if (fls_long(resource_mask) > num_libs)
+ return -EINVAL;
+ size = struct_size(info, logs_priorities_mask, num_libs);
+ info = kzalloc(size, GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->aging_timer_period = aging_period;
+ info->fifo_full_timer_period = fifo_full_period;
+ info->enable = enable;
+ if (enable)
+ for_each_set_bit(i, &resource_mask, num_libs)
+ info->logs_priorities_mask[i] = *priorities++;
+
+ ret = avs_ipc_set_enable_logs(adev, (u8 *)info, size);
+ kfree(info);
+ if (ret)
+ return AVS_IPC_RET(ret);
+
+ return 0;
+}
+#endif
+
+union avs_icl_memwnd2_slot_type {
+ u32 val;
+ struct {
+ u32 resource_id:8;
+ u32 type:24;
+ };
+} __packed;
+
+struct avs_icl_memwnd2_desc {
+ u32 resource_id;
+ union avs_icl_memwnd2_slot_type slot_id;
+ u32 vma;
+} __packed;
+
+#define AVS_ICL_MEMWND2_SLOTS_COUNT 15
+
+struct avs_icl_memwnd2 {
+ union {
+ struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
+ u8 rsvd[PAGE_SIZE];
+ };
+ u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE];
+} __packed;
+
+#define AVS_ICL_SLOT_UNUSED \
+ ((union avs_icl_memwnd2_slot_type) { 0x00000000U })
+#define AVS_ICL_SLOT_CRITICAL_LOG \
+ ((union avs_icl_memwnd2_slot_type) { 0x54524300U })
+#define AVS_ICL_SLOT_DEBUG_LOG \
+ ((union avs_icl_memwnd2_slot_type) { 0x474f4c00U })
+#define AVS_ICL_SLOT_GDB_STUB \
+ ((union avs_icl_memwnd2_slot_type) { 0x42444700U })
+#define AVS_ICL_SLOT_BROKEN \
+ ((union avs_icl_memwnd2_slot_type) { 0x44414544U })
+
+static int avs_icl_slot_offset(struct avs_dev *adev, union avs_icl_memwnd2_slot_type slot_type)
+{
+ struct avs_icl_memwnd2_desc desc[AVS_ICL_MEMWND2_SLOTS_COUNT];
+ int i;
+
+ memcpy_fromio(&desc, avs_sram_addr(adev, AVS_DEBUG_WINDOW), sizeof(desc));
+
+ for (i = 0; i < AVS_ICL_MEMWND2_SLOTS_COUNT; i++)
+ if (desc[i].slot_id.val == slot_type.val)
+ return offsetof(struct avs_icl_memwnd2, slot_array) +
+ avs_skl_log_buffer_offset(adev, i);
+ return -ENXIO;
+}
+
+int avs_icl_log_buffer_offset(struct avs_dev *adev, u32 core)
+{
+ union avs_icl_memwnd2_slot_type slot_type = AVS_ICL_SLOT_DEBUG_LOG;
+ int ret;
+
+ slot_type.resource_id = core;
+ ret = avs_icl_slot_offset(adev, slot_type);
+ if (ret < 0)
+ dev_dbg(adev->dev, "No slot offset found for: %x\n",
+ slot_type.val);
+
+ return ret;
+}
+
+bool avs_icl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
+{
+ /* Payload-less IPCs do not take part in d0ix toggling. */
+ return tx->size;
+}
+
+int avs_icl_set_d0ix(struct avs_dev *adev, bool enable)
+{
+ int ret;
+
+ ret = avs_ipc_set_d0ix(adev, enable, false);
+ return AVS_IPC_RET(ret);
+}
+
+int avs_icl_load_basefw(struct avs_dev *adev, struct firmware *fw)
+{
+ struct hdac_bus *bus = &adev->base.core;
+ struct hdac_ext_stream *host_stream;
+ struct snd_pcm_substream substream;
+ struct snd_dma_buffer dmab;
+ unsigned int sd_fmt;
+ u8 ltrp_gb;
+ int ret;
+
+ /*
+ * ICCMAX:
+ *
+ * For ICL+ platforms, as per HW recommendation LTRP_GB is set to 95us
+ * during FW load. Its original value shall be restored once load completes.
+ *
+ * To avoid DMI/OPIO L1 entry during the load procedure, additional CAPTURE
+ * stream is allocated and set to run.
+ */
+
+ memset(&substream, 0, sizeof(substream));
+ substream.stream = SNDRV_PCM_STREAM_CAPTURE;
+
+ host_stream = snd_hdac_ext_stream_assign(bus, &substream, HDAC_EXT_STREAM_TYPE_HOST);
+ if (!host_stream)
+ return -EBUSY;
+
+ ltrp_gb = snd_hdac_chip_readb(bus, VS_LTRP) & AZX_REG_VS_LTRP_GB_MASK;
+ /* Carries no real data, use default format. */
+ sd_fmt = snd_hdac_stream_format(1, 32, 48000);
+
+ ret = snd_hdac_dsp_prepare(hdac_stream(host_stream), sd_fmt, fw->size, &dmab);
+ if (ret < 0)
+ goto release_stream;
+
+ snd_hdac_chip_updateb(bus, VS_LTRP, AZX_REG_VS_LTRP_GB_MASK, ICL_VS_LTRP_GB_ICCMAX);
+
+ spin_lock(&bus->reg_lock);
+ snd_hdac_stream_start(hdac_stream(host_stream));
+ spin_unlock(&bus->reg_lock);
+
+ ret = avs_hda_load_basefw(adev, fw);
+
+ spin_lock(&bus->reg_lock);
+ snd_hdac_stream_stop(hdac_stream(host_stream));
+ spin_unlock(&bus->reg_lock);
+
+ snd_hdac_dsp_cleanup(hdac_stream(host_stream), &dmab);
+
+release_stream:
+ snd_hdac_ext_stream_release(host_stream, HDAC_EXT_STREAM_TYPE_HOST);
+ snd_hdac_chip_updateb(bus, VS_LTRP, AZX_REG_VS_LTRP_GB_MASK, ltrp_gb);
+
+ return ret;
+}
+
+const struct avs_dsp_ops avs_icl_dsp_ops = {
+ .power = avs_dsp_core_power,
+ .reset = avs_dsp_core_reset,
+ .stall = avs_dsp_core_stall,
+ .irq_handler = avs_irq_handler,
+ .irq_thread = avs_cnl_irq_thread,
+ .int_control = avs_dsp_interrupt_control,
+ .load_basefw = avs_icl_load_basefw,
+ .load_lib = avs_hda_load_library,
+ .transfer_mods = avs_hda_transfer_modules,
+ .log_buffer_offset = avs_icl_log_buffer_offset,
+ .log_buffer_status = avs_apl_log_buffer_status,
+ .coredump = avs_apl_coredump,
+ .d0ix_toggle = avs_icl_d0ix_toggle,
+ .set_d0ix = avs_icl_set_d0ix,
+ AVS_SET_ENABLE_LOGS_OP(icl)
+};
diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c
index 65bfc83bd1f0..ad0e535b3c2e 100644
--- a/sound/soc/intel/avs/ipc.c
+++ b/sound/soc/intel/avs/ipc.c
@@ -301,10 +301,10 @@ void avs_dsp_process_response(struct avs_dev *adev, u64 header)
complete(&ipc->busy_completion);
}
-irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id)
+irqreturn_t avs_irq_handler(struct avs_dev *adev)
{
- struct avs_dev *adev = dev_id;
struct avs_ipc *ipc = adev->ipc;
+ const struct avs_spec *const spec = adev->spec;
u32 adspis, hipc_rsp, hipc_ack;
irqreturn_t ret = IRQ_NONE;
@@ -312,35 +312,35 @@ irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id)
if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC))
return ret;
- hipc_ack = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCIE);
- hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
+ hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset);
+ hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
/* DSP acked host's request */
- if (hipc_ack & SKL_ADSP_HIPCIE_DONE) {
+ if (hipc_ack & spec->hipc->ack_done_mask) {
/*
* As an extra precaution, mask done interrupt. Code executed
* due to complete() found below does not assume any masking.
*/
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
+ snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
AVS_ADSP_HIPCCTL_DONE, 0);
complete(&ipc->done_completion);
/* tell DSP it has our attention */
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCIE,
- SKL_ADSP_HIPCIE_DONE,
- SKL_ADSP_HIPCIE_DONE);
+ snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset,
+ spec->hipc->ack_done_mask,
+ spec->hipc->ack_done_mask);
/* unmask done interrupt */
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
+ snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
AVS_ADSP_HIPCCTL_DONE,
AVS_ADSP_HIPCCTL_DONE);
ret = IRQ_HANDLED;
}
/* DSP sent new response to process */
- if (hipc_rsp & SKL_ADSP_HIPCT_BUSY) {
+ if (hipc_rsp & spec->hipc->rsp_busy_mask) {
/* mask busy interrupt */
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
+ snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset,
AVS_ADSP_HIPCCTL_BUSY, 0);
ret = IRQ_WAKE_THREAD;
@@ -349,40 +349,14 @@ irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id)
return ret;
}
-irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id)
-{
- struct avs_dev *adev = dev_id;
- union avs_reply_msg msg;
- u32 hipct, hipcte;
-
- hipct = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
- hipcte = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE);
-
- /* ensure DSP sent new response to process */
- if (!(hipct & SKL_ADSP_HIPCT_BUSY))
- return IRQ_NONE;
-
- msg.primary = hipct;
- msg.ext.val = hipcte;
- avs_dsp_process_response(adev, msg.val);
-
- /* tell DSP we accepted its message */
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT,
- SKL_ADSP_HIPCT_BUSY, SKL_ADSP_HIPCT_BUSY);
- /* unmask busy interrupt */
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL,
- AVS_ADSP_HIPCCTL_BUSY, AVS_ADSP_HIPCCTL_BUSY);
-
- return IRQ_HANDLED;
-}
-
static bool avs_ipc_is_busy(struct avs_ipc *ipc)
{
struct avs_dev *adev = to_avs_dev(ipc->dev);
+ const struct avs_spec *const spec = adev->spec;
u32 hipc_rsp;
- hipc_rsp = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
- return hipc_rsp & SKL_ADSP_HIPCT_BUSY;
+ hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
+ return hipc_rsp & spec->hipc->rsp_busy_mask;
}
static int avs_ipc_wait_busy_completion(struct avs_ipc *ipc, int timeout)
@@ -440,9 +414,10 @@ static void avs_ipc_msg_init(struct avs_ipc *ipc, struct avs_ipc_msg *reply)
static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool read_fwregs)
{
+ const struct avs_spec *const spec = adev->spec;
u64 reg = ULONG_MAX;
- tx->header |= SKL_ADSP_HIPCI_BUSY;
+ tx->header |= spec->hipc->req_busy_mask;
if (read_fwregs)
reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
@@ -450,8 +425,8 @@ static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool r
if (tx->size)
memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size);
- snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCIE, tx->header >> 32);
- snd_hdac_adsp_writel(adev, SKL_ADSP_REG_HIPCI, tx->header & UINT_MAX);
+ snd_hdac_adsp_writel(adev, spec->hipc->req_ext_offset, tx->header >> 32);
+ snd_hdac_adsp_writel(adev, spec->hipc->req_offset, tx->header & UINT_MAX);
}
static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request,
@@ -606,6 +581,7 @@ int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, cons
void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable)
{
+ const struct avs_spec *const spec = adev->spec;
u32 value, mask;
/*
@@ -617,7 +593,7 @@ void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable)
mask = AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY;
value = enable ? mask : 0;
- snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, mask, value);
+ snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, mask, value);
}
int avs_ipc_init(struct avs_ipc *ipc, struct device *dev)
diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c
index e83ce6a35755..8e34d3536082 100644
--- a/sound/soc/intel/avs/loader.c
+++ b/sound/soc/intel/avs/loader.c
@@ -306,7 +306,7 @@ avs_hda_init_rom(struct avs_dev *adev, unsigned int dma_id, bool purge)
}
/* await ROM init */
- ret = snd_hdac_adsp_readq_poll(adev, spec->rom_status, reg,
+ ret = snd_hdac_adsp_readq_poll(adev, spec->sram->rom_status_offset, reg,
(reg & 0xF) == AVS_ROM_INIT_DONE ||
(reg & 0xF) == APL_ROM_FW_ENTERED,
AVS_ROM_INIT_POLLING_US, APL_ROM_INIT_TIMEOUT_US);
diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c
index 06b4394cabd2..f874e4f0d95f 100644
--- a/sound/soc/intel/avs/messages.c
+++ b/sound/soc/intel/avs/messages.c
@@ -381,6 +381,7 @@ int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming)
msg.ext.set_d0ix.wake = enable_pg;
msg.ext.set_d0ix.streaming = streaming;
+ msg.ext.set_d0ix.prevent_pg = !enable_pg;
request.header = msg.val;
diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h
index d0344e242e5b..4e609a08863c 100644
--- a/sound/soc/intel/avs/messages.h
+++ b/sound/soc/intel/avs/messages.h
@@ -145,8 +145,12 @@ union avs_module_msg {
u32 src_queue:3;
} bind_unbind;
struct {
+ /* pre-IceLake */
u32 wake:1;
u32 streaming:1;
+ /* IceLake and onwards */
+ u32 prevent_pg:1;
+ u32 prevent_local_cg:1;
} set_d0ix;
} ext;
};
@@ -359,21 +363,45 @@ enum avs_skl_log_priority {
AVS_SKL_LOG_VERBOSE,
};
-struct skl_log_state {
+struct avs_skl_log_state {
u32 enable;
u32 min_priority;
} __packed;
-struct skl_log_state_info {
+struct avs_skl_log_state_info {
u32 core_mask;
- struct skl_log_state logs_core[];
+ struct avs_skl_log_state logs_core[];
} __packed;
-struct apl_log_state_info {
+struct avs_apl_log_state_info {
u32 aging_timer_period;
u32 fifo_full_timer_period;
u32 core_mask;
- struct skl_log_state logs_core[];
+ struct avs_skl_log_state logs_core[];
+} __packed;
+
+enum avs_icl_log_priority {
+ AVS_ICL_LOG_CRITICAL = 0,
+ AVS_ICL_LOG_HIGH,
+ AVS_ICL_LOG_MEDIUM,
+ AVS_ICL_LOG_LOW,
+ AVS_ICL_LOG_VERBOSE,
+};
+
+enum avs_icl_log_source {
+ AVS_ICL_LOG_INFRA = 0,
+ AVS_ICL_LOG_HAL,
+ AVS_ICL_LOG_MODULE,
+ AVS_ICL_LOG_AUDIO,
+ AVS_ICL_LOG_SENSING,
+ AVS_ICL_LOG_ULP_INFRA,
+};
+
+struct avs_icl_log_state_info {
+ u32 aging_timer_period;
+ u32 fifo_full_timer_period;
+ u32 enable;
+ u32 logs_priorities_mask[];
} __packed;
int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size);
diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
index 3aa16ee8d34c..e785fc2a7008 100644
--- a/sound/soc/intel/avs/path.c
+++ b/sound/soc/intel/avs/path.c
@@ -547,6 +547,33 @@ static int avs_path_module_type_create(struct avs_dev *adev, struct avs_path_mod
return avs_modext_create(adev, mod);
}
+static int avs_path_module_send_init_configs(struct avs_dev *adev, struct avs_path_module *mod)
+{
+ struct avs_soc_component *acomp;
+
+ acomp = to_avs_soc_component(mod->template->owner->owner->owner->owner->comp);
+
+ u32 num_ids = mod->template->num_config_ids;
+ u32 *ids = mod->template->config_ids;
+
+ for (int i = 0; i < num_ids; i++) {
+ struct avs_tplg_init_config *config = &acomp->tplg->init_configs[ids[i]];
+ size_t len = config->length;
+ void *data = config->data;
+ u32 param = config->param;
+ int ret;
+
+ ret = avs_ipc_set_large_config(adev, mod->module_id, mod->instance_id,
+ param, data, len);
+ if (ret) {
+ dev_err(adev->dev, "send initial module config failed: %d\n", ret);
+ return AVS_IPC_RET(ret);
+ }
+ }
+
+ return 0;
+}
+
static void avs_path_module_free(struct avs_dev *adev, struct avs_path_module *mod)
{
kfree(mod);
@@ -580,6 +607,12 @@ avs_path_module_create(struct avs_dev *adev,
return ERR_PTR(ret);
}
+ ret = avs_path_module_send_init_configs(adev, mod);
+ if (ret) {
+ kfree(mod);
+ return ERR_PTR(ret);
+ }
+
return mod;
}
diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c
index 4dfc5a1ebb7c..2cafbc392cdb 100644
--- a/sound/soc/intel/avs/pcm.c
+++ b/sound/soc/intel/avs/pcm.c
@@ -643,6 +643,79 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so
return 0;
}
+static void avs_hda_stream_start(struct hdac_bus *bus, struct hdac_ext_stream *host_stream)
+{
+ struct hdac_stream *first_running = NULL;
+ struct hdac_stream *pos;
+ struct avs_dev *adev = hdac_to_avs(bus);
+
+ list_for_each_entry(pos, &bus->stream_list, list) {
+ if (pos->running) {
+ if (first_running)
+ break; /* more than one running */
+ first_running = pos;
+ }
+ }
+
+ /*
+ * If host_stream is a CAPTURE stream and will be the only one running,
+ * disable L1SEN to avoid sound clipping.
+ */
+ if (!first_running) {
+ if (hdac_stream(host_stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
+ avs_hda_l1sen_enable(adev, false);
+ snd_hdac_stream_start(hdac_stream(host_stream));
+ return;
+ }
+
+ snd_hdac_stream_start(hdac_stream(host_stream));
+ /*
+ * If host_stream is the first stream to break the rule above,
+ * re-enable L1SEN.
+ */
+ if (list_entry_is_head(pos, &bus->stream_list, list) &&
+ first_running->direction == SNDRV_PCM_STREAM_CAPTURE)
+ avs_hda_l1sen_enable(adev, true);
+}
+
+static void avs_hda_stream_stop(struct hdac_bus *bus, struct hdac_ext_stream *host_stream)
+{
+ struct hdac_stream *first_running = NULL;
+ struct hdac_stream *pos;
+ struct avs_dev *adev = hdac_to_avs(bus);
+
+ list_for_each_entry(pos, &bus->stream_list, list) {
+ if (pos == hdac_stream(host_stream))
+ continue; /* ignore stream that is about to be stopped */
+ if (pos->running) {
+ if (first_running)
+ break; /* more than one running */
+ first_running = pos;
+ }
+ }
+
+ /*
+ * If host_stream is a CAPTURE stream and is the only one running,
+ * re-enable L1SEN.
+ */
+ if (!first_running) {
+ snd_hdac_stream_stop(hdac_stream(host_stream));
+ if (hdac_stream(host_stream)->direction == SNDRV_PCM_STREAM_CAPTURE)
+ avs_hda_l1sen_enable(adev, true);
+ return;
+ }
+
+ /*
+ * If by stopping host_stream there is only a single, CAPTURE stream running
+ * left, disable L1SEN to avoid sound clipping.
+ */
+ if (list_entry_is_head(pos, &bus->stream_list, list) &&
+ first_running->direction == SNDRV_PCM_STREAM_CAPTURE)
+ avs_hda_l1sen_enable(adev, false);
+
+ snd_hdac_stream_stop(hdac_stream(host_stream));
+}
+
static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
@@ -664,7 +737,7 @@ static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, stru
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
spin_lock_irqsave(&bus->reg_lock, flags);
- snd_hdac_stream_start(hdac_stream(host_stream));
+ avs_hda_stream_start(bus, host_stream);
spin_unlock_irqrestore(&bus->reg_lock, flags);
/* Timeout on DRSM poll shall not stop the resume so ignore the result. */
@@ -694,7 +767,7 @@ static int avs_dai_fe_trigger(struct snd_pcm_substream *substream, int cmd, stru
dev_err(dai->dev, "pause FE path failed: %d\n", ret);
spin_lock_irqsave(&bus->reg_lock, flags);
- snd_hdac_stream_stop(hdac_stream(host_stream));
+ avs_hda_stream_stop(bus, host_stream);
spin_unlock_irqrestore(&bus->reg_lock, flags);
ret = avs_path_reset(data->path);
diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h
index 078a0ebafa42..6126adca500c 100644
--- a/sound/soc/intel/avs/registers.h
+++ b/sound/soc/intel/avs/registers.h
@@ -50,6 +50,21 @@
#define SKL_ADSP_HIPCIE_DONE BIT(30)
#define SKL_ADSP_HIPCT_BUSY BIT(31)
+/* CNL Intel HD Audio Inter-Processor Communication Registers */
+#define CNL_ADSP_IPC_BASE 0xC0
+#define CNL_ADSP_REG_HIPCTDR (CNL_ADSP_IPC_BASE + 0x00)
+#define CNL_ADSP_REG_HIPCTDA (CNL_ADSP_IPC_BASE + 0x04)
+#define CNL_ADSP_REG_HIPCTDD (CNL_ADSP_IPC_BASE + 0x08)
+#define CNL_ADSP_REG_HIPCIDR (CNL_ADSP_IPC_BASE + 0x10)
+#define CNL_ADSP_REG_HIPCIDA (CNL_ADSP_IPC_BASE + 0x14)
+#define CNL_ADSP_REG_HIPCIDD (CNL_ADSP_IPC_BASE + 0x18)
+#define CNL_ADSP_REG_HIPCCTL (CNL_ADSP_IPC_BASE + 0x28)
+
+#define CNL_ADSP_HIPCTDR_BUSY BIT(31)
+#define CNL_ADSP_HIPCTDA_DONE BIT(31)
+#define CNL_ADSP_HIPCIDR_BUSY BIT(31)
+#define CNL_ADSP_HIPCIDA_DONE BIT(31)
+
/* Intel HD Audio SRAM windows base addresses */
#define SKL_ADSP_SRAM_BASE_OFFSET 0x8000
#define SKL_ADSP_SRAM_WINDOW_SIZE 0x2000
@@ -57,7 +72,7 @@
#define APL_ADSP_SRAM_WINDOW_SIZE 0x20000
/* Constants used when accessing SRAM, space shared with firmware */
-#define AVS_FW_REG_BASE(adev) ((adev)->spec->sram_base_offset)
+#define AVS_FW_REG_BASE(adev) ((adev)->spec->sram->base_offset)
#define AVS_FW_REG_STATUS(adev) (AVS_FW_REG_BASE(adev) + 0x0)
#define AVS_FW_REG_ERROR_CODE(adev) (AVS_FW_REG_BASE(adev) + 0x4)
@@ -72,8 +87,8 @@
/* registry I/O helpers */
#define avs_sram_offset(adev, window_idx) \
- ((adev)->spec->sram_base_offset + \
- (adev)->spec->sram_window_size * (window_idx))
+ ((adev)->spec->sram->base_offset + \
+ (adev)->spec->sram->window_size * (window_idx))
#define avs_sram_addr(adev, window_idx) \
((adev)->dsp_ba + avs_sram_offset(adev, window_idx))
diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c
index 6bb8bbc70442..d19f8953993f 100644
--- a/sound/soc/intel/avs/skl.c
+++ b/sound/soc/intel/avs/skl.c
@@ -12,11 +12,36 @@
#include "avs.h"
#include "messages.h"
+irqreturn_t avs_skl_irq_thread(struct avs_dev *adev)
+{
+ union avs_reply_msg msg;
+ u32 hipct, hipcte;
+
+ hipct = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT);
+ hipcte = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE);
+
+ /* Ensure DSP sent new response to process. */
+ if (!(hipct & SKL_ADSP_HIPCT_BUSY))
+ return IRQ_NONE;
+
+ msg.primary = hipct;
+ msg.ext.val = hipcte;
+ avs_dsp_process_response(adev, msg.val);
+
+ /* Tell DSP we accepted its message. */
+ snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, SKL_ADSP_HIPCT_BUSY, SKL_ADSP_HIPCT_BUSY);
+ /* Unmask busy interrupt. */
+ snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, AVS_ADSP_HIPCCTL_BUSY,
+ AVS_ADSP_HIPCCTL_BUSY);
+
+ return IRQ_HANDLED;
+}
+
static int __maybe_unused
-skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
- u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
+avs_skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
+ u32 fifo_full_period, unsigned long resource_mask, u32 *priorities)
{
- struct skl_log_state_info *info;
+ struct avs_skl_log_state_info *info;
u32 size, num_cores = adev->hw_cfg.dsp_cores;
int ret, i;
@@ -45,7 +70,7 @@ skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_peri
return 0;
}
-int skl_log_buffer_offset(struct avs_dev *adev, u32 core)
+int avs_skl_log_buffer_offset(struct avs_dev *adev, u32 core)
{
return core * avs_log_buffer_size(adev);
}
@@ -53,8 +78,7 @@ int skl_log_buffer_offset(struct avs_dev *adev, u32 core)
/* fw DbgLogWp registers */
#define FW_REGS_DBG_LOG_WP(core) (0x30 + 0x4 * core)
-static int
-skl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
+static int avs_skl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
{
void __iomem *buf;
u16 size, write, offset;
@@ -74,7 +98,7 @@ skl_log_buffer_status(struct avs_dev *adev, union avs_notify_msg *msg)
return 0;
}
-static int skl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
+static int avs_skl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
{
u8 *dump;
@@ -88,33 +112,32 @@ static int skl_coredump(struct avs_dev *adev, union avs_notify_msg *msg)
return 0;
}
-static bool
-skl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
+static bool avs_skl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake)
{
/* unsupported on cAVS 1.5 hw */
return false;
}
-static int skl_set_d0ix(struct avs_dev *adev, bool enable)
+static int avs_skl_set_d0ix(struct avs_dev *adev, bool enable)
{
/* unsupported on cAVS 1.5 hw */
return 0;
}
-const struct avs_dsp_ops skl_dsp_ops = {
+const struct avs_dsp_ops avs_skl_dsp_ops = {
.power = avs_dsp_core_power,
.reset = avs_dsp_core_reset,
.stall = avs_dsp_core_stall,
- .irq_handler = avs_dsp_irq_handler,
- .irq_thread = avs_dsp_irq_thread,
+ .irq_handler = avs_irq_handler,
+ .irq_thread = avs_skl_irq_thread,
.int_control = avs_dsp_interrupt_control,
.load_basefw = avs_cldma_load_basefw,
.load_lib = avs_cldma_load_library,
.transfer_mods = avs_cldma_transfer_modules,
- .log_buffer_offset = skl_log_buffer_offset,
- .log_buffer_status = skl_log_buffer_status,
- .coredump = skl_coredump,
- .d0ix_toggle = skl_d0ix_toggle,
- .set_d0ix = skl_set_d0ix,
+ .log_buffer_offset = avs_skl_log_buffer_offset,
+ .log_buffer_status = avs_skl_log_buffer_status,
+ .coredump = avs_skl_coredump,
+ .d0ix_toggle = avs_skl_d0ix_toggle,
+ .set_d0ix = avs_skl_set_d0ix,
AVS_SET_ENABLE_LOGS_OP(skl)
};
diff --git a/sound/soc/intel/avs/sysfs.c b/sound/soc/intel/avs/sysfs.c
new file mode 100644
index 000000000000..cce21636fbc0
--- /dev/null
+++ b/sound/soc/intel/avs/sysfs.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021-2024 Intel Corporation. All rights reserved.
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#include <linux/sysfs.h>
+#include "avs.h"
+
+static ssize_t fw_version_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct avs_dev *adev = to_avs_dev(dev);
+ struct avs_fw_version *fw_version = &adev->fw_cfg.fw_version;
+
+ return sysfs_emit(buf, "%d.%d.%d.%d\n", fw_version->major, fw_version->minor,
+ fw_version->hotfix, fw_version->build);
+}
+static DEVICE_ATTR_RO(fw_version);
+
+static struct attribute *avs_fw_attrs[] = {
+ &dev_attr_fw_version.attr,
+ NULL
+};
+
+static const struct attribute_group avs_attr_group = {
+ .name = "avs",
+ .attrs = avs_fw_attrs,
+};
+
+const struct attribute_group *avs_attr_groups[] = {
+ &avs_attr_group,
+ NULL
+};
diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c
new file mode 100644
index 000000000000..0e052e7f6bac
--- /dev/null
+++ b/sound/soc/intel/avs/tgl.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021-2024 Intel Corporation. All rights reserved.
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#include "avs.h"
+
+static int avs_tgl_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
+{
+ core_mask &= AVS_MAIN_CORE_MASK;
+
+ if (!core_mask)
+ return 0;
+ return avs_dsp_core_power(adev, core_mask, power);
+}
+
+static int avs_tgl_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset)
+{
+ core_mask &= AVS_MAIN_CORE_MASK;
+
+ if (!core_mask)
+ return 0;
+ return avs_dsp_core_reset(adev, core_mask, reset);
+}
+
+static int avs_tgl_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall)
+{
+ core_mask &= AVS_MAIN_CORE_MASK;
+
+ if (!core_mask)
+ return 0;
+ return avs_dsp_core_stall(adev, core_mask, stall);
+}
+
+const struct avs_dsp_ops avs_tgl_dsp_ops = {
+ .power = avs_tgl_dsp_core_power,
+ .reset = avs_tgl_dsp_core_reset,
+ .stall = avs_tgl_dsp_core_stall,
+ .irq_handler = avs_irq_handler,
+ .irq_thread = avs_cnl_irq_thread,
+ .int_control = avs_dsp_interrupt_control,
+ .load_basefw = avs_icl_load_basefw,
+ .load_lib = avs_hda_load_library,
+ .transfer_mods = avs_hda_transfer_modules,
+ .log_buffer_offset = avs_icl_log_buffer_offset,
+ .log_buffer_status = avs_apl_log_buffer_status,
+ .coredump = avs_apl_coredump,
+ .d0ix_toggle = avs_icl_d0ix_toggle,
+ .set_d0ix = avs_icl_set_d0ix,
+ AVS_SET_ENABLE_LOGS_OP(icl)
+};
diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c
index 48b3c67c9103..13061bd1488b 100644
--- a/sound/soc/intel/avs/topology.c
+++ b/sound/soc/intel/avs/topology.c
@@ -1118,6 +1118,21 @@ static const struct avs_tplg_token_parser module_parsers[] = {
.offset = offsetof(struct avs_tplg_module, ctl_id),
.parse = avs_parse_byte_token,
},
+ {
+ .token = AVS_TKN_MOD_INIT_CONFIG_NUM_IDS_U32,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .offset = offsetof(struct avs_tplg_module, num_config_ids),
+ .parse = avs_parse_byte_token,
+ },
+};
+
+static const struct avs_tplg_token_parser init_config_parsers[] = {
+ {
+ .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .offset = 0,
+ .parse = avs_parse_word_token,
+ },
};
static struct avs_tplg_module *
@@ -1125,17 +1140,50 @@ avs_tplg_module_create(struct snd_soc_component *comp, struct avs_tplg_pipeline
struct snd_soc_tplg_vendor_array *tuples, u32 block_size)
{
struct avs_tplg_module *module;
+ u32 esize;
int ret;
+ /* See where config id block starts. */
+ ret = avs_tplg_vendor_entry_size(tuples, block_size,
+ AVS_TKN_MOD_INIT_CONFIG_ID_U32, &esize);
+ if (ret)
+ return ERR_PTR(ret);
+
module = devm_kzalloc(comp->card->dev, sizeof(*module), GFP_KERNEL);
if (!module)
return ERR_PTR(-ENOMEM);
ret = avs_parse_tokens(comp, module, module_parsers,
- ARRAY_SIZE(module_parsers), tuples, block_size);
+ ARRAY_SIZE(module_parsers), tuples, esize);
if (ret < 0)
return ERR_PTR(ret);
+ block_size -= esize;
+ /* Parse trailing config ids if any. */
+ if (block_size) {
+ u32 num_config_ids = module->num_config_ids;
+ u32 *config_ids;
+
+ if (!num_config_ids)
+ return ERR_PTR(-EINVAL);
+
+ config_ids = devm_kcalloc(comp->card->dev, num_config_ids, sizeof(*config_ids),
+ GFP_KERNEL);
+ if (!config_ids)
+ return ERR_PTR(-ENOMEM);
+
+ tuples = avs_tplg_vendor_array_at(tuples, esize);
+ ret = parse_dictionary_entries(comp, tuples, block_size,
+ config_ids, num_config_ids, sizeof(*config_ids),
+ AVS_TKN_MOD_INIT_CONFIG_ID_U32,
+ init_config_parsers,
+ ARRAY_SIZE(init_config_parsers));
+ if (ret)
+ return ERR_PTR(ret);
+
+ module->config_ids = config_ids;
+ }
+
module->owner = owner;
INIT_LIST_HEAD(&module->node);
@@ -1416,6 +1464,82 @@ avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *o
return template;
}
+static const struct avs_tplg_token_parser mod_init_config_parsers[] = {
+ {
+ .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .offset = offsetof(struct avs_tplg_init_config, id),
+ .parse = avs_parse_word_token,
+ },
+ {
+ .token = AVS_TKN_INIT_CONFIG_PARAM_U8,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
+ .offset = offsetof(struct avs_tplg_init_config, param),
+ .parse = avs_parse_byte_token,
+ },
+ {
+ .token = AVS_TKN_INIT_CONFIG_LENGTH_U32,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .offset = offsetof(struct avs_tplg_init_config, length),
+ .parse = avs_parse_word_token,
+ },
+};
+
+static int avs_tplg_parse_initial_configs(struct snd_soc_component *comp,
+ struct snd_soc_tplg_vendor_array *tuples,
+ u32 block_size)
+{
+ struct avs_soc_component *acomp = to_avs_soc_component(comp);
+ struct avs_tplg *tplg = acomp->tplg;
+ int ret, i;
+
+ /* Parse tuple section telling how many init configs there are. */
+ ret = parse_dictionary_header(comp, tuples, (void **)&tplg->init_configs,
+ &tplg->num_init_configs,
+ sizeof(*tplg->init_configs),
+ AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32);
+ if (ret)
+ return ret;
+
+ block_size -= le32_to_cpu(tuples->size);
+ /* With header parsed, move on to parsing entries. */
+ tuples = avs_tplg_vendor_array_next(tuples);
+
+ for (i = 0; i < tplg->num_init_configs && block_size > 0; i++) {
+ struct avs_tplg_init_config *config = &tplg->init_configs[i];
+ struct snd_soc_tplg_vendor_array *tmp;
+ void *init_config_data;
+ u32 esize;
+
+ /*
+ * Usually to get section length we search for first token of next group of data,
+ * but in this case we can't as tuples are followed by raw data.
+ */
+ tmp = avs_tplg_vendor_array_next(tuples);
+ esize = le32_to_cpu(tuples->size) + le32_to_cpu(tmp->size);
+
+ ret = parse_dictionary_entries(comp, tuples, esize, config, 1, sizeof(*config),
+ AVS_TKN_MOD_INIT_CONFIG_ID_U32,
+ mod_init_config_parsers,
+ ARRAY_SIZE(mod_init_config_parsers));
+
+ block_size -= esize;
+
+ /* handle raw data section */
+ init_config_data = (void *)tuples + esize;
+ esize = config->length;
+
+ config->data = devm_kmemdup(comp->card->dev, init_config_data, esize, GFP_KERNEL);
+ if (!config->data)
+ return -ENOMEM;
+
+ tuples = init_config_data + esize;
+ block_size -= esize;
+ }
+
+ return 0;
+}
+
static int avs_route_load(struct snd_soc_component *comp, int index,
struct snd_soc_dapm_route *route)
{
@@ -1571,6 +1695,7 @@ static int avs_manifest(struct snd_soc_component *comp, int index,
struct snd_soc_tplg_vendor_array *tuples = manifest->priv.array;
struct avs_soc_component *acomp = to_avs_soc_component(comp);
size_t remaining = le32_to_cpu(manifest->priv.size);
+ bool has_init_config = true;
u32 offset;
int ret;
@@ -1668,8 +1793,43 @@ static int avs_manifest(struct snd_soc_component *comp, int index,
remaining -= offset;
tuples = avs_tplg_vendor_array_at(tuples, offset);
+ ret = avs_tplg_vendor_array_lookup(tuples, remaining,
+ AVS_TKN_MANIFEST_NUM_CONDPATH_TMPLS_U32, &offset);
+ if (ret) {
+ dev_err(comp->dev, "condpath lookup failed: %d\n", ret);
+ return ret;
+ }
+
/* Bindings dictionary. */
- return avs_tplg_parse_bindings(comp, tuples, remaining);
+ ret = avs_tplg_parse_bindings(comp, tuples, offset);
+ if (ret < 0)
+ return ret;
+
+ remaining -= offset;
+ tuples = avs_tplg_vendor_array_at(tuples, offset);
+
+ ret = avs_tplg_vendor_array_lookup(tuples, remaining,
+ AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32, &offset);
+ if (ret == -ENOENT) {
+ dev_dbg(comp->dev, "init config lookup failed: %d\n", ret);
+ has_init_config = false;
+ } else if (ret) {
+ dev_err(comp->dev, "init config lookup failed: %d\n", ret);
+ return ret;
+ }
+
+ if (!has_init_config)
+ return 0;
+
+ remaining -= offset;
+ tuples = avs_tplg_vendor_array_at(tuples, offset);
+
+ /* Initial configs dictionary. */
+ ret = avs_tplg_parse_initial_configs(comp, tuples, remaining);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
#define AVS_CONTROL_OPS_VOLUME 257
diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h
index 6e1c8e9b2496..6a59dd766603 100644
--- a/sound/soc/intel/avs/topology.h
+++ b/sound/soc/intel/avs/topology.h
@@ -33,6 +33,9 @@ struct avs_tplg {
u32 num_pplcfgs;
struct avs_tplg_binding *bindings;
u32 num_bindings;
+ u32 num_condpath_tmpls;
+ struct avs_tplg_init_config *init_configs;
+ u32 num_init_configs;
struct list_head path_tmpl_list;
};
@@ -147,6 +150,14 @@ struct avs_tplg_path_template {
struct list_head node;
};
+struct avs_tplg_init_config {
+ u32 id;
+
+ u8 param;
+ size_t length;
+ void *data;
+};
+
struct avs_tplg_path {
u32 id;
@@ -183,6 +194,8 @@ struct avs_tplg_module {
u8 domain;
struct avs_tplg_modcfg_ext *cfg_ext;
u32 ctl_id;
+ u32 num_config_ids;
+ u32 *config_ids;
struct avs_tplg_pipeline *owner;
/* Pipeline modules management. */
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index 8fd5e7f83054..18ac3ce0752e 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -677,6 +677,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
depends on MFD_INTEL_LPSS || COMPILE_TEST
depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST
depends on SOUNDWIRE
+ select SND_SOC_INTEL_SOF_BOARD_HELPERS
select SND_SOC_MAX98363
select SND_SOC_MAX98373_I2C
select SND_SOC_MAX98373_SDW
diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c
index 4f2cb8e52971..088894ff4165 100644
--- a/sound/soc/intel/boards/sof_board_helpers.c
+++ b/sound/soc/intel/boards/sof_board_helpers.c
@@ -73,6 +73,16 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd)
/*
* DAI Link Helpers
*/
+
+/* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
+#define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \
+ SOF_LINK_DMIC01, \
+ SOF_LINK_DMIC16K, \
+ SOF_LINK_IDISP_HDMI, \
+ SOF_LINK_AMP, \
+ SOF_LINK_BT_OFFLOAD, \
+ SOF_LINK_HDMI_IN)
+
static struct snd_soc_dai_link_component dmic_component[] = {
{
.name = "dmic-codec",
@@ -416,6 +426,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
int idx = 0;
int ret;
int ssp_hdmi_in = 0;
+ unsigned long link_order, link;
num_links = calculate_num_links(ctx);
@@ -424,94 +435,140 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
if (!links)
return -ENOMEM;
- /* headphone codec */
- if (ctx->codec_type != CODEC_NONE) {
- ret = sof_intel_board_set_codec_link(dev, &links[idx], idx,
- ctx->codec_type,
- ctx->ssp_codec);
- if (ret) {
- dev_err(dev, "fail to set codec link, ret %d\n", ret);
- return ret;
- }
-
- ctx->codec_link = &links[idx];
- idx++;
- }
-
- /* dmic01 and dmic16k */
- if (ctx->dmic_be_num > 0) {
- /* at least we have dmic01 */
- ret = sof_intel_board_set_dmic_link(dev, &links[idx], idx,
- SOF_DMIC_01);
- if (ret) {
- dev_err(dev, "fail to set dmic01 link, ret %d\n", ret);
- return ret;
- }
-
- idx++;
- }
-
- if (ctx->dmic_be_num > 1) {
- /* set up 2 BE links at most */
- ret = sof_intel_board_set_dmic_link(dev, &links[idx], idx,
- SOF_DMIC_16K);
- if (ret) {
- dev_err(dev, "fail to set dmic16k link, ret %d\n", ret);
- return ret;
- }
-
- idx++;
- }
-
- /* idisp HDMI */
- for (i = 1; i <= ctx->hdmi_num; i++) {
- ret = sof_intel_board_set_intel_hdmi_link(dev, &links[idx], idx,
- i,
- ctx->hdmi.idisp_codec);
- if (ret) {
- dev_err(dev, "fail to set hdmi link, ret %d\n", ret);
- return ret;
+ if (ctx->link_order_overwrite)
+ link_order = ctx->link_order_overwrite;
+ else
+ link_order = DEFAULT_LINK_ORDER;
+
+ dev_dbg(dev, "create dai links, link_order 0x%lx\n", link_order);
+
+ while (link_order) {
+ link = link_order & SOF_LINK_ORDER_MASK;
+ link_order >>= SOF_LINK_ORDER_SHIFT;
+
+ switch (link) {
+ case SOF_LINK_CODEC:
+ /* headphone codec */
+ if (ctx->codec_type == CODEC_NONE)
+ continue;
+
+ ret = sof_intel_board_set_codec_link(dev, &links[idx],
+ idx,
+ ctx->codec_type,
+ ctx->ssp_codec);
+ if (ret) {
+ dev_err(dev, "fail to set codec link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ ctx->codec_link = &links[idx];
+ idx++;
+ break;
+ case SOF_LINK_DMIC01:
+ /* dmic01 */
+ if (ctx->dmic_be_num == 0)
+ continue;
+
+ /* at least we have dmic01 */
+ ret = sof_intel_board_set_dmic_link(dev, &links[idx],
+ idx, SOF_DMIC_01);
+ if (ret) {
+ dev_err(dev, "fail to set dmic01 link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ idx++;
+ break;
+ case SOF_LINK_DMIC16K:
+ /* dmic16k */
+ if (ctx->dmic_be_num <= 1)
+ continue;
+
+ /* set up 2 BE links at most */
+ ret = sof_intel_board_set_dmic_link(dev, &links[idx],
+ idx, SOF_DMIC_16K);
+ if (ret) {
+ dev_err(dev, "fail to set dmic16k link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ idx++;
+ break;
+ case SOF_LINK_IDISP_HDMI:
+ /* idisp HDMI */
+ for (i = 1; i <= ctx->hdmi_num; i++) {
+ ret = sof_intel_board_set_intel_hdmi_link(dev,
+ &links[idx],
+ idx, i,
+ ctx->hdmi.idisp_codec);
+ if (ret) {
+ dev_err(dev, "fail to set hdmi link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ idx++;
+ }
+ break;
+ case SOF_LINK_AMP:
+ /* speaker amp */
+ if (ctx->amp_type == CODEC_NONE)
+ continue;
+
+ ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx],
+ idx,
+ ctx->amp_type,
+ ctx->ssp_amp);
+ if (ret) {
+ dev_err(dev, "fail to set amp link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ ctx->amp_link = &links[idx];
+ idx++;
+ break;
+ case SOF_LINK_BT_OFFLOAD:
+ /* BT audio offload */
+ if (!ctx->bt_offload_present)
+ continue;
+
+ ret = sof_intel_board_set_bt_link(dev, &links[idx], idx,
+ ctx->ssp_bt);
+ if (ret) {
+ dev_err(dev, "fail to set bt link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ idx++;
+ break;
+ case SOF_LINK_HDMI_IN:
+ /* HDMI-In */
+ for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
+ ret = sof_intel_board_set_hdmi_in_link(dev,
+ &links[idx],
+ idx,
+ ssp_hdmi_in);
+ if (ret) {
+ dev_err(dev, "fail to set hdmi-in link, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ idx++;
+ }
+ break;
+ case SOF_LINK_NONE:
+ /* caught here if it's not used as terminator in macro */
+ fallthrough;
+ default:
+ dev_err(dev, "invalid link type %ld\n", link);
+ return -EINVAL;
}
-
- idx++;
- }
-
- /* speaker amp */
- if (ctx->amp_type != CODEC_NONE) {
- ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx], idx,
- ctx->amp_type,
- ctx->ssp_amp);
- if (ret) {
- dev_err(dev, "fail to set amp link, ret %d\n", ret);
- return ret;
- }
-
- ctx->amp_link = &links[idx];
- idx++;
- }
-
- /* BT audio offload */
- if (ctx->bt_offload_present) {
- ret = sof_intel_board_set_bt_link(dev, &links[idx], idx,
- ctx->ssp_bt);
- if (ret) {
- dev_err(dev, "fail to set bt link, ret %d\n", ret);
- return ret;
- }
-
- idx++;
- }
-
- /* HDMI-In */
- for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
- ret = sof_intel_board_set_hdmi_in_link(dev, &links[idx], idx,
- ssp_hdmi_in);
- if (ret) {
- dev_err(dev, "fail to set hdmi-in link, ret %d\n", ret);
- return ret;
- }
-
- idx++;
}
if (idx != num_links) {
@@ -527,6 +584,24 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
}
EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd,
+ const char * const dai_name[], int num_dais)
+{
+ struct snd_soc_dai *dai;
+ int index;
+ int i;
+
+ for (index = 0; index < num_dais; index++)
+ for_each_rtd_codec_dais(rtd, i, dai)
+ if (strstr(dai->name, dai_name[index])) {
+ dev_dbg(rtd->card->dev, "get dai %s\n", dai->name);
+ return dai;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_NS(get_codec_dai_by_name, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+
MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h
index 3b36058118ca..f42d5d640321 100644
--- a/sound/soc/intel/boards/sof_board_helpers.h
+++ b/sound/soc/intel/boards/sof_board_helpers.h
@@ -10,6 +10,29 @@
#include "sof_hdmi_common.h"
#include "sof_ssp_common.h"
+enum {
+ SOF_LINK_NONE = 0,
+ SOF_LINK_CODEC,
+ SOF_LINK_DMIC01,
+ SOF_LINK_DMIC16K,
+ SOF_LINK_IDISP_HDMI,
+ SOF_LINK_AMP,
+ SOF_LINK_BT_OFFLOAD,
+ SOF_LINK_HDMI_IN,
+};
+
+#define SOF_LINK_ORDER_MASK (0xF)
+#define SOF_LINK_ORDER_SHIFT (4)
+
+#define SOF_LINK_ORDER(k1, k2, k3, k4, k5, k6, k7) \
+ ((((k1) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 0)) | \
+ (((k2) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 1)) | \
+ (((k3) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 2)) | \
+ (((k4) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 3)) | \
+ (((k5) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 4)) | \
+ (((k6) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 5)) | \
+ (((k7) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 6)))
+
/*
* sof_rt5682_private: private data for rt5682 machine driver
*
@@ -37,6 +60,7 @@ struct sof_rt5682_private {
* @bt_offload_present: true to create BT offload BE link
* @codec_link: pointer to headset codec dai link
* @amp_link: pointer to speaker amplifier dai link
+ * @link_order_overwrite: custom DAI link order
* @rt5682: private data for rt5682 machine driver
*/
struct sof_card_private {
@@ -59,6 +83,8 @@ struct sof_card_private {
struct snd_soc_dai_link *codec_link;
struct snd_soc_dai_link *amp_link;
+ unsigned long link_order_overwrite;
+
union {
struct sof_rt5682_private rt5682;
};
@@ -92,4 +118,7 @@ int sof_intel_board_set_hdmi_in_link(struct device *dev,
struct snd_soc_dai_link *link, int be_id,
int ssp_hdmi);
+struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd,
+ const char * const dai_name[], int num_dais);
+
#endif /* __SOF_INTEL_BOARD_HELPERS_H */
diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c
index c2442bf8ced0..323b86c42ef9 100644
--- a/sound/soc/intel/boards/sof_cs42l42.c
+++ b/sound/soc/intel/boards/sof_cs42l42.c
@@ -34,25 +34,12 @@
#define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7))
#define SOF_CS42L42_NUM_HDMIDEV(quirk) \
(((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK)
-#define SOF_CS42L42_DAILINK_SHIFT 10
-#define SOF_CS42L42_DAILINK_MASK (GENMASK(24, 10))
-#define SOF_CS42L42_DAILINK(link1, link2, link3, link4, link5) \
- ((((link1) | ((link2) << 3) | ((link3) << 6) | ((link4) << 9) | ((link5) << 12)) << SOF_CS42L42_DAILINK_SHIFT) & SOF_CS42L42_DAILINK_MASK)
#define SOF_BT_OFFLOAD_PRESENT BIT(25)
#define SOF_CS42L42_SSP_BT_SHIFT 26
#define SOF_CS42L42_SSP_BT_MASK (GENMASK(28, 26))
#define SOF_CS42L42_SSP_BT(quirk) \
(((quirk) << SOF_CS42L42_SSP_BT_SHIFT) & SOF_CS42L42_SSP_BT_MASK)
-enum {
- LINK_NONE = 0,
- LINK_HP = 1,
- LINK_SPK = 2,
- LINK_DMIC = 3,
- LINK_HDMI = 4,
- LINK_BT = 5,
-};
-
static struct snd_soc_jack_pin jack_pins[] = {
{
.pin = "Headphone Jack",
@@ -182,156 +169,63 @@ static struct snd_soc_dai_link_component cs42l42_component[] = {
}
};
-static struct snd_soc_dai_link *
-sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type,
- int ssp_codec, int ssp_amp, int ssp_bt,
- int dmic_be_num, int hdmi_num, bool idisp_codec)
+static int
+sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,
+ struct sof_card_private *ctx)
{
- struct snd_soc_dai_link *links;
int ret;
- int id = 0;
- int link_seq;
- int i;
-
- links = devm_kcalloc(dev, sof_audio_card_cs42l42.num_links,
- sizeof(struct snd_soc_dai_link), GFP_KERNEL);
- if (!links)
- goto devm_err;
-
- link_seq = (sof_cs42l42_quirk & SOF_CS42L42_DAILINK_MASK) >> SOF_CS42L42_DAILINK_SHIFT;
-
- while (link_seq) {
- int link_type = link_seq & 0x07;
-
- switch (link_type) {
- case LINK_HP:
- ret = sof_intel_board_set_codec_link(dev, &links[id], id,
- CODEC_CS42L42,
- ssp_codec);
- if (ret) {
- dev_err(dev, "fail to create hp codec dai links, ret %d\n",
- ret);
- goto devm_err;
- }
-
- /* codec-specific fields */
- links[id].codecs = cs42l42_component;
- links[id].num_codecs = ARRAY_SIZE(cs42l42_component);
- links[id].init = sof_cs42l42_init;
- links[id].exit = sof_cs42l42_exit;
- links[id].ops = &sof_cs42l42_ops;
-
- id++;
- break;
- case LINK_SPK:
- if (amp_type != CODEC_NONE) {
- ret = sof_intel_board_set_ssp_amp_link(dev,
- &links[id],
- id,
- amp_type,
- ssp_amp);
- if (ret) {
- dev_err(dev, "fail to create spk amp dai links, ret %d\n",
- ret);
- goto devm_err;
- }
-
- /* codec-specific fields */
- switch (amp_type) {
- case CODEC_MAX98357A:
- max_98357a_dai_link(&links[id]);
- break;
- case CODEC_MAX98360A:
- max_98360a_dai_link(&links[id]);
- break;
- default:
- dev_err(dev, "invalid amp type %d\n",
- amp_type);
- goto devm_err;
- }
-
- id++;
- }
- break;
- case LINK_DMIC:
- if (dmic_be_num > 0) {
- /* at least we have dmic01 */
- ret = sof_intel_board_set_dmic_link(dev,
- &links[id],
- id,
- SOF_DMIC_01);
- if (ret) {
- dev_err(dev, "fail to create dmic01 link, ret %d\n",
- ret);
- goto devm_err;
- }
-
- id++;
- }
-
- if (dmic_be_num > 1) {
- /* set up 2 BE links at most */
- ret = sof_intel_board_set_dmic_link(dev,
- &links[id],
- id,
- SOF_DMIC_16K);
- if (ret) {
- dev_err(dev, "fail to create dmic16k link, ret %d\n",
- ret);
- goto devm_err;
- }
-
- id++;
- }
- break;
- case LINK_HDMI:
- for (i = 1; i <= hdmi_num; i++) {
- ret = sof_intel_board_set_intel_hdmi_link(dev,
- &links[id],
- id, i,
- idisp_codec);
- if (ret) {
- dev_err(dev, "fail to create hdmi link, ret %d\n",
- ret);
- goto devm_err;
- }
-
- id++;
- }
- break;
- case LINK_BT:
- if (sof_cs42l42_quirk & SOF_BT_OFFLOAD_PRESENT) {
- ret = sof_intel_board_set_bt_link(dev,
- &links[id], id,
- ssp_bt);
- if (ret) {
- dev_err(dev, "fail to create bt offload dai links, ret %d\n",
- ret);
- goto devm_err;
- }
-
- id++;
- }
- break;
- case LINK_NONE:
- /* caught here if it's not used as terminator in macro */
- default:
- dev_err(dev, "invalid link type %d\n", link_type);
- goto devm_err;
- }
-
- link_seq >>= 3;
+
+ ret = sof_intel_board_set_dai_link(dev, card, ctx);
+ if (ret)
+ return ret;
+
+ if (!ctx->codec_link) {
+ dev_err(dev, "codec link not available");
+ return -EINVAL;
+ }
+
+ /* codec-specific fields for headphone codec */
+ ctx->codec_link->codecs = cs42l42_component;
+ ctx->codec_link->num_codecs = ARRAY_SIZE(cs42l42_component);
+ ctx->codec_link->init = sof_cs42l42_init;
+ ctx->codec_link->exit = sof_cs42l42_exit;
+ ctx->codec_link->ops = &sof_cs42l42_ops;
+
+ if (ctx->amp_type == CODEC_NONE)
+ return 0;
+
+ if (!ctx->amp_link) {
+ dev_err(dev, "amp link not available");
+ return -EINVAL;
}
- return links;
-devm_err:
- return NULL;
+ /* codec-specific fields for speaker amplifier */
+ switch (ctx->amp_type) {
+ case CODEC_MAX98357A:
+ max_98357a_dai_link(ctx->amp_link);
+ break;
+ case CODEC_MAX98360A:
+ max_98360a_dai_link(ctx->amp_link);
+ break;
+ default:
+ dev_err(dev, "invalid amp type %d\n", ctx->amp_type);
+ return -EINVAL;
+ }
+
+ return 0;
}
+#define GLK_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \
+ SOF_LINK_CODEC, \
+ SOF_LINK_DMIC01, \
+ SOF_LINK_IDISP_HDMI, \
+ SOF_LINK_NONE, \
+ SOF_LINK_NONE, \
+ SOF_LINK_NONE)
+
static int sof_audio_probe(struct platform_device *pdev)
{
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
- struct snd_soc_dai_link *dai_links;
struct sof_card_private *ctx;
int ret;
@@ -348,6 +242,9 @@ static int sof_audio_probe(struct platform_device *pdev)
if (soc_intel_is_glk()) {
ctx->dmic_be_num = 1;
ctx->hdmi_num = 3;
+
+ /* overwrite the DAI link order for GLK boards */
+ ctx->link_order_overwrite = GLK_LINK_ORDER;
} else {
ctx->dmic_be_num = 2;
ctx->hdmi_num = (sof_cs42l42_quirk & SOF_CS42L42_NUM_HDMIDEV_MASK) >>
@@ -371,25 +268,13 @@ static int sof_audio_probe(struct platform_device *pdev)
ctx->ssp_codec = sof_cs42l42_quirk & SOF_CS42L42_SSP_CODEC_MASK;
- /* compute number of dai links */
- sof_audio_card_cs42l42.num_links = 1 + ctx->dmic_be_num + ctx->hdmi_num;
-
- if (ctx->amp_type != CODEC_NONE)
- sof_audio_card_cs42l42.num_links++;
- if (sof_cs42l42_quirk & SOF_BT_OFFLOAD_PRESENT) {
+ if (sof_cs42l42_quirk & SOF_BT_OFFLOAD_PRESENT)
ctx->bt_offload_present = true;
- sof_audio_card_cs42l42.num_links++;
- }
-
- dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type,
- ctx->ssp_codec, ctx->ssp_amp,
- ctx->ssp_bt, ctx->dmic_be_num,
- ctx->hdmi_num,
- ctx->hdmi.idisp_codec);
- if (!dai_links)
- return -ENOMEM;
- sof_audio_card_cs42l42.dai_link = dai_links;
+ /* update dai_link */
+ ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_cs42l42, ctx);
+ if (ret)
+ return ret;
sof_audio_card_cs42l42.dev = &pdev->dev;
@@ -409,14 +294,12 @@ static const struct platform_device_id board_ids[] = {
{
.name = "glk_cs4242_mx98357a",
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) |
- SOF_CS42L42_SSP_AMP(1)) |
- SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE),
+ SOF_CS42L42_SSP_AMP(1)),
},
{
.name = "jsl_cs4242_mx98360a",
.driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) |
- SOF_CS42L42_SSP_AMP(1)) |
- SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_NONE),
+ SOF_CS42L42_SSP_AMP(1)),
},
{
.name = "adl_mx98360a_cs4242",
@@ -424,8 +307,7 @@ static const struct platform_device_id board_ids[] = {
SOF_CS42L42_SSP_AMP(1) |
SOF_CS42L42_NUM_HDMIDEV(4) |
SOF_BT_OFFLOAD_PRESENT |
- SOF_CS42L42_SSP_BT(2) |
- SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_BT)),
+ SOF_CS42L42_SSP_BT(2)),
},
{ }
};
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index cd50f26d1edb..640d17c6cd35 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -158,46 +158,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
.callback = sof_rt5682_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
- DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S"),
- },
- .driver_data = (void *)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(2) |
- SOF_RT5682_SSP_AMP(0) |
- SOF_RT5682_NUM_HDMIDEV(3) |
- SOF_BT_OFFLOAD_SSP(1) |
- SOF_SSP_BT_OFFLOAD_PRESENT
- ),
- },
- {
- .callback = sof_rt5682_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
- DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_DISCRETE_I2S_BT"),
- },
- .driver_data = (void *)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(2) |
- SOF_RT5682_SSP_AMP(0) |
- SOF_RT5682_NUM_HDMIDEV(3) |
- SOF_BT_OFFLOAD_SSP(1) |
- SOF_SSP_BT_OFFLOAD_PRESENT
- ),
- },
- {
- .callback = sof_rt5682_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
- DMI_MATCH(DMI_OEM_STRING, "AUDIO-ALC1019_ALC5682I_I2S"),
- },
- .driver_data = (void *)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(2) |
- SOF_RT5682_SSP_AMP(0) |
- SOF_RT5682_NUM_HDMIDEV(3)
- ),
- },
- {
- .callback = sof_rt5682_quirk_cb,
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
@@ -810,54 +770,13 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_SSP_AMP(1)),
},
{
- .name = "jsl_rt5682_rt1015",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1)),
- },
- {
- .name = "jsl_rt5682_mx98360",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1)),
- },
- {
- .name = "jsl_rt5682_rt1015p",
+ .name = "jsl_rt5682_def",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_RT5682_SSP_AMP(1)),
},
{
- .name = "jsl_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0)),
- },
- {
- .name = "jsl_rt5650",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1)),
- },
- {
- .name = "tgl_mx98357_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .name = "tgl_rt1011_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .name = "tgl_mx98373_rt5682",
+ .name = "tgl_rt5682_def",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_RT5682_SSP_AMP(1) |
@@ -866,7 +785,7 @@ static const struct platform_device_id board_ids[] = {
SOF_SSP_BT_OFFLOAD_PRESENT),
},
{
- .name = "adl_mx98373_rt5682",
+ .name = "adl_rt5682_def",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_RT5682_SSP_AMP(1) |
@@ -882,41 +801,6 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_NUM_HDMIDEV(4)),
},
{
- .name = "adl_max98390_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .name = "adl_mx98360_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .name = "adl_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .name = "adl_rt1019_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
.name = "adl_rt5682_c1_h02",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(1) |
@@ -925,15 +809,6 @@ static const struct platform_device_id board_ids[] = {
SOF_HDMI_CAPTURE_SSP_MASK(0x5)),
},
{
- .name = "adl_rt5650",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
.name = "rpl_mx98357_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
@@ -941,16 +816,7 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_NUM_HDMIDEV(4)),
},
{
- .name = "rpl_mx98360_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(0) |
- SOF_RT5682_SSP_AMP(1) |
- SOF_RT5682_NUM_HDMIDEV(4) |
- SOF_BT_OFFLOAD_SSP(2) |
- SOF_SSP_BT_OFFLOAD_PRESENT),
- },
- {
- .name = "rpl_rt1019_rt5682",
+ .name = "rpl_rt5682_def",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(0) |
SOF_RT5682_SSP_AMP(1) |
@@ -983,14 +849,7 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_NUM_HDMIDEV(3)),
},
{
- .name = "mtl_rt1019_rt5682",
- .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
- SOF_RT5682_SSP_CODEC(2) |
- SOF_RT5682_SSP_AMP(0) |
- SOF_RT5682_NUM_HDMIDEV(3)),
- },
- {
- .name = "mtl_rt5650",
+ .name = "mtl_rt5682_def",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
SOF_RT5682_SSP_AMP(0) |
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 300391fbc2fc..08f330ed5c2e 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -236,6 +236,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_SDW_PCH_DMIC |
RT711_JD2_100K),
},
+ {
+ /* NUC15 LAPRC710 skews */
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_SDW_PCH_DMIC |
+ RT711_JD2_100K),
+ },
/* TigerLake-SDCA devices */
{
.callback = sof_sdw_quirk_cb,
@@ -650,7 +661,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt700-aif1",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
- .init = sof_sdw_rt700_init,
+ .rtd_init = rt700_rtd_init,
},
},
.dai_num = 1,
@@ -666,6 +677,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
+ .rtd_init = rt_sdca_jack_rtd_init,
},
},
.dai_num = 1,
@@ -681,6 +693,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt711_init,
.exit = sof_sdw_rt711_exit,
+ .rtd_init = rt711_rtd_init,
},
},
.dai_num = 1,
@@ -696,13 +709,14 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
+ .rtd_init = rt_sdca_jack_rtd_init,
},
{
.direction = {true, false},
.dai_name = "rt712-sdca-aif2",
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
- .init = sof_sdw_rt712_spk_init,
+ .rtd_init = rt712_spk_rtd_init,
},
},
.dai_num = 2,
@@ -716,7 +730,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt712-sdca-dmic-aif1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt712_sdca_dmic_init,
+ .rtd_init = rt712_sdca_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -732,6 +746,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
.init = sof_sdw_rt_sdca_jack_init,
.exit = sof_sdw_rt_sdca_jack_exit,
+ .rtd_init = rt_sdca_jack_rtd_init,
},
},
.dai_num = 1,
@@ -745,7 +760,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt712-sdca-dmic-aif1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt712_sdca_dmic_init,
+ .rtd_init = rt712_sdca_dmic_rtd_init,
},
},
.dai_num = 1,
@@ -761,6 +776,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
+ .rtd_init = rt_amp_spk_rtd_init,
},
},
.dai_num = 1,
@@ -776,6 +792,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
+ .rtd_init = rt_amp_spk_rtd_init,
},
},
.dai_num = 1,
@@ -790,6 +807,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_rt_amp_init,
.exit = sof_sdw_rt_amp_exit,
+ .rtd_init = rt_amp_spk_rtd_init,
},
},
.dai_num = 1,
@@ -804,7 +822,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt715_sdca_init,
+ .rtd_init = rt715_sdca_rtd_init,
},
},
.dai_num = 1,
@@ -819,7 +837,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt715_sdca_init,
+ .rtd_init = rt715_sdca_rtd_init,
},
},
.dai_num = 1,
@@ -834,7 +852,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt715_init,
+ .rtd_init = rt715_rtd_init,
},
},
.dai_num = 1,
@@ -849,7 +867,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt715-aif2",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_rt715_init,
+ .rtd_init = rt715_rtd_init,
},
},
.dai_num = 1,
@@ -893,6 +911,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_maxim_init,
+ .rtd_init = maxim_spk_rtd_init,
},
},
.dai_num = 1,
@@ -906,6 +925,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
.init = sof_sdw_maxim_init,
+ .rtd_init = maxim_spk_rtd_init,
},
},
.dai_num = 1,
@@ -918,7 +938,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "rt5682-sdw",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
- .init = sof_sdw_rt5682_init,
+ .rtd_init = rt5682_rtd_init,
},
},
.dai_num = 1,
@@ -932,6 +952,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_type = SOF_SDW_DAI_TYPE_AMP,
.dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID},
.init = sof_sdw_cs_amp_init,
+ .rtd_init = cs_spk_rtd_init,
},
},
.dai_num = 1,
@@ -944,7 +965,7 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "cs42l42-sdw",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID},
- .init = sof_sdw_cs42l42_init,
+ .rtd_init = cs42l42_rtd_init,
},
},
.dai_num = 1,
@@ -958,14 +979,14 @@ static struct sof_sdw_codec_info codec_info_list[] = {
.dai_name = "cs42l43-dp5",
.dai_type = SOF_SDW_DAI_TYPE_JACK,
.dailink = {SDW_JACK_OUT_DAI_ID, SDW_UNUSED_DAI_ID},
- .init = sof_sdw_cs42l43_hs_init,
+ .rtd_init = cs42l43_hs_rtd_init,
},
{
.direction = {false, true},
.dai_name = "cs42l43-dp1",
.dai_type = SOF_SDW_DAI_TYPE_MIC,
.dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID},
- .init = sof_sdw_cs42l43_dmic_init,
+ .rtd_init = cs42l43_dmic_rtd_init,
},
{
.direction = {false, true},
@@ -1387,6 +1408,56 @@ static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps,
}
}
+static inline int find_codec_info_dai(const char *dai_name, int *dai_index)
+{
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
+ for (j = 0; j < codec_info_list[i].dai_num; j++) {
+ if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) {
+ *dai_index = j;
+ return i;
+ }
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct sof_sdw_codec_info *codec_info;
+ struct snd_soc_dai *dai;
+ int codec_index;
+ int dai_index;
+ int ret;
+ int i;
+
+ for_each_rtd_codec_dais(rtd, i, dai) {
+ codec_index = find_codec_info_dai(dai->name, &dai_index);
+ if (codec_index < 0)
+ return -EINVAL;
+
+ codec_info = &codec_info_list[codec_index];
+ /*
+ * A codec dai can be connected to different dai links for capture and playback,
+ * but we only need to call the rtd_init function once.
+ * The rtd_init for each codec dai is independent. So, the order of rtd_init
+ * doesn't matter.
+ */
+ if (codec_info->dais[dai_index].rtd_init_done)
+ continue;
+ if (codec_info->dais[dai_index].rtd_init) {
+ ret = codec_info->dais[dai_index].rtd_init(rtd);
+ if (ret)
+ return ret;
+ }
+ codec_info->dais[dai_index].rtd_init_done = true;
+ }
+
+ return 0;
+}
+
static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};
static int create_sdw_dailink(struct snd_soc_card *card, int *link_index,
@@ -1547,7 +1618,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index,
init_dai_link(dev, dai_links + *link_index, be_id, name,
playback, capture, cpus, cpu_dai_num, codecs, codec_num,
- NULL, &sdw_ops);
+ sof_sdw_rtd_init, &sdw_ops);
/*
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations
@@ -1696,15 +1767,21 @@ out:
return codec_index;
for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) {
+ int current_be_id;
+
ret = create_sdw_dailink(card, &link_index, dai_links,
sdw_be_num, adr_link,
codec_conf, codec_conf_num,
- &be_id, &codec_conf_index,
+ &current_be_id, &codec_conf_index,
&ignore_pch_dmic, append_dai_type, i, j);
if (ret < 0) {
dev_err(dev, "failed to create dai link %d\n", link_index);
return ret;
}
+
+ /* Update the be_id to match the highest ID used for SDW link */
+ if (be_id < current_be_id)
+ be_id = current_be_id;
}
if (aggregation && endpoint->aggregated)
@@ -1880,6 +1957,7 @@ static void mc_dailink_exit_loop(struct snd_soc_card *card)
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
for (j = 0; j < codec_info_list[i].dai_num; j++) {
+ codec_info_list[i].dais[j].rtd_init_done = false;
/* Check each dai in codec_info_lis to see if it is used in the link */
if (!codec_info_list[i].dais[j].exit)
continue;
diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h
index f16456945edb..b1d57034361c 100644
--- a/sound/soc/intel/boards/sof_sdw_common.h
+++ b/sound/soc/intel/boards/sof_sdw_common.h
@@ -78,6 +78,8 @@ struct sof_sdw_dai_info {
struct sof_sdw_codec_info *info,
bool playback);
int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
+ int (*rtd_init)(struct snd_soc_pcm_runtime *rtd);
+ bool rtd_init_done; /* Indicate that the rtd_init callback is done */
};
struct sof_sdw_codec_info {
@@ -137,25 +139,6 @@ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
bool playback);
int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
-/* RT712-SDCA support */
-int sof_sdw_rt712_spk_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-int sof_sdw_rt712_sdca_dmic_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
-/* RT700 support */
-int sof_sdw_rt700_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
/* RT1308 I2S support */
extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops;
@@ -167,22 +150,6 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card,
bool playback);
int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link);
-/* RT1316 support */
-
-/* RT715 support */
-int sof_sdw_rt715_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
-/* RT715-SDCA support */
-int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
/* RT722-SDCA support */
int sof_sdw_rt722_spk_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
@@ -202,37 +169,28 @@ int sof_sdw_maxim_init(struct snd_soc_card *card,
struct sof_sdw_codec_info *info,
bool playback);
-/* RT5682 support */
-int sof_sdw_rt5682_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
-/* CS42L42 support */
-int sof_sdw_cs42l42_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
-/* CS42L43 support */
-int sof_sdw_cs42l43_hs_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
-int sof_sdw_cs42l43_dmic_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback);
-
/* CS AMP support */
int sof_sdw_cs_amp_init(struct snd_soc_card *card,
const struct snd_soc_acpi_link_adr *link,
struct snd_soc_dai_link *dai_links,
struct sof_sdw_codec_info *info,
bool playback);
+
+/* dai_link init callbacks */
+
+int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd);
+int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd);
+
#endif
diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c
index 436f41086da6..0dc297f7de01 100644
--- a/sound/soc/intel/boards/sof_sdw_cs42l42.c
+++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c
@@ -15,6 +15,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
+#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget cs42l42_widgets[] = {
@@ -46,15 +47,24 @@ static struct snd_soc_jack_pin cs42l42_jack_pins[] = {
},
};
-static int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd)
+static const char * const jack_codecs[] = {
+ "cs42l42"
+};
+
+int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_component *component;
struct snd_soc_jack *jack;
int ret;
+ codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs));
+ if (!codec_dai)
+ return -EINVAL;
+
+ component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:cs42l42",
card->components);
@@ -111,21 +121,4 @@ static int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-
-int sof_sdw_cs42l42_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- /*
- * headset should be initialized once.
- * Do it with dai link for playback.
- */
- if (!playback)
- return 0;
-
- dai_links->init = cs42l42_rtd_init;
-
- return 0;
-}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c
index 360f11b72aa2..a9b6edac2ecd 100644
--- a/sound/soc/intel/boards/sof_sdw_cs42l43.c
+++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c
@@ -50,7 +50,7 @@ static struct snd_soc_jack_pin sof_jack_pins[] = {
},
};
-static int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd)
+int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card);
@@ -108,20 +108,7 @@ static int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_cs42l43_hs_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info,
- bool playback)
-{
- /*
- * No need to test if (!playback) like other codecs as cs42l43 uses separated dai for
- * playback and capture, and sof_sdw_cs42l43_init is only linked to the playback dai.
- */
- dai_links->init = cs42l43_hs_rtd_init;
-
- return 0;
-}
-
-static int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
+int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
@@ -146,11 +133,3 @@ static int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_cs42l43_dmic_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = cs42l43_dmic_rtd_init;
-
- return 0;
-}
diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c
index f88c01552a92..56cf75bc6cc4 100644
--- a/sound/soc/intel/boards/sof_sdw_cs_amp.c
+++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c
@@ -18,7 +18,7 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
SND_SOC_DAPM_SPK("Speakers", NULL),
};
-static int cs_spk_init(struct snd_soc_pcm_runtime *rtd)
+int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
const char *dai_name = rtd->dai_link->codecs->dai_name;
struct snd_soc_card *card = rtd->card;
@@ -67,7 +67,6 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card,
return 0;
info->amp_num++;
- dai_links->init = cs_spk_init;
return 0;
}
diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c
index e36b8d8c70c9..034730432671 100644
--- a/sound/soc/intel/boards/sof_sdw_maxim.c
+++ b/sound/soc/intel/boards/sof_sdw_maxim.c
@@ -27,7 +27,7 @@ static const struct snd_kcontrol_new maxim_controls[] = {
SOC_DAPM_PIN_SWITCH("Right Spk"),
};
-static int spk_init(struct snd_soc_pcm_runtime *rtd)
+int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
@@ -145,8 +145,6 @@ int sof_sdw_maxim_init(struct snd_soc_card *card,
bool playback)
{
info->amp_num++;
- if (info->amp_num == 2)
- dai_links->init = spk_init;
maxim_part_id = info->part_id;
switch (maxim_part_id) {
diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c
index 7b7c9def398b..6b008a5a343b 100644
--- a/sound/soc/intel/boards/sof_sdw_rt5682.c
+++ b/sound/soc/intel/boards/sof_sdw_rt5682.c
@@ -15,6 +15,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
+#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt5682_widgets[] = {
@@ -45,15 +46,24 @@ static struct snd_soc_jack_pin rt5682_jack_pins[] = {
},
};
-static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
+static const char * const jack_codecs[] = {
+ "rt5682"
+};
+
+int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_component *component;
struct snd_soc_jack *jack;
int ret;
+ codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs));
+ if (!codec_dai)
+ return -EINVAL;
+
+ component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:rt5682",
card->components);
@@ -110,21 +120,4 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-
-int sof_sdw_rt5682_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- /*
- * headset should be initialized once.
- * Do it with dai link for playback.
- */
- if (!playback)
- return 0;
-
- dai_links->init = rt5682_rtd_init;
-
- return 0;
-}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c
index a1714afe8515..88e785a54b16 100644
--- a/sound/soc/intel/boards/sof_sdw_rt700.c
+++ b/sound/soc/intel/boards/sof_sdw_rt700.c
@@ -13,6 +13,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
+#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt700_widgets[] = {
@@ -45,15 +46,24 @@ static struct snd_soc_jack_pin rt700_jack_pins[] = {
},
};
-static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
+static const char * const jack_codecs[] = {
+ "rt700"
+};
+
+int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_component *component;
struct snd_soc_jack *jack;
int ret;
+ codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs));
+ if (!codec_dai)
+ return -EINVAL;
+
+ component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:rt700",
card->components);
@@ -109,21 +119,4 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-
-int sof_sdw_rt700_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- /*
- * headset should be initialized once.
- * Do it with dai link for playback.
- */
- if (!playback)
- return 0;
-
- dai_links->init = rt700_rtd_init;
-
- return 0;
-}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c
index 38782fdfcf15..cdd1587b246c 100644
--- a/sound/soc/intel/boards/sof_sdw_rt711.c
+++ b/sound/soc/intel/boards/sof_sdw_rt711.c
@@ -15,6 +15,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
+#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
/*
@@ -69,15 +70,24 @@ static struct snd_soc_jack_pin rt711_jack_pins[] = {
},
};
-static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
+static const char * const jack_codecs[] = {
+ "rt711"
+};
+
+int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_component *component;
struct snd_soc_jack *jack;
int ret;
+ codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs));
+ if (!codec_dai)
+ return -EINVAL;
+
+ component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:rt711",
card->components);
@@ -176,7 +186,6 @@ int sof_sdw_rt711_init(struct snd_soc_card *card,
}
ctx->headset_codec_dev = sdw_dev;
- dai_links->init = rt711_rtd_init;
-
return 0;
}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c
index 3092029419df..ebb4b58c198b 100644
--- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c
@@ -13,6 +13,7 @@
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
+#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
static const struct snd_soc_dapm_widget rt712_spk_widgets[] = {
@@ -34,7 +35,7 @@ static const struct snd_kcontrol_new rt712_spk_controls[] = {
SOC_DAPM_PIN_SWITCH("Speaker"),
};
-static int rt712_spk_init(struct snd_soc_pcm_runtime *rtd)
+int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
int ret;
@@ -66,23 +67,21 @@ static int rt712_spk_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-int sof_sdw_rt712_spk_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = rt712_spk_init;
-
- return 0;
-}
+static const char * const dmics[] = {
+ "rt712-sdca-dmic"
+};
-static int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
+int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_component *component;
+
+ codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics));
+ if (!codec_dai)
+ return -EINVAL;
+ component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s mic:%s",
card->components, component->name_prefix);
@@ -91,14 +90,4 @@ static int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-
-int sof_sdw_rt712_sdca_dmic_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = rt712_sdca_dmic_rtd_init;
-
- return 0;
-}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c
index 7c068dc6b9cf..b5a886cd595d 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715.c
@@ -11,7 +11,7 @@
#include <sound/soc-acpi.h>
#include "sof_sdw_common.h"
-static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
+int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
@@ -24,13 +24,3 @@ static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-int sof_sdw_rt715_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = rt715_rtd_init;
-
- return 0;
-}
diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
index ca0cf3db2e4d..4b37a8a6dd2e 100644
--- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
+++ b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c
@@ -11,7 +11,7 @@
#include <sound/soc-acpi.h>
#include "sof_sdw_common.h"
-static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
+int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
@@ -24,13 +24,3 @@ static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-int sof_sdw_rt715_sdca_init(struct snd_soc_card *card,
- const struct snd_soc_acpi_link_adr *link,
- struct snd_soc_dai_link *dai_links,
- struct sof_sdw_codec_info *info,
- bool playback)
-{
- dai_links->init = rt715_sdca_rtd_init;
-
- return 0;
-}
diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c
index 436975b6bdc1..202edab95000 100644
--- a/sound/soc/intel/boards/sof_sdw_rt_amp.c
+++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c
@@ -185,12 +185,14 @@ static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_
return rt1318_map;
}
-static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
+int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
const struct snd_soc_dapm_route *rt_amp_map;
char codec_name[CODEC_NAME_SIZE];
+ struct snd_soc_dai *dai;
int ret;
+ int i;
rt_amp_map = get_codec_name_and_route(rtd, codec_name);
@@ -214,40 +216,16 @@ static int first_spk_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
- ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2);
- if (ret)
- dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret);
-
- return ret;
-}
-
-static int second_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_card *card = rtd->card;
- const struct snd_soc_dapm_route *rt_amp_map;
- char codec_name[CODEC_NAME_SIZE];
- int ret;
-
- rt_amp_map = get_codec_name_and_route(rtd, codec_name);
-
- ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map + 2, 2);
- if (ret)
- dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret);
+ for_each_rtd_codec_dais(rtd, i, dai) {
+ if (strstr(dai->component->name_prefix, "-1"))
+ ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2);
+ else if (strstr(dai->component->name_prefix, "-2"))
+ ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map + 2, 2);
+ }
return ret;
}
-static int all_spk_init(struct snd_soc_pcm_runtime *rtd)
-{
- int ret;
-
- ret = first_spk_init(rtd);
- if (ret)
- return ret;
-
- return second_spk_init(rtd);
-}
-
static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -317,8 +295,6 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card,
return 0;
info->amp_num++;
- if (info->amp_num == 1)
- dai_links->init = first_spk_init;
if (info->amp_num == 2) {
sdw_dev1 = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
@@ -342,17 +318,6 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card,
return ret;
}
ctx->amp_dev2 = sdw_dev2;
-
- /*
- * if two amps are in one dai link, the init function
- * in this dai link will be first set for the first speaker,
- * and it should be reset to initialize all speakers when
- * the second speaker is found.
- */
- if (dai_links->init)
- dai_links->init = all_spk_init;
- else
- dai_links->init = second_spk_init;
}
return 0;
diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
index d9c283829fc7..5253d8332780 100644
--- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
+++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c
@@ -15,6 +15,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-dapm.h>
#include <sound/jack.h>
+#include "sof_board_helpers.h"
#include "sof_sdw_common.h"
/*
@@ -84,15 +85,24 @@ static struct snd_soc_jack_pin rt_sdca_jack_pins[] = {
},
};
-static int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd)
+static const char * const jack_codecs[] = {
+ "rt711", "rt712", "rt713"
+};
+
+int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct mc_private *ctx = snd_soc_card_get_drvdata(card);
- struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
- struct snd_soc_component *component = codec_dai->component;
+ struct snd_soc_dai *codec_dai;
+ struct snd_soc_component *component;
struct snd_soc_jack *jack;
int ret;
+ codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs));
+ if (!codec_dai)
+ return -EINVAL;
+
+ component = codec_dai->component;
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
"%s hs:%s-sdca",
card->components, component->name_prefix);
@@ -209,7 +219,6 @@ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
}
ctx->headset_codec_dev = sdw_dev;
- dai_links->init = rt_sdca_jack_rtd_init;
-
return 0;
}
+MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
diff --git a/sound/soc/intel/boards/sof_ssp_common.h b/sound/soc/intel/boards/sof_ssp_common.h
index 6d827103479b..d24888bc99fd 100644
--- a/sound/soc/intel/boards/sof_ssp_common.h
+++ b/sound/soc/intel/boards/sof_ssp_common.h
@@ -67,6 +67,14 @@ enum sof_ssp_codec {
enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev);
enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev);
+
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON)
const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type);
+#else
+static inline const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type)
+{
+ return NULL;
+}
+#endif
#endif /* __SOF_SSP_COMMON_H */
diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
index 346bec000306..5454c6d9ab5b 100644
--- a/sound/soc/intel/catpt/dsp.c
+++ b/sound/soc/intel/catpt/dsp.c
@@ -387,7 +387,7 @@ int catpt_dsp_power_down(struct catpt_dev *cdev)
mask = cdev->spec->d3srampgd_bit | cdev->spec->d3pgd_bit;
catpt_updatel_pci(cdev, VDRTCTL0, mask, cdev->spec->d3pgd_bit);
- catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot);
+ catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, (__force u32)PCI_D3hot);
/* give hw time to drop off */
udelay(50);
@@ -411,7 +411,7 @@ int catpt_dsp_power_up(struct catpt_dev *cdev)
val = mask & (~CATPT_VDRTCTL2_DTCGE);
catpt_updatel_pci(cdev, VDRTCTL2, mask, val);
- catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0);
+ catpt_updatel_pci(cdev, PMCS, PCI_PM_CTRL_STATE_MASK, (__force u32)PCI_D0);
/* SRAM power gating none */
mask = cdev->spec->d3srampgd_bit | cdev->spec->d3pgd_bit;
diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
index d3d913458c60..0da79a3ba1f0 100644
--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
@@ -500,7 +500,7 @@ static struct snd_soc_acpi_codecs adl_rt5650_amp = {
struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
{
.comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_mx98373_rt5682",
+ .drv_name = "adl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_max98373_amp,
.sof_tplg_filename = "sof-adl-max98373-rt5682.tplg",
@@ -514,7 +514,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
},
{
.comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_mx98360_rt5682",
+ .drv_name = "adl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_max98360a_amp,
.sof_tplg_filename = "sof-adl-max98360a-rt5682.tplg",
@@ -542,7 +542,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
},
{
.comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt1019_rt5682",
+ .drv_name = "adl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_rt1019p_amp,
.sof_tplg_filename = "sof-adl-rt1019-rt5682.tplg",
@@ -568,7 +568,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
},
{
.comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_max98390_rt5682",
+ .drv_name = "adl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_max98390_amp,
.sof_tplg_filename = "sof-adl-max98390-rt5682.tplg",
@@ -582,7 +582,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
},
{
.comp_ids = &adl_rt5682_rt5682s_hp,
- .drv_name = "adl_rt5682",
+ .drv_name = "adl_rt5682_def",
.sof_tplg_filename = "sof-adl-rt5682.tplg",
},
{
@@ -609,7 +609,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
},
{
.id = "10EC5650",
- .drv_name = "adl_rt5650",
+ .drv_name = "adl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &adl_rt5650_amp,
.sof_tplg_filename = "sof-adl-rt5650.tplg",
diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
index 342bbbb48ca7..a6ac2525df17 100644
--- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c
@@ -66,28 +66,28 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
},
{
.comp_ids = &rt5682_rt5682s_hp,
- .drv_name = "jsl_rt5682_rt1015",
+ .drv_name = "jsl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rt1015_spk,
.sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg",
},
{
.comp_ids = &rt5682_rt5682s_hp,
- .drv_name = "jsl_rt5682_rt1015p",
+ .drv_name = "jsl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rt1015p_spk,
.sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg",
},
{
.comp_ids = &rt5682_rt5682s_hp,
- .drv_name = "jsl_rt5682_mx98360",
+ .drv_name = "jsl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &mx98360a_spk,
.sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg",
},
{
.comp_ids = &rt5682_rt5682s_hp,
- .drv_name = "jsl_rt5682",
+ .drv_name = "jsl_rt5682_def",
.sof_tplg_filename = "sof-jsl-rt5682.tplg",
},
{
@@ -107,7 +107,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = {
},
{
.id = "10EC5650",
- .drv_name = "jsl_rt5650",
+ .drv_name = "jsl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rt5650_spk,
.sof_tplg_filename = "sof-jsl-rt5650.tplg",
diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
index 5897bb6b28b8..74d6dcd7471f 100644
--- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
@@ -36,6 +36,46 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
+static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+/*
+ * RT722 is a multi-function codec, three endpoints are created for
+ * its headset, amp and dmic functions.
+ */
+static const struct snd_soc_acpi_endpoint rt722_endpoints[] = {
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
{
.adr = 0x000030025D071101ull,
@@ -45,6 +85,33 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt712_2_single_adr[] = {
+ {
+ .adr = 0x000230025D071201ull,
+ .num_endpoints = ARRAY_SIZE(rt712_endpoints),
+ .endpoints = rt712_endpoints,
+ .name_prefix = "rt712"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = {
+ {
+ .adr = 0x000330025D171201ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt712-dmic"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
+ {
+ .adr = 0x000030025d072201ull,
+ .num_endpoints = ARRAY_SIZE(rt722_endpoints),
+ .endpoints = rt722_endpoints,
+ .name_prefix = "rt722"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt1316_2_group1_adr[] = {
{
.adr = 0x000230025D131601ull,
@@ -81,6 +148,29 @@ static const struct snd_soc_acpi_link_adr lnl_rvp[] = {
{}
};
+static const struct snd_soc_acpi_link_adr lnl_712_only[] = {
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(rt712_2_single_adr),
+ .adr_d = rt712_2_single_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt1712_3_single_adr),
+ .adr_d = rt1712_3_single_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr lnl_rt722_only[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt722_0_single_adr),
+ .adr_d = rt722_0_single_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr lnl_3_in_1_sdca[] = {
{
.mask = BIT(0),
@@ -138,6 +228,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-lnl-rt711.tplg",
},
+ {
+ .link_mask = BIT(2) | BIT(3),
+ .links = lnl_712_only,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-rt712-l2-rt1712-l3.tplg",
+ },
+ {
+ .link_mask = BIT(0),
+ .links = lnl_rt722_only,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-rt722-l0.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index feb12c6c85d1..e9a5da079089 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -62,7 +62,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
},
{
.comp_ids = &mtl_rt5682_rt5682s_hp,
- .drv_name = "mtl_rt1019_rt5682",
+ .drv_name = "mtl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &mtl_rt1019p_amp,
.sof_tplg_filename = "sof-mtl-rt1019-rt5682.tplg",
@@ -84,7 +84,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
},
{
.id = "10EC5650",
- .drv_name = "mtl_rt5650",
+ .drv_name = "mtl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &mtl_rt5650_amp,
.sof_tplg_filename = "sof-mtl-rt5650.tplg",
@@ -377,6 +377,37 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device cs35l56_2_r_adr[] = {
+ {
+ .adr = 0x00023201FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "AMP3"
+ },
+ {
+ .adr = 0x00023301FA355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_3_endpoint,
+ .name_prefix = "AMP4"
+ }
+
+};
+
+static const struct snd_soc_acpi_adr_device cs35l56_3_l_adr[] = {
+ {
+ .adr = 0x00033001fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "AMP1"
+ },
+ {
+ .adr = 0x00033101fa355601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_2_endpoint,
+ .name_prefix = "AMP2"
+ }
+};
+
static const struct snd_soc_acpi_link_adr rt5682_link2_max98373_link0[] = {
/* Expected order: jack -> amp */
{
@@ -554,6 +585,26 @@ static const struct snd_soc_acpi_link_adr mtl_cs42l43_cs35l56[] = {
{}
};
+static const struct snd_soc_acpi_link_adr cs42l43_link0_cs35l56_link2_link3[] = {
+ /* Expected order: jack -> amp */
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(cs42l43_0_adr),
+ .adr_d = cs42l43_0_adr,
+ },
+ {
+ .mask = BIT(2),
+ .num_adr = ARRAY_SIZE(cs35l56_2_r_adr),
+ .adr_d = cs35l56_2_r_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(cs35l56_3_l_adr),
+ .adr_d = cs35l56_3_l_adr,
+ },
+ {}
+};
+
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
/* mockup tests need to be first */
@@ -600,6 +651,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
.sof_tplg_filename = "sof-mtl-rt1318-l12-rt714-l0.tplg"
},
{
+ .link_mask = BIT(0) | BIT(2) | BIT(3),
+ .links = cs42l43_link0_cs35l56_link2_link3,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-cs42l43-l0-cs35l56-l23.tplg",
+ },
+ {
.link_mask = GENMASK(2, 0),
.links = mtl_cs42l43_cs35l56,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
index c0a643f4725a..00a21af210fa 100644
--- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c
@@ -395,7 +395,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
},
{
.comp_ids = &rpl_rt5682_hp,
- .drv_name = "rpl_mx98360_rt5682",
+ .drv_name = "rpl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rpl_max98360a_amp,
.sof_tplg_filename = "sof-rpl-max98360a-rt5682.tplg",
@@ -423,7 +423,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = {
},
{
.comp_ids = &rpl_rt5682_hp,
- .drv_name = "rpl_rt1019_rt5682",
+ .drv_name = "rpl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rpl_rt1019p_amp,
.sof_tplg_filename = "sof-rpl-rt1019-rt5682.tplg",
diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
index e5f721ba5ed4..0fba0a60d9c7 100644
--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c
@@ -495,21 +495,21 @@ static const struct snd_soc_acpi_codecs tgl_lt6911_hdmi = {
struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = {
{
.comp_ids = &tgl_rt5682_rt5682s_hp,
- .drv_name = "tgl_mx98357_rt5682",
+ .drv_name = "tgl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &tgl_codecs,
.sof_tplg_filename = "sof-tgl-max98357a-rt5682.tplg",
},
{
.comp_ids = &tgl_rt5682_rt5682s_hp,
- .drv_name = "tgl_mx98373_rt5682",
+ .drv_name = "tgl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &tgl_max98373_amp,
.sof_tplg_filename = "sof-tgl-max98373-rt5682.tplg",
},
{
.comp_ids = &tgl_rt5682_rt5682s_hp,
- .drv_name = "tgl_rt1011_rt5682",
+ .drv_name = "tgl_rt5682_def",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &tgl_rt1011_amp,
.sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg",