@@ -4,7 +4,7 @@ snd-soc-avs-y := dsp.o ipc.o messages.o utils.o core.o loader.o \
topology.o path.o pcm.o board_selection.o control.o \
sysfs.o
snd-soc-avs-y += cldma.o
-snd-soc-avs-y += skl.o apl.o cnl.o icl.o tgl.o mtl.o
+snd-soc-avs-y += skl.o apl.o cnl.o icl.o tgl.o mtl.o lnl.o
snd-soc-avs-y += trace.o
# tell define_trace.h where to find the trace header
@@ -70,6 +70,7 @@ 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;
extern const struct avs_dsp_ops avs_mtl_dsp_ops;
+extern const struct avs_dsp_ops avs_lnl_dsp_ops;
#define AVS_PLATATTR_CLDMA BIT_ULL(0)
#define AVS_PLATATTR_IMR BIT_ULL(1)
@@ -815,6 +815,18 @@ static const struct avs_hipc_spec mtl_hipc_spec = {
.sts_offset = MTL_REG_HfFLGP(0, 0),
};
+static const struct avs_hipc_spec lnl_hipc_spec = {
+ .req_offset = MTL_REG_HfIPCxIDR,
+ .req_ext_offset = MTL_REG_HfIPCxIDD,
+ .req_busy_mask = MTL_HfIPCxIDR_BUSY,
+ .ack_offset = MTL_REG_HfIPCxIDA,
+ .ack_done_mask = MTL_HfIPCxIDA_DONE,
+ .rsp_offset = MTL_REG_HfIPCxTDR,
+ .rsp_busy_mask = MTL_HfIPCxTDR_BUSY,
+ .ctl_offset = MTL_REG_HfIPCxCTL,
+ .sts_offset = LNL_REG_HfDFR(0),
+};
+
static const struct avs_spec skl_desc = {
.name = "skl",
.min_fw_version = { 9, 21, 0, 4732 },
@@ -892,6 +904,16 @@ static const struct avs_spec mtl_desc = {
.hipc = &mtl_hipc_spec,
};
+static const struct avs_spec lnl_desc = {
+ .name = "lnl",
+ .min_fw_version = { 0 },
+ .dsp_ops = &avs_lnl_dsp_ops,
+ .core_init_mask = 1,
+ .attributes = AVS_PLATATTR_IMR | AVS_PLATATTR_ACE | AVS_PLATATTR_ALTHDA,
+ .sram = &mtl_sram_spec,
+ .hipc = &lnl_hipc_spec,
+};
+
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) },
@@ -929,6 +951,7 @@ static const struct pci_device_id avs_ids[] = {
{ PCI_DEVICE_DATA(INTEL, HDA_RPL_PX, &adl_desc) },
{ PCI_DEVICE_DATA(INTEL, HDA_MTL, &mtl_desc) },
{ PCI_DEVICE_DATA(INTEL, HDA_ARL_S, &mtl_desc) },
+ { PCI_DEVICE_DATA(INTEL, HDA_LNL_P, &lnl_desc) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, avs_ids);
@@ -961,3 +984,4 @@ MODULE_FIRMWARE("intel/ehl/dsp_basefw.bin");
MODULE_FIRMWARE("intel/adl/dsp_basefw.bin");
MODULE_FIRMWARE("intel/adl_n/dsp_basefw.bin");
MODULE_FIRMWARE("intel/mtl/dsp_basefw.bin");
+MODULE_FIRMWARE("intel/lnl/dsp_basefw.bin");
new file mode 100644
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright(c) 2021-2025 Intel Corporation
+ *
+ * Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+ * Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+ */
+
+#include <sound/hdaudio_ext.h>
+#include "avs.h"
+#include "registers.h"
+
+static int avs_lnl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall)
+{
+ struct hdac_bus *bus = &adev->base.core;
+ struct hdac_ext_link *hlink;
+ int ret;
+
+ ret = avs_mtl_core_stall(adev, core_mask, stall);
+
+ /* On unstall, route interrupts from the links to the DSP firmware. */
+ if (!ret && !stall)
+ list_for_each_entry(hlink, &bus->hlink_list, list)
+ snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_OFLEN,
+ AZX_ML_LCTL_OFLEN);
+ return ret;
+}
+
+const struct avs_dsp_ops avs_lnl_dsp_ops = {
+ .power = avs_mtl_core_power,
+ .reset = avs_mtl_core_reset,
+ .stall = avs_lnl_core_stall,
+ .dsp_interrupt = avs_mtl_dsp_interrupt,
+ .int_control = avs_mtl_interrupt_control,
+ .load_basefw = avs_hda_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)
+};
@@ -86,6 +86,7 @@
#define MTL_HfFLV_BASE 0x162000
#define MTL_REG_HfFLGP(x, y) (MTL_HfFLV_BASE + 0x1200 + (x) * 0x20 + (y) * 0x08)
+#define LNL_REG_HfDFR(x) (0x160200 + (x) * 0x8)
#define MTL_DWICTL_BASE 0x1800
#define MTL_DWICTL_REG_INTENL (MTL_DWICTL_BASE + 0x0)