summary refs log tree commit diff
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorJohn Schoenick <johns@valvesoftware.com>2023-11-13 20:47:14 -0800
committerJohn Schoenick <johns@valvesoftware.com>2023-11-13 20:47:14 -0800
commitd418de2c82f22130b3411ca5334013fa9e2de31f (patch)
treef8d719d1d4724b24a4bcb0213cf92f430ae50655 /sound/soc/sof
parentb7dd868b5f57099d7f67810eb3acc58c3c108c07 (diff)
parentfd6db0236917ce0712065e82cf80d601d523abef (diff)
downloadlinux-6.1.52-valve5.tar.gz
Merge galilypad/6.1.52 into frog/6.1.52 6.1.52-valve5
Brings in galileo support
Diffstat (limited to 'sound/soc/sof')
-rw-r--r--sound/soc/sof/amd/Kconfig13
-rw-r--r--sound/soc/sof/amd/Makefile3
-rw-r--r--sound/soc/sof/amd/acp-common.c4
-rw-r--r--sound/soc/sof/amd/acp-dsp-offset.h3
-rw-r--r--sound/soc/sof/amd/acp-ipc.c49
-rw-r--r--sound/soc/sof/amd/acp-loader.c47
-rw-r--r--sound/soc/sof/amd/acp-probes.c147
-rw-r--r--sound/soc/sof/amd/acp.c194
-rw-r--r--sound/soc/sof/amd/acp.h44
-rw-r--r--sound/soc/sof/amd/pci-rmb.c2
-rw-r--r--sound/soc/sof/amd/pci-rn.c2
-rw-r--r--sound/soc/sof/amd/pci-vangogh.c16
-rw-r--r--sound/soc/sof/amd/vangogh.c19
-rw-r--r--sound/soc/sof/intel/hda-ipc.c3
-rw-r--r--sound/soc/sof/intel/hda.h2
-rw-r--r--sound/soc/sof/ipc3-pcm.c3
-rw-r--r--sound/soc/sof/ipc3-topology.c11
-rw-r--r--sound/soc/sof/ops.h4
-rw-r--r--sound/soc/sof/sof-client-probes.c1
-rw-r--r--sound/soc/sof/sof-priv.h5
-rw-r--r--sound/soc/sof/stream-ipc.c49
-rw-r--r--sound/soc/sof/topology.c3
22 files changed, 503 insertions, 121 deletions
diff --git a/sound/soc/sof/amd/Kconfig b/sound/soc/sof/amd/Kconfig
index 9b7fd8a23034..f2faa08f0c0e 100644
--- a/sound/soc/sof/amd/Kconfig
+++ b/sound/soc/sof/amd/Kconfig
@@ -2,7 +2,7 @@
 # This file is provided under a dual BSD/GPLv2 license. When using or
 # redistributing this file, you may do so under either license.
 #
-# Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved.
 
 config SND_SOC_SOF_AMD_TOPLEVEL
 	tristate "SOF support for AMD audio DSPs"
@@ -21,6 +21,7 @@ config SND_SOC_SOF_AMD_COMMON
 	select SND_SOC_SOF_PCI_DEV
 	select SND_AMD_ACP_CONFIG
 	select SND_SOC_SOF_XTENSA
+	select SND_SOC_SOF_ACP_PROBES
 	select SND_SOC_ACPI if ACPI
 	help
 	  This option is not user-selectable but automatically handled by
@@ -38,7 +39,8 @@ config SND_SOC_SOF_AMD_VANGOGH
 	depends on SND_SOC_SOF_PCI
 	select SND_SOC_SOF_AMD_COMMON
 	help
-	  Select this option for SOF support on AMD Vangogh platform
+	  Select this option for SOF support
+	  on AMD Vangogh platform.
 	  Say Y if you want to enable SOF on Vangogh.
 	  If unsure select "N".
 
@@ -51,4 +53,11 @@ config SND_SOC_SOF_AMD_REMBRANDT
 	  Say Y if you want to enable SOF on Rembrandt.
 	  If unsure select "N".
 
+config SND_SOC_SOF_ACP_PROBES
+	tristate
+	select SND_SOC_SOF_DEBUG_PROBES
+	help
+	  This option is not user-selectable but automatically handled by
+	  'select' statements at a higher level
+
 endif
diff --git a/sound/soc/sof/amd/Makefile b/sound/soc/sof/amd/Makefile
index f32106d28c45..f3b375e67a6f 100644
--- a/sound/soc/sof/amd/Makefile
+++ b/sound/soc/sof/amd/Makefile
@@ -2,9 +2,10 @@
 # This file is provided under a dual BSD/GPLv2 license. When using or
 # redistributing this file, you may do so under either license.
 #
-# Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved.
 
 snd-sof-amd-acp-objs := acp.o acp-loader.o acp-ipc.o acp-pcm.o acp-stream.o acp-trace.o acp-common.o
+snd-sof-amd-acp-$(CONFIG_SND_SOC_SOF_ACP_PROBES) = acp-probes.o
 snd-sof-amd-renoir-objs := pci-rn.o renoir.o
 snd-sof-amd-rembrandt-objs := pci-rmb.o rembrandt.o
 snd-sof-amd-vangogh-objs := pci-vangogh.o vangogh.o
diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c
index df36b411a12e..3a0c7688dcfe 100644
--- a/sound/soc/sof/amd/acp-common.c
+++ b/sound/soc/sof/amd/acp-common.c
@@ -196,6 +196,10 @@ struct snd_sof_dsp_ops sof_acp_common_ops = {
 	.dbg_dump		= amd_sof_dump,
 	.debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem,
 	.dsp_arch_ops = &sof_xtensa_arch_ops,
+
+	/* probe client device registation */
+	.register_ipc_clients = acp_probes_register,
+	.unregister_ipc_clients = acp_probes_unregister,
 };
 EXPORT_SYMBOL_NS(sof_acp_common_ops, SND_SOC_SOF_AMD_COMMON);
 
diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h
index 879e95627d35..a913f1cc4c80 100644
--- a/sound/soc/sof/amd/acp-dsp-offset.h
+++ b/sound/soc/sof/amd/acp-dsp-offset.h
@@ -3,7 +3,7 @@
  * This file is provided under a dual BSD/GPLv2 license. When using or
  * redistributing this file, you may do so under either license.
  *
- * Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved.
  *
  * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
  */
@@ -91,7 +91,6 @@
 #define ACP_SHA_PSP_ACK                         0x1C74
 
 #define ACP_SCRATCH_REG_0			0x10000
-#define ACP5X_DSP_FUSION_RUNSTALL		0x0414
 #define ACP6X_DSP_FUSION_RUNSTALL		0x0644
 
 /* Cache window registers */
diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c
index 1f614eff2a68..93dd14f06d1d 100644
--- a/sound/soc/sof/amd/acp-ipc.c
+++ b/sound/soc/sof/amd/acp-ipc.c
@@ -130,6 +130,13 @@ static void acp_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
 		memcpy(msg->reply_data, &reply, sizeof(reply));
 		ret = reply.error;
 	} else {
+		/*
+		 * To support an IPC tx_message with a
+		 * reply_size set to zero.
+		 */
+		if (!msg->reply_size)
+			goto out;
+
 		/* reply correct size ? */
 		if (reply.hdr.size != msg->reply_size &&
 		    !(reply.hdr.cmd & SOF_IPC_GLB_PROBE)) {
@@ -148,6 +155,8 @@ out:
 irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
 {
 	struct snd_sof_dev *sdev = context;
+	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
+	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
 	unsigned int dsp_msg_write = sdev->debug_box.offset +
 				     offsetof(struct scratch_ipc_conf, sof_dsp_msg_write);
 	unsigned int dsp_ack_write = sdev->debug_box.offset +
@@ -161,6 +170,8 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
 		if ((status & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
 			snd_sof_dsp_panic(sdev, sdev->dsp_box.offset + sizeof(status),
 					  true);
+			status = 0;
+			acp_mailbox_write(sdev, sdev->dsp_box.offset, &status, sizeof(status));
 			return IRQ_HANDLED;
 		}
 		snd_sof_ipc_msgs_rx(sdev);
@@ -177,22 +188,46 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
 
 	dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write);
 	if (dsp_ack) {
-		spin_lock_irq(&sdev->ipc_lock);
 		/* handle immediate reply from DSP core */
 		acp_dsp_ipc_get_reply(sdev);
 		snd_sof_ipc_reply(sdev, 0);
 		/* set the done bit */
 		acp_dsp_ipc_dsp_done(sdev);
-		spin_unlock_irq(&sdev->ipc_lock);
 		ipc_irq = true;
 	}
 
 	acp_mailbox_read(sdev, sdev->debug_box.offset, &status, sizeof(u32));
 	if ((status & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
 		snd_sof_dsp_panic(sdev, sdev->dsp_oops_offset, true);
+		status = 0;
+		acp_mailbox_write(sdev, sdev->debug_box.offset, &status, sizeof(status));
 		return IRQ_HANDLED;
 	}
 
+	if (desc->probe_reg_offset) {
+		u32 val;
+		u32 posn;
+
+		/* Probe register consists of two parts
+		 * (0-30) bit has cumulative position value
+		 * 31 bit is a synchronization flag between DSP and CPU
+		 * for the position update
+		 */
+		val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->probe_reg_offset);
+		if (val & PROBE_STATUS_BIT) {
+			posn = val & ~PROBE_STATUS_BIT;
+			if (adata->probe_stream) {
+				/* Probe related posn value is of 31 bits limited to 2GB
+				 * once wrapped DSP won't send posn interrupt.
+				 */
+				adata->probe_stream->cstream_posn = posn;
+				snd_compr_fragment_elapsed(adata->probe_stream->cstream);
+				snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->probe_reg_offset, posn);
+				ipc_irq = true;
+			}
+		}
+	}
+
 	if (!ipc_irq)
 		dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
 
@@ -209,7 +244,12 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sp
 		acp_mailbox_read(sdev, offset, p, sz);
 	} else {
 		struct snd_pcm_substream *substream = sps->substream;
-		struct acp_dsp_stream *stream = substream->runtime->private_data;
+		struct acp_dsp_stream *stream;
+
+		if (!substream || !substream->runtime)
+			return -ESTRPIPE;
+
+		stream = substream->runtime->private_data;
 
 		if (!stream)
 			return -ESTRPIPE;
@@ -222,9 +262,10 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sp
 EXPORT_SYMBOL_NS(acp_sof_ipc_msg_data, SND_SOC_SOF_AMD_COMMON);
 
 int acp_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset)
 {
+	struct snd_pcm_substream *substream = sps->substream;
 	struct acp_dsp_stream *stream = substream->runtime->private_data;
 
 	/* check for unaligned offset or overflow */
diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c
index 8c1003ca8860..a427673cfb03 100644
--- a/sound/soc/sof/amd/acp-loader.c
+++ b/sound/soc/sof/amd/acp-loader.c
@@ -3,7 +3,7 @@
 // This file is provided under a dual BSD/GPLv2 license. When using or
 // redistributing this file, you may do so under either license.
 //
-// Copyright(c) 2021 Advanced Micro Devices, Inc.
+// Copyright(c) 2021, 2023 Advanced Micro Devices, Inc.
 //
 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
 
@@ -160,7 +160,7 @@ int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
 	adata = sdev->pdata->hw_pdata;
 
 	if (adata->signed_fw_image)
-		size_fw = adata->fw_bin_size - FW_SIGNATURE;
+		size_fw = adata->fw_bin_size - ACP_FIRMWARE_SIGNATURE;
 	else
 		size_fw = adata->fw_bin_size;
 
@@ -207,6 +207,7 @@ EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, SND_SOC_SOF_AMD_COMMON);
 
 int acp_sof_dsp_run(struct snd_sof_dev *sdev)
 {
+	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
 	int val;
 
@@ -215,7 +216,7 @@ int acp_sof_dsp_run(struct snd_sof_dev *sdev)
 	dev_dbg(sdev->dev, "ACP_DSP0_RUNSTALL : 0x%0x\n", val);
 
 	/* Some platforms won't support fusion DSP,keep offset zero for no support */
-	if (desc->fusion_dsp_offset) {
+	if (desc->fusion_dsp_offset && adata->enable_fw_debug) {
 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset, ACP_DSP_RUN);
 		val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset);
 		dev_dbg(sdev->dev, "ACP_DSP0_FUSION_RUNSTALL : 0x%0x\n", val);
@@ -224,53 +225,33 @@ int acp_sof_dsp_run(struct snd_sof_dev *sdev)
 }
 EXPORT_SYMBOL_NS(acp_sof_dsp_run, SND_SOC_SOF_AMD_COMMON);
 
-int acp_sof_load_firmware(struct snd_sof_dev *sdev)
+int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
 {
 	struct snd_sof_pdata *plat_data = sdev->pdata;
 	struct acp_dev_data *adata = plat_data->hw_pdata;
-	const char *fw_filename;
-	const char *fw_datafilename;
 	int ret;
 
-	adata->signed_fw_image = true;
-	fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
-				plat_data->fw_filename_prefix,
-				"sof-vangogh-code.bin");
-
-	ret = request_firmware(&sdev->basefw.fw, fw_filename, sdev->dev);
-
+	ret = request_firmware(&sdev->basefw.fw, adata->fw_code_bin, sdev->dev);
 	if (ret < 0) {
-		dev_err(sdev->dev,
-			"error: sof firmware file is missing, you might need to\n");
-		dev_err(sdev->dev,
-			"download it from https://github.com/thesofproject/sof-bin/\n");
-
+		dev_err(sdev->dev, "sof signed firmware code bin is missing\n");
+		return ret;
 	} else {
-		dev_dbg(sdev->dev, "request_firmware %s successful\n",
-			fw_filename);
+		dev_dbg(sdev->dev, "request_firmware %s successful\n", adata->fw_code_bin);
 	}
 	ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0,
 				      (void *)sdev->basefw.fw->data, sdev->basefw.fw->size);
 
-	fw_datafilename = kasprintf(GFP_KERNEL, "%s/%s",
-				    plat_data->fw_filename_prefix,
-				    "sof-vangogh-data.bin");
-
-	ret = request_firmware(&adata->fw_dbin, fw_datafilename, sdev->dev);
-
+	ret = request_firmware(&adata->fw_dbin, adata->fw_data_bin, sdev->dev);
 	if (ret < 0) {
-		dev_err(sdev->dev,
-			"error: sof firmware file is missing, you might need to\n");
-		dev_err(sdev->dev,
-			"download it from https://github.com/thesofproject/sof-bin/\n");
+		dev_err(sdev->dev, "sof signed firmware data bin is missing\n");
+		return ret;
 
 	} else {
-		dev_dbg(sdev->dev, "request_firmware %s successful\n",
-			fw_filename);
+		dev_dbg(sdev->dev, "request_firmware %s successful\n", adata->fw_data_bin);
 	}
 
 	ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_DRAM, 0,
 				      (void *)adata->fw_dbin->data, adata->fw_dbin->size);
 	return ret;
 }
-EXPORT_SYMBOL_NS(acp_sof_load_firmware, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_load_signed_firmware, SND_SOC_SOF_AMD_COMMON);
diff --git a/sound/soc/sof/amd/acp-probes.c b/sound/soc/sof/amd/acp-probes.c
new file mode 100644
index 000000000000..778cf1a8b610
--- /dev/null
+++ b/sound/soc/sof/amd/acp-probes.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2023 Advanced Micro Devices, Inc.
+//
+// Authors: V Sujith Kumar Reddy <Vsujithkumar.Reddy@amd.com>
+
+/*
+ * Probe interface for generic AMD audio ACP DSP block
+ */
+
+#include <linux/module.h>
+#include <sound/soc.h>
+#include "../sof-priv.h"
+#include "../sof-client-probes.h"
+#include "../sof-client.h"
+#include "../ops.h"
+#include "acp.h"
+#include "acp-dsp-offset.h"
+
+static int acp_probes_compr_startup(struct sof_client_dev *cdev,
+				    struct snd_compr_stream *cstream,
+				    struct snd_soc_dai *dai, u32 *stream_id)
+{
+	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
+	struct acp_dsp_stream *stream;
+	struct acp_dev_data *adata;
+
+	adata = sdev->pdata->hw_pdata;
+	stream = acp_dsp_stream_get(sdev, 0);
+	if (!stream)
+		return -ENODEV;
+
+	stream->cstream = cstream;
+	cstream->runtime->private_data = stream;
+
+	adata->probe_stream = stream;
+	*stream_id = stream->stream_tag;
+
+	return 0;
+}
+
+static int acp_probes_compr_shutdown(struct sof_client_dev *cdev,
+				     struct snd_compr_stream *cstream,
+				     struct snd_soc_dai *dai)
+{
+	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
+	struct acp_dsp_stream *stream = cstream->runtime->private_data;
+	struct acp_dev_data *adata;
+	int ret;
+
+	ret = acp_dsp_stream_put(sdev, stream);
+	if (ret < 0) {
+		dev_err(sdev->dev, "Failed to release probe compress stream\n");
+		return ret;
+	}
+
+	adata = sdev->pdata->hw_pdata;
+	stream->cstream = NULL;
+	cstream->runtime->private_data = NULL;
+	adata->probe_stream = NULL;
+
+	return 0;
+}
+
+static int acp_probes_compr_set_params(struct sof_client_dev *cdev,
+				       struct snd_compr_stream *cstream,
+				       struct snd_compr_params *params,
+				       struct snd_soc_dai *dai)
+{
+	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
+	struct acp_dsp_stream *stream = cstream->runtime->private_data;
+	unsigned int buf_offset, index;
+	u32 size;
+	int ret;
+
+	stream->dmab = cstream->runtime->dma_buffer_p;
+	stream->num_pages = PFN_UP(cstream->runtime->dma_bytes);
+	size = cstream->runtime->buffer_size;
+
+	ret = acp_dsp_stream_config(sdev, stream);
+	if (ret < 0) {
+		acp_dsp_stream_put(sdev, stream);
+		return ret;
+	}
+
+	/* write buffer size of stream in scratch memory */
+
+	buf_offset = sdev->debug_box.offset +
+		     offsetof(struct scratch_reg_conf, buf_size);
+	index = stream->stream_tag - 1;
+	buf_offset = buf_offset + index * 4;
+
+	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + buf_offset, size);
+
+	return 0;
+}
+
+static int acp_probes_compr_trigger(struct sof_client_dev *cdev,
+				    struct snd_compr_stream *cstream,
+				    int cmd, struct snd_soc_dai *dai)
+{
+	/* Nothing to do here, as it is a mandatory callback just defined */
+	return 0;
+}
+
+static int acp_probes_compr_pointer(struct sof_client_dev *cdev,
+				    struct snd_compr_stream *cstream,
+				    struct snd_compr_tstamp *tstamp,
+				    struct snd_soc_dai *dai)
+{
+	struct acp_dsp_stream *stream = cstream->runtime->private_data;
+	struct snd_soc_pcm_stream *pstream;
+
+	pstream = &dai->driver->capture;
+	tstamp->copied_total = stream->cstream_posn;
+	tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates);
+
+	return 0;
+}
+
+/* SOF client implementation */
+static const struct sof_probes_host_ops acp_probes_ops = {
+	.startup = acp_probes_compr_startup,
+	.shutdown = acp_probes_compr_shutdown,
+	.set_params = acp_probes_compr_set_params,
+	.trigger = acp_probes_compr_trigger,
+	.pointer = acp_probes_compr_pointer,
+};
+
+int acp_probes_register(struct snd_sof_dev *sdev)
+{
+	return sof_client_dev_register(sdev, "acp-probes", 0, &acp_probes_ops,
+				       sizeof(acp_probes_ops));
+}
+EXPORT_SYMBOL_NS(acp_probes_register, SND_SOC_SOF_AMD_COMMON);
+
+void acp_probes_unregister(struct snd_sof_dev *sdev)
+{
+	sof_client_dev_unregister(sdev, "acp-probes", 0);
+}
+EXPORT_SYMBOL_NS(acp_probes_unregister, SND_SOC_SOF_AMD_COMMON);
+
+MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index 8563a60235b6..5638af72a3fe 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -3,7 +3,7 @@
 // This file is provided under a dual BSD/GPLv2 license. When using or
 // redistributing this file, you may do so under either license.
 //
-// Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+// Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved.
 //
 // Authors: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
 //	    Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
@@ -16,10 +16,35 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 
+#include <linux/fs.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/buffer_head.h>
+
 #include "../ops.h"
 #include "acp.h"
 #include "acp-dsp-offset.h"
 
+#define SECURED_FIRMWARE 1
+
+static bool enable_fw_debug;
+module_param(enable_fw_debug, bool, 0444);
+MODULE_PARM_DESC(enable_fw_debug, "Enable Firmware debug");
+
+const struct dmi_system_id acp_sof_quirk_table[] = {
+	{
+		/* Valve Jupiter device */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Valve"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"),
+			DMI_MATCH(DMI_PRODUCT_FAMILY, "Sephiroth"),
+		},
+		.driver_data = (void *)SECURED_FIRMWARE,
+	},
+	{}
+};
+EXPORT_SYMBOL_GPL(acp_sof_quirk_table);
+
 static int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
 {
 	pci_write_config_dword(dev, 0x60, smn_addr);
@@ -217,6 +242,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
 			      unsigned int image_length)
 {
 	struct snd_sof_dev *sdev = adata->dev;
+	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
 	unsigned int tx_count, fw_qualifier, val;
 	int ret;
 
@@ -238,7 +264,9 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
 		}
 	}
 
-	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_INCLUDE_HDR, ACP_SHA_HEADER);
+	if (adata->signed_fw_image)
+		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_INCLUDE_HDR, ACP_SHA_HEADER);
+
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_STRT_ADDR, start_addr);
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_DESTINATION_ADDR, dest_addr);
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_MSG_LENGTH, image_length);
@@ -252,9 +280,12 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
 		return ret;
 	}
 
-	ret = psp_send_cmd(adata, MBOX_ACP_SHA_DMA_COMMAND);
-	if (ret)
-		return ret;
+	/* psp_send_cmd only required for renoir platform (rev - 3) */
+	if (desc->rev == 3) {
+		ret = psp_send_cmd(adata, MBOX_ACP_SHA_DMA_COMMAND);
+		if (ret)
+			return ret;
+	}
 
 	ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER,
 					    fw_qualifier, fw_qualifier & DSP_FW_RUN_ENABLE,
@@ -319,15 +350,9 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
 {
 	struct snd_sof_dev *sdev = context;
 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
-	unsigned int val, count = ACP_HW_SEM_RETRY_COUNT;
-
-	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat);
-	if (val & ACP_SHA_STAT) {
-		/* Clear SHA interrupt raised by PSP */
-		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat, val);
-		return IRQ_HANDLED;
-	}
+	unsigned int count = ACP_HW_SEM_RETRY_COUNT;
 
+	spin_lock_irq(&sdev->ipc_lock);
 	while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset)) {
 		/* Wait until acquired HW Semaphore lock or timeout */
 		count--;
@@ -340,6 +365,7 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
 	sof_ops(sdev)->irq_thread(irq, sdev);
 	/* Unlock or Release HW Semaphore */
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->hw_semaphore_offset, 0x0);
+	spin_unlock_irq(&sdev->ipc_lock);
 
 	return IRQ_HANDLED;
 };
@@ -352,9 +378,9 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
 	unsigned int val;
 
 	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
-	if (val) {
-		val |= ACP_DSP_TO_HOST_IRQ;
-		snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET, val);
+	if (val & ACP_DSP_TO_HOST_IRQ) {
+		snd_sof_dsp_write(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET,
+				  ACP_DSP_TO_HOST_IRQ);
 		return IRQ_WAKE_THREAD;
 	}
 
@@ -409,6 +435,9 @@ static int acp_reset(struct snd_sof_dev *sdev)
 		dev_err(sdev->dev, "timeout in releasing reset\n");
 
 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK);
+	if (desc->ext_intr_enb)
+		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_enb, 0x01);
+
 	return ret;
 }
 
@@ -446,7 +475,6 @@ EXPORT_SYMBOL_NS(amd_sof_acp_suspend, SND_SOC_SOF_AMD_COMMON);
 
 int amd_sof_acp_resume(struct snd_sof_dev *sdev)
 {
-	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
 	int ret;
 
 	ret = acp_init(sdev);
@@ -455,51 +483,106 @@ int amd_sof_acp_resume(struct snd_sof_dev *sdev)
 		return ret;
 	}
 
-	snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK);
-
 	ret = acp_memory_init(sdev);
 
 	return ret;
 }
 EXPORT_SYMBOL_NS(amd_sof_acp_resume, SND_SOC_SOF_AMD_COMMON);
 
-static void acp_set_window_offset(struct snd_sof_dev *sdev,
-				  struct pci_dev *pci)
+static int acp_get_oem_strings(struct snd_sof_dev *sdev)
 {
-	switch (pci->revision) {
-	case 0x50:
-		sdev->dsp_box.offset = 0;
-		sdev->dsp_box.size = BOX_SIZE_1024;
-
-		sdev->host_box.offset = sdev->dsp_box.offset + sdev->dsp_box.size;
-		sdev->host_box.size = BOX_SIZE_1024;
+	const struct dmi_device *dev = NULL;
+	struct file *fp;
+	struct acp_oem_str *oem_strings;
+	int line = 0;
+	int Max_left_ch_id = 0x01000006;
+	int Max_right_ch_id = 0x02000006;
+	int Max_amb_temp_id = 0x03000008;
+	char *Max_amb_temp_val;
+	char str[5][30];
+	static unsigned int dsm_calib_data[18];
+
+	dsm_calib_data[0] = 0x03;
+	dsm_calib_data[1] = 0x044;
+	dsm_calib_data[2] = 0x464f53;	// hdr magic id
+	dsm_calib_data[3] = 0x1;	// IPC type - 0 for IPC3 and 1 for IPC4
+	dsm_calib_data[4] = 0x20;	// Size of payload
+	dsm_calib_data[5] = 0x3017000;	// ABI version
+	/* reserved[4] */
+	dsm_calib_data[6] = 0x0;
+	dsm_calib_data[7] = 0x0;
+	dsm_calib_data[8] = 0x0;
+	dsm_calib_data[9] = 0x0;
+	dsm_calib_data[10] = 0x18;		// data blob size
+	dsm_calib_data[11] = 0x18;
+
+	oem_strings = devm_kcalloc(sdev->dev, MAX_OEM_STRINGS, sizeof(oem_strings), GFP_KERNEL);
+	if (!oem_strings)
+		return -ENOMEM;
 
-		sdev->debug_box.offset = sdev->host_box.offset + sdev->host_box.size;
-		sdev->debug_box.size = BOX_SIZE_1024;
+	pr_err("DEBUG: %s ########### Trying to OEM strings \n", __func__);
+
+	while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
+		if (sscanf(dev->name, "%s", str[line]) <= 5) {
+			switch (line) {
+			case 0:
+				oem_strings[MAX_OEM_STRINGS - line].name = str[line];
+				break;
+			case 1:
+				oem_strings[MAX_OEM_STRINGS - line].name = str[line];
+				break;
+			case 2:
+				oem_strings[MAX_OEM_STRINGS - line].name = str[line];
+				break;
+			case 3:
+				oem_strings[MAX_OEM_STRINGS - line].name = str[line];
+				break;
+			case 4:
+				oem_strings[MAX_OEM_STRINGS - line].name = str[line];
+				break;
+			default:
+				break;
+			}
+			++line;
+		}
+	}
+	for (int i=1; i<=MAX_OEM_STRINGS; i++)
+		pr_err("DEBUG: oem_str[%d][%s] \n", i, oem_strings[i]);
 
-		sdev->dsp_oops_offset = sdev->debug_box.offset + sdev->debug_box.size;
+	dsm_calib_data[12] = Max_left_ch_id;
+	dsm_calib_data[14] = Max_right_ch_id;
+	dsm_calib_data[16] = Max_amb_temp_id;
 
-		sdev->stream_box.offset = sdev->dsp_oops_offset + BOX_SIZE_1024;
-		sdev->stream_box.size = BOX_SIZE_1024;
-		break;
-	default:
-		sdev->dsp_box.offset = 0;
-		sdev->dsp_box.size = BOX_SIZE_512;
+	sscanf(&oem_strings[1].name[13], "%x", &dsm_calib_data[13]);
+	// dsm_calib_data[13] = CHANGE_ENDIANNESS(dsm_calib_data[13]);
 
-		sdev->host_box.offset = sdev->dsp_box.offset + sdev->dsp_box.size;
-		sdev->host_box.size = BOX_SIZE_512;
+	Max_amb_temp_val = devm_kasprintf(sdev->dev, GFP_KERNEL,"%0.8s", &oem_strings[3].name[2]);
+	sscanf(Max_amb_temp_val, "%x", &dsm_calib_data[17]);
+	// dsm_calib_data[17] = CHANGE_ENDIANNESS(dsm_calib_data[17]);
 
-		sdev->debug_box.offset = sdev->host_box.offset + sdev->host_box.size;
-		sdev->debug_box.size = BOX_SIZE_1024;
+	sscanf(&oem_strings[3].name[13], "%x", &dsm_calib_data[15]);
+	// dsm_calib_data[15] = CHANGE_ENDIANNESS(dsm_calib_data[15]);
 
-		break;
+	fp = filp_open("/lib/firmware/amd/sof/dsmcalib.bin", O_RDWR | O_CREAT, 0666);
+	if (IS_ERR(fp)) {
+			pr_err("DEBUG: failed to create file \n");
+			return -1;
 	}
+	dev_err(sdev->dev,"DEBUG: /lib/firmware/amd/sof/dsmcalib.bin created \n");
+
+	kernel_write(fp, &dsm_calib_data, 19 * sizeof(int), 0);
+	filp_close(fp, NULL);
+
+	return 0;
 }
+
 int amd_sof_acp_probe(struct snd_sof_dev *sdev)
 {
 	struct pci_dev *pci = to_pci_dev(sdev->dev);
+	struct snd_sof_pdata *plat_data = sdev->pdata;
 	struct acp_dev_data *adata;
 	const struct sof_amd_acp_desc *chip;
+	const struct dmi_system_id *dmi_id;
 	unsigned int addr;
 	int ret;
 
@@ -551,7 +634,32 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
 	if (ret < 0)
 		goto free_ipc_irq;
 
-	acp_set_window_offset(sdev, pci);
+	sdev->dsp_box.offset = 0;
+	sdev->dsp_box.size = BOX_SIZE_512;
+
+	sdev->host_box.offset = sdev->dsp_box.offset + sdev->dsp_box.size;
+	sdev->host_box.size = BOX_SIZE_512;
+
+	sdev->debug_box.offset = sdev->host_box.offset + sdev->host_box.size;
+	sdev->debug_box.size = BOX_SIZE_1024;
+
+	adata->signed_fw_image = false;
+	dmi_id = dmi_first_match(acp_sof_quirk_table);
+	if (dmi_id && dmi_id->driver_data) {
+		adata->fw_code_bin = kasprintf(GFP_KERNEL, "%s/sof-%s-code.bin",
+					       plat_data->fw_filename_prefix,
+					       chip->name);
+		adata->fw_data_bin = kasprintf(GFP_KERNEL, "%s/sof-%s-data.bin",
+					       plat_data->fw_filename_prefix,
+					       chip->name);
+		adata->signed_fw_image = dmi_id->driver_data;
+
+		dev_dbg(sdev->dev, "fw_code_bin:%s, fw_data_bin:%s\n", adata->fw_code_bin,
+			adata->fw_data_bin);
+
+		acp_get_oem_strings(sdev);
+	}
+	adata->enable_fw_debug = enable_fw_debug;
 	acp_memory_init(sdev);
 
 	acp_dsp_stream_init(sdev);
diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h
index 20d8d576a81b..8abf64017c7f 100644
--- a/sound/soc/sof/amd/acp.h
+++ b/sound/soc/sof/amd/acp.h
@@ -3,7 +3,7 @@
  * This file is provided under a dual BSD/GPLv2 license. When using or
  * redistributing this file, you may do so under either license.
  *
- * Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved.
  *
  * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
  */
@@ -11,9 +11,15 @@
 #ifndef __SOF_AMD_ACP_H
 #define __SOF_AMD_ACP_H
 
+#include <linux/dmi.h>
+
 #include "../sof-priv.h"
 #include "../sof-audio.h"
 
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+
 #define ACP_MAX_STREAM	8
 
 #define ACP_DSP_BAR	0
@@ -58,6 +64,7 @@
 #define ACP_DSP_TO_HOST_IRQ			0x04
 
 #define ACP_RN_PCI_ID				0x01
+#define ACP_VANGOGH_PCI_ID			0x50
 #define ACP_RMB_PCI_ID				0x6F
 
 #define HOST_BRIDGE_CZN				0x1630
@@ -80,8 +87,16 @@
 #define AMD_STACK_DUMP_SIZE			32
 
 #define SRAM1_SIZE				0x13A000
+#define PROBE_STATUS_BIT			BIT(31)
+
+#define ACP_FIRMWARE_SIGNATURE			0x100
+
+#define MAX_OEM_STRINGS			0x05
+#define CHANGE_ENDIANNESS(val)   ((((uint32_t)(val) & 0xff000000) >> 24) \
+                               | (((uint32_t)(val) & 0x00ff0000) >> 8) \
+                               | (((uint32_t)(val) & 0x0000ff00) << 8)  \
+                               | (((uint32_t)(val) & 0x000000ff) << 24))
 
-#define FW_SIGNATURE				0x100
 
 enum clock_source {
 	ACP_CLOCK_96M = 0,
@@ -161,18 +176,23 @@ struct acp_dsp_stream {
 	int active;
 	unsigned int reg_offset;
 	size_t posn_offset;
+	struct snd_compr_stream *cstream;
+	u64 cstream_posn;
 };
 
 struct sof_amd_acp_desc {
 	unsigned int rev;
+	const char *name;
 	unsigned int host_bridge_id;
 	u32 pgfsm_base;
+	u32 ext_intr_enb;
 	u32 ext_intr_stat;
 	u32 dsp_intr_base;
 	u32 sram_pte_offset;
 	u32 hw_semaphore_offset;
 	u32 acp_clkmux_sel;
 	u32 fusion_dsp_offset;
+	u32 probe_reg_offset;
 };
 
 /* Common device data struct for ACP devices */
@@ -183,16 +203,24 @@ struct acp_dev_data {
 	struct platform_device *dmic_dev;
 	unsigned int fw_bin_size;
 	unsigned int fw_data_bin_size;
+	const char *fw_code_bin;
+	const char *fw_data_bin;
 	u32 fw_bin_page_count;
 	dma_addr_t sha_dma_addr;
 	u8 *bin_buf;
 	dma_addr_t dma_addr;
 	u8 *data_buf;
+	bool signed_fw_image;
 	struct dma_descriptor dscr_info[ACP_MAX_DESC];
 	struct acp_dsp_stream stream_buf[ACP_MAX_STREAM];
 	struct acp_dsp_stream *dtrace_stream;
 	struct pci_dev *smn_dev;
-	bool signed_fw_image;
+	struct acp_dsp_stream *probe_stream;
+	bool enable_fw_debug;
+};
+
+struct acp_oem_str {
+	const char *name;
 };
 
 void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes);
@@ -212,7 +240,7 @@ int amd_sof_acp_remove(struct snd_sof_dev *sdev);
 /* DSP Loader callbacks */
 int acp_sof_dsp_run(struct snd_sof_dev *sdev);
 int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev);
-int acp_sof_load_firmware(struct snd_sof_dev *sdev);
+int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev);
 int acp_get_bar_index(struct snd_sof_dev *sdev, u32 type);
 
 /* Block IO callbacks */
@@ -226,7 +254,7 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context);
 int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps,
 			 void *p, size_t sz);
 int acp_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset);
 int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev,
 			 struct snd_sof_ipc_msg *msg);
@@ -283,4 +311,10 @@ static inline const struct sof_amd_acp_desc *get_chip_info(struct snd_sof_pdata
 
 	return desc->chip_info;
 }
+
+int acp_probes_register(struct snd_sof_dev *sdev);
+void acp_probes_unregister(struct snd_sof_dev *sdev);
+
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[];
+extern const struct dmi_system_id acp_sof_quirk_table[];
 #endif
diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c
index 58b3092425f1..9935e457b467 100644
--- a/sound/soc/sof/amd/pci-rmb.c
+++ b/sound/soc/sof/amd/pci-rmb.c
@@ -25,6 +25,7 @@
 
 #define ACP6x_REG_START		0x1240000
 #define ACP6x_REG_END		0x125C000
+#define ACP6X_FUTURE_REG_ACLK_0	0x1854
 
 static const struct sof_amd_acp_desc rembrandt_chip_info = {
 	.rev		= 6,
@@ -36,6 +37,7 @@ static const struct sof_amd_acp_desc rembrandt_chip_info = {
 	.hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0,
 	.acp_clkmux_sel = ACP6X_CLKMUX_SEL,
 	.fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL,
+	.probe_reg_offset = ACP6X_FUTURE_REG_ACLK_0,
 };
 
 static const struct sof_dev_desc rembrandt_desc = {
diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c
index 7409e21ce5aa..c72d5d8aff8e 100644
--- a/sound/soc/sof/amd/pci-rn.c
+++ b/sound/soc/sof/amd/pci-rn.c
@@ -25,6 +25,7 @@
 
 #define ACP3x_REG_START		0x1240000
 #define ACP3x_REG_END		0x125C000
+#define ACP3X_FUTURE_REG_ACLK_0	0x1860
 
 static const struct sof_amd_acp_desc renoir_chip_info = {
 	.rev		= 3,
@@ -35,6 +36,7 @@ static const struct sof_amd_acp_desc renoir_chip_info = {
 	.sram_pte_offset = ACP3X_SRAM_PTE_OFFSET,
 	.hw_semaphore_offset = ACP3X_AXI2DAGB_SEM_0,
 	.acp_clkmux_sel	= ACP3X_CLKMUX_SEL,
+	.probe_reg_offset = ACP3X_FUTURE_REG_ACLK_0,
 };
 
 static const struct sof_dev_desc renoir_desc = {
diff --git a/sound/soc/sof/amd/pci-vangogh.c b/sound/soc/sof/amd/pci-vangogh.c
index b6fd8c535cf3..d8be42fbcb6d 100644
--- a/sound/soc/sof/amd/pci-vangogh.c
+++ b/sound/soc/sof/amd/pci-vangogh.c
@@ -3,7 +3,7 @@
 // This file is provided under a dual BSD/GPLv2 license. When using or
 // redistributing this file, you may do so under either license.
 //
-// Copyright(c) 2022 Advanced Micro Devices, Inc. All rights reserved.
+// Copyright(c) 2023 Advanced Micro Devices, Inc. All rights reserved.
 //
 // Authors: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
 
@@ -23,11 +23,11 @@
 #include "acp.h"
 #include "acp-dsp-offset.h"
 
-#define ACP5x_REG_START		0x1240000
-#define ACP5x_REG_END		0x125C000
+#define ACP5X_FUTURE_REG_ACLK_0 0x1864
 
 static const struct sof_amd_acp_desc vangogh_chip_info = {
 	.rev		= 5,
+	.name		= "vangogh",
 	.host_bridge_id = HOST_BRIDGE_VGH,
 	.pgfsm_base	= ACP5X_PGFSM_BASE,
 	.ext_intr_stat	= ACP5X_EXT_INTR_STAT,
@@ -35,11 +35,11 @@ static const struct sof_amd_acp_desc vangogh_chip_info = {
 	.sram_pte_offset = ACP5X_SRAM_PTE_OFFSET,
 	.hw_semaphore_offset = ACP5X_AXI2DAGB_SEM_0,
 	.acp_clkmux_sel = ACP5X_CLKMUX_SEL,
-	.fusion_dsp_offset = ACP5X_DSP_FUSION_RUNSTALL,
+	.probe_reg_offset = ACP5X_FUTURE_REG_ACLK_0,
 };
 
 static const struct sof_dev_desc vangogh_desc = {
-	.machines		= snd_soc_acpi_amd_vgh_sof_machines,
+	.machines		= snd_soc_acpi_amd_vangogh_sof_machines,
 	.resindex_lpe_base	= 0,
 	.resindex_pcicfg_base	= -1,
 	.resindex_imr_base	= -1,
@@ -65,6 +65,9 @@ static int acp_pci_vgh_probe(struct pci_dev *pci, const struct pci_device_id *pc
 {
 	unsigned int flag;
 
+	if (pci->revision != ACP_VANGOGH_PCI_ID)
+		return -ENODEV;
+
 	flag = snd_amd_acp_find_config(pci);
 	if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC)
 		return -ENODEV;
@@ -91,6 +94,9 @@ static struct pci_driver snd_sof_pci_amd_vgh_driver = {
 	.id_table = vgh_pci_ids,
 	.probe = acp_pci_vgh_probe,
 	.remove = acp_pci_vgh_remove,
+	.driver = {
+		.pm = &sof_pci_pm,
+	},
 };
 module_pci_driver(snd_sof_pci_amd_vgh_driver);
 
diff --git a/sound/soc/sof/amd/vangogh.c b/sound/soc/sof/amd/vangogh.c
index 8c5dd990df6c..de15d21aa6d9 100644
--- a/sound/soc/sof/amd/vangogh.c
+++ b/sound/soc/sof/amd/vangogh.c
@@ -3,7 +3,7 @@
 // This file is provided under a dual BSD/GPLv2 license. When using or
 // redistributing this file, you may do so under either license.
 //
-// Copyright(c) 2022 Advanced Micro Devices, Inc.
+// Copyright(c) 2023 Advanced Micro Devices, Inc.
 //
 // Authors: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
 
@@ -123,6 +123,16 @@ static struct snd_soc_dai_driver vangogh_sof_dai[] = {
 			.rate_min = 8000,
 			.rate_max = 96000,
 		},
+		.capture = {
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+				   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+			/* Supporting only stereo for I2S HS-Virtual controller capture */
+			.channels_min = 2,
+			.channels_max = 2,
+			.rate_min = 8000,
+			.rate_max = 48000,
+		},
 	},
 };
 
@@ -132,12 +142,17 @@ EXPORT_SYMBOL_NS(sof_vangogh_ops, SND_SOC_SOF_AMD_COMMON);
 
 int sof_vangogh_ops_init(struct snd_sof_dev *sdev)
 {
+	const struct dmi_system_id *dmi_id;
+
 	/* common defaults */
 	memcpy(&sof_vangogh_ops, &sof_acp_common_ops, sizeof(struct snd_sof_dsp_ops));
 
 	sof_vangogh_ops.drv = vangogh_sof_dai;
 	sof_vangogh_ops.num_drv = ARRAY_SIZE(vangogh_sof_dai);
-	sof_vangogh_ops.load_firmware = acp_sof_load_firmware;
+
+	dmi_id = dmi_first_match(acp_sof_quirk_table);
+	if (dmi_id && dmi_id->driver_data)
+		sof_vangogh_ops.load_firmware = acp_sof_load_signed_firmware;
 
 	return 0;
 }
diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c
index 96f909441b44..ed87c00f345c 100644
--- a/sound/soc/sof/intel/hda-ipc.c
+++ b/sound/soc/sof/intel/hda-ipc.c
@@ -367,9 +367,10 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev,
 }
 
 int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset)
 {
+	struct snd_pcm_substream *substream = sps->substream;
 	struct hdac_stream *hstream = substream->runtime->private_data;
 	struct sof_intel_hda_stream *hda_stream;
 
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 2cb7c8f96365..3f88f2afd895 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -649,7 +649,7 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev,
 		     struct snd_sof_pcm_stream *sps,
 		     void *p, size_t sz);
 int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset);
 
 /*
diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c
index f10bfc9bd5cb..b29d93e0d216 100644
--- a/sound/soc/sof/ipc3-pcm.c
+++ b/sound/soc/sof/ipc3-pcm.c
@@ -129,7 +129,8 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component,
 		return ret;
 	}
 
-	ret = snd_sof_set_stream_data_offset(sdev, substream, ipc_params_reply.posn_offset);
+	ret = snd_sof_set_stream_data_offset(sdev, &spcm->stream[substream->stream],
+					     ipc_params_reply.posn_offset);
 	if (ret < 0) {
 		dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n",
 			__func__, spcm->pcm.pcm_id);
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index b94cc40485ed..e5854adde4e1 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -1174,6 +1174,7 @@ static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_
 	struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs;
 	struct sof_dai_private_data *private = dai->private;
 	u32 size = sizeof(*config);
+	int ret;
 
 	/* handle master/slave and inverted clocks */
 	sof_dai_set_format(hw_config, config);
@@ -1182,12 +1183,14 @@ static int sof_link_acp_bt_load(struct snd_soc_component *scomp, struct snd_sof_
 	memset(&config->acpbt, 0, sizeof(config->acpbt));
 	config->hdr.size = size;
 
-	config->acpbt.fsync_rate = le32_to_cpu(hw_config->fsync_rate);
-	config->acpbt.tdm_slots = le32_to_cpu(hw_config->tdm_slots);
+	ret = sof_update_ipc_object(scomp, &config->acpbt, SOF_ACPI2S_TOKENS, slink->tuples,
+				    slink->num_tuples, size, slink->num_hw_configs);
+	if (ret < 0)
+		return ret;
 
-	dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d\n",
+	dev_info(scomp->dev, "ACP_BT config ACP%d channel %d rate %d tdm_mode %d\n",
 		 config->dai_index, config->acpbt.tdm_slots,
-		 config->acpbt.fsync_rate);
+		 config->acpbt.fsync_rate, config->acpbt.tdm_mode);
 
 	dai->number_configs = 1;
 	dai->current_config = 0;
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index db92cd338467..febe318b9427 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -480,11 +480,11 @@ static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
 /* host side configuration of the stream's data offset in stream mailbox area */
 static inline int
 snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset)
 {
 	if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_offset)
-		return sof_ops(sdev)->set_stream_data_offset(sdev, substream,
+		return sof_ops(sdev)->set_stream_data_offset(sdev, sps,
 							     posn_offset);
 
 	return 0;
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c
index bfb4f3a41206..38376a16f6da 100644
--- a/sound/soc/sof/sof-client-probes.c
+++ b/sound/soc/sof/sof-client-probes.c
@@ -520,6 +520,7 @@ static void sof_probes_client_remove(struct auxiliary_device *auxdev)
 
 static const struct auxiliary_device_id sof_probes_client_id_table[] = {
 	{ .name = "snd_sof.hda-probes", },
+	{ .name = "snd_sof.acp-probes", },
 	{},
 };
 MODULE_DEVICE_TABLE(auxiliary, sof_probes_client_id_table);
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index cf1546137d29..082b86662630 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -112,6 +112,7 @@ struct sof_compr_stream {
 	u32 sampling_rate;
 	u16 channels;
 	u16 sample_container_bytes;
+	size_t posn_offset;
 };
 
 struct snd_sof_dev;
@@ -251,7 +252,7 @@ struct snd_sof_dsp_ops {
 
 	/* host side configuration of the stream's data offset in stream mailbox area */
 	int (*set_stream_data_offset)(struct snd_sof_dev *sdev,
-				      struct snd_pcm_substream *substream,
+				      struct snd_sof_pcm_stream *sps,
 				      size_t posn_offset); /* optional */
 
 	/* pre/post firmware run */
@@ -761,7 +762,7 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev,
 		     struct snd_sof_pcm_stream *sps,
 		     void *p, size_t sz);
 int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset);
 
 int sof_stream_pcm_open(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sof/stream-ipc.c b/sound/soc/sof/stream-ipc.c
index 13e44501d442..216b454f6b94 100644
--- a/sound/soc/sof/stream-ipc.c
+++ b/sound/soc/sof/stream-ipc.c
@@ -33,14 +33,27 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev,
 	if (!sps || !sdev->stream_box.size) {
 		snd_sof_dsp_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
 	} else {
-		struct snd_pcm_substream *substream = sps->substream;
-		struct sof_stream *stream = substream->runtime->private_data;
+		size_t posn_offset;
 
-		/* The stream might already be closed */
-		if (!stream)
-			return -ESTRPIPE;
+		if (sps->substream) {
+			struct sof_stream *stream = sps->substream->runtime->private_data;
 
-		snd_sof_dsp_mailbox_read(sdev, stream->posn_offset, p, sz);
+			/* The stream might already be closed */
+			if (!stream)
+				return -ESTRPIPE;
+
+			posn_offset = stream->posn_offset;
+		} else {
+
+			struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
+
+			if (!sstream)
+				return -ESTRPIPE;
+
+			posn_offset = sstream->posn_offset;
+		}
+
+		snd_sof_dsp_mailbox_read(sdev, posn_offset, p, sz);
 	}
 
 	return 0;
@@ -48,20 +61,32 @@ int sof_ipc_msg_data(struct snd_sof_dev *sdev,
 EXPORT_SYMBOL(sof_ipc_msg_data);
 
 int sof_set_stream_data_offset(struct snd_sof_dev *sdev,
-			       struct snd_pcm_substream *substream,
+			       struct snd_sof_pcm_stream *sps,
 			       size_t posn_offset)
 {
-	struct sof_stream *stream = substream->runtime->private_data;
-
 	/* check if offset is overflow or it is not aligned */
 	if (posn_offset > sdev->stream_box.size ||
 	    posn_offset % sizeof(struct sof_ipc_stream_posn) != 0)
 		return -EINVAL;
 
-	stream->posn_offset = sdev->stream_box.offset + posn_offset;
+	posn_offset += sdev->stream_box.offset;
+
+	if (sps->substream) {
+		struct sof_stream *stream = sps->substream->runtime->private_data;
+
+		stream->posn_offset = posn_offset;
+		dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
+			sps->substream->stream, posn_offset);
+	} else if (sps->cstream) {
+		struct sof_compr_stream *sstream = sps->cstream->runtime->private_data;
 
-	dev_dbg(sdev->dev, "pcm: stream dir %d, posn mailbox offset is %zu",
-		substream->stream, stream->posn_offset);
+		sstream->posn_offset = posn_offset;
+		dev_dbg(sdev->dev, "compr: stream dir %d, posn mailbox offset is %zu",
+			sps->cstream->direction, posn_offset);
+	} else {
+		dev_err(sdev->dev, "No stream opened");
+		return -EINVAL;
+	}
 
 	return 0;
 }
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 5303a11d738e..79ee8ce5c5b6 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -284,7 +284,7 @@ static const struct sof_dai_types sof_dais[] = {
 	{"ALH", SOF_DAI_INTEL_ALH},
 	{"SAI", SOF_DAI_IMX_SAI},
 	{"ESAI", SOF_DAI_IMX_ESAI},
-	{"ACP", SOF_DAI_AMD_BT},
+	{"ACPBT", SOF_DAI_AMD_BT},
 	{"ACPSP", SOF_DAI_AMD_SP},
 	{"ACPDMIC", SOF_DAI_AMD_DMIC},
 	{"ACPHS", SOF_DAI_AMD_HS},
@@ -1902,6 +1902,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_
 		token_id = SOF_ACPDMIC_TOKENS;
 		num_tuples += token_list[SOF_ACPDMIC_TOKENS].count;
 		break;
+	case SOF_DAI_AMD_BT:
 	case SOF_DAI_AMD_SP:
 	case SOF_DAI_AMD_HS:
 	case SOF_DAI_AMD_SP_VIRTUAL: