ASoC: Intel: avs: ICL-based platforms support
authorCezary Rojewski <cezary.rojewski@intel.com>
Tue, 20 Feb 2024 11:50:32 +0000 (12:50 +0100)
committerMark Brown <broonie@kernel.org>
Tue, 20 Feb 2024 13:19:58 +0000 (13:19 +0000)
Define handlers specific to cAVS 2.0 platforms, that is ICL, JSL and all
other variants based on this very version of AudioDSP architecture. Most
operations are inherited from their predecessors with the major
difference being firmware-logging functionality - IPC request as well as
debug memory windows layout have changed.

Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
Link: https://msgid.link/r/20240220115035.770402-8-cezary.rojewski@intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/avs/Makefile
sound/soc/intel/avs/avs.h
sound/soc/intel/avs/core.c
sound/soc/intel/avs/icl.c [new file with mode: 0644]
sound/soc/intel/avs/messages.c
sound/soc/intel/avs/messages.h

index a8d4b0ef2603f03275a3c3b46cb6e2f8e9fb8c57..6ababafd40bd555fdb1ae11d32075c2e994a182d 100644 (file)
@@ -3,7 +3,7 @@
 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
 snd-soc-avs-objs += cldma.o
-snd-soc-avs-objs += skl.o apl.o cnl.o
+snd-soc-avs-objs += skl.o apl.o cnl.o icl.o
 
 snd-soc-avs-objs += trace.o
 # tell define_trace.h where to find the trace header
index b53cf35fa556a5ff396e6c371d2ad860994fef2d..27b2e1b189141e1bf464bdf3dc30c0bcf83bd7e4 100644 (file)
@@ -67,6 +67,7 @@ struct avs_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;
 
 #define AVS_PLATATTR_CLDMA             BIT_ULL(0)
 #define AVS_PLATATTR_IMR               BIT_ULL(1)
@@ -269,11 +270,16 @@ 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 */
 
index 2054c2034fe2a1486709f261891e62b3c95ae8f7..17444ffca019636b27c842add6a306e76b254cc9 100644 (file)
@@ -808,6 +808,26 @@ static const struct avs_spec cnl_desc = {
        .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,
+};
+
 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) },
@@ -822,6 +842,10 @@ static const struct pci_device_id avs_ids[] = {
        { 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) },
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, avs_ids);
diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c
new file mode 100644 (file)
index 0000000..83ebee6
--- /dev/null
@@ -0,0 +1,137 @@
+// 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 "avs.h"
+#include "messages.h"
+
+#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);
+}
+
+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_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)
+};
index 06b4394cabd2042e9859f7abfcc3a7e18106344d..f874e4f0d95f454ba9e885c87777683ac4972d27 100644 (file)
@@ -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;
 
index 0f0862818f0284046a3571628ff87e790e62935d..4e609a08863c8cb9eb14e9a83af555882e82a7be 100644 (file)
@@ -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;
        };
@@ -376,6 +380,30 @@ struct avs_apl_log_state_info {
        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);
 
 struct avs_fw_version {