summaryrefslogtreecommitdiff
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2021-06-25 14:08:03 +0100
committerMark Brown <broonie@kernel.org>2021-06-25 14:08:03 +0100
commit192664528154a84fab4e6d820f9cb2e2e0835544 (patch)
tree4fd7c74097fc474150317fb04245460f0992af17 /sound/soc/sof
parentc073a58a7ec59145f8a0b87403d559645bfd9edb (diff)
parent6a7f5bd6185e1c86256d5e52c3bb7a4d390d6e19 (diff)
Merge remote-tracking branch 'asoc/for-5.14' into asoc-next
Diffstat (limited to 'sound/soc/sof')
-rw-r--r--sound/soc/sof/compress.c2
-rw-r--r--sound/soc/sof/compress.h2
-rw-r--r--sound/soc/sof/imx/imx8.c1
-rw-r--r--sound/soc/sof/intel/Makefile5
-rw-r--r--sound/soc/sof/intel/atom.c463
-rw-r--r--sound/soc/sof/intel/atom.h74
-rw-r--r--sound/soc/sof/intel/byt.c768
-rw-r--r--sound/soc/sof/intel/hda-loader.c5
-rw-r--r--sound/soc/sof/intel/hda.c27
-rw-r--r--sound/soc/sof/intel/pci-tgl.c2
-rw-r--r--sound/soc/sof/intel/pci-tng.c171
-rw-r--r--sound/soc/sof/loader.c2
-rw-r--r--sound/soc/sof/ops.h10
-rw-r--r--sound/soc/sof/sof-acpi-dev.c5
-rw-r--r--sound/soc/sof/sof-of-dev.c5
-rw-r--r--sound/soc/sof/sof-pci-dev.c7
-rw-r--r--sound/soc/sof/topology.c17
17 files changed, 818 insertions, 748 deletions
diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c
index 2d4969c705a4..57d5bf0a171e 100644
--- a/sound/soc/sof/compress.c
+++ b/sound/soc/sof/compress.c
@@ -13,7 +13,7 @@
#include "ops.h"
#include "probe.h"
-struct snd_compress_ops sof_probe_compressed_ops = {
+const struct snd_compress_ops sof_probe_compressed_ops = {
.copy = sof_probe_compr_copy,
};
EXPORT_SYMBOL(sof_probe_compressed_ops);
diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h
index ca8790bd4b13..4448c799e14b 100644
--- a/sound/soc/sof/compress.h
+++ b/sound/soc/sof/compress.h
@@ -13,7 +13,7 @@
#include <sound/compress_driver.h>
-extern struct snd_compress_ops sof_probe_compressed_ops;
+extern const struct snd_compress_ops sof_probe_compressed_ops;
int sof_probe_compr_open(struct snd_compr_stream *cstream,
struct snd_soc_dai *dai);
diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c
index 4e7dccadd7d0..12fedf0984bd 100644
--- a/sound/soc/sof/imx/imx8.c
+++ b/sound/soc/sof/imx/imx8.c
@@ -315,6 +315,7 @@ static int imx8_probe(struct snd_sof_dev *sdev)
}
ret = of_address_to_resource(res_node, 0, &res);
+ of_node_put(res_node);
if (ret) {
dev_err(&pdev->dev, "failed to get reserved region address\n");
goto exit_pdev_unregister;
diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile
index f3d6f7070fb3..feae487f0227 100644
--- a/sound/soc/sof/intel/Makefile
+++ b/sound/soc/sof/intel/Makefile
@@ -13,7 +13,10 @@ snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-compress.o
snd-sof-intel-hda-objs := hda-codec.o
-obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-acpi-intel-byt.o
+snd-sof-intel-atom-objs := atom.o
+
+obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o
+obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o
obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-acpi-intel-bdw.o
obj-$(CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC) += snd-sof-intel-ipc.o
obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o
diff --git a/sound/soc/sof/intel/atom.c b/sound/soc/sof/intel/atom.c
new file mode 100644
index 000000000000..d8804efede5e
--- /dev/null
+++ b/sound/soc/sof/intel/atom.c
@@ -0,0 +1,463 @@
+// 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) 2018-2021 Intel Corporation. All rights reserved.
+//
+// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+//
+
+/*
+ * Hardware interface for audio DSP on Atom devices
+ */
+
+#include <linux/module.h>
+#include <sound/sof.h>
+#include <sound/sof/xtensa.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-acpi-intel-match.h>
+#include <sound/intel-dsp-config.h>
+#include "../ops.h"
+#include "shim.h"
+#include "atom.h"
+#include "../sof-acpi-dev.h"
+#include "../sof-audio.h"
+#include "../../intel/common/soc-intel-quirks.h"
+
+static void atom_host_done(struct snd_sof_dev *sdev);
+static void atom_dsp_done(struct snd_sof_dev *sdev);
+static void atom_get_reply(struct snd_sof_dev *sdev);
+
+/*
+ * Debug
+ */
+
+static void atom_get_registers(struct snd_sof_dev *sdev,
+ struct sof_ipc_dsp_oops_xtensa *xoops,
+ struct sof_ipc_panic_info *panic_info,
+ u32 *stack, size_t stack_words)
+{
+ u32 offset = sdev->dsp_oops_offset;
+
+ /* first read regsisters */
+ sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
+
+ /* note: variable AR register array is not read */
+
+ /* then get panic info */
+ if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+ dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+ xoops->arch_hdr.totalsize);
+ return;
+ }
+ offset += xoops->arch_hdr.totalsize;
+ sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
+
+ /* then get the stack */
+ offset += sizeof(*panic_info);
+ sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
+}
+
+void atom_dump(struct snd_sof_dev *sdev, u32 flags)
+{
+ struct sof_ipc_dsp_oops_xtensa xoops;
+ struct sof_ipc_panic_info panic_info;
+ u32 stack[STACK_DUMP_SIZE];
+ u64 status, panic, imrd, imrx;
+
+ /* now try generic SOF status messages */
+ status = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCD);
+ panic = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCX);
+ atom_get_registers(sdev, &xoops, &panic_info, stack,
+ STACK_DUMP_SIZE);
+ snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
+ STACK_DUMP_SIZE);
+
+ /* provide some context for firmware debug */
+ imrx = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IMRX);
+ imrd = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IMRD);
+ dev_err(sdev->dev,
+ "error: ipc host -> DSP: pending %s complete %s raw 0x%llx\n",
+ (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
+ (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
+ dev_err(sdev->dev,
+ "error: mask host: pending %s complete %s raw 0x%llx\n",
+ (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
+ (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
+ dev_err(sdev->dev,
+ "error: ipc DSP -> host: pending %s complete %s raw 0x%llx\n",
+ (status & SHIM_IPCD_BUSY) ? "yes" : "no",
+ (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
+ dev_err(sdev->dev,
+ "error: mask DSP: pending %s complete %s raw 0x%llx\n",
+ (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
+ (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
+
+}
+EXPORT_SYMBOL_NS(atom_dump, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+/*
+ * IPC Doorbell IRQ handler and thread.
+ */
+
+irqreturn_t atom_irq_handler(int irq, void *context)
+{
+ struct snd_sof_dev *sdev = context;
+ u64 ipcx, ipcd;
+ int ret = IRQ_NONE;
+
+ ipcx = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCX);
+ ipcd = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCD);
+
+ if (ipcx & SHIM_BYT_IPCX_DONE) {
+
+ /* reply message from DSP, Mask Done interrupt first */
+ snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR,
+ SHIM_IMRX,
+ SHIM_IMRX_DONE,
+ SHIM_IMRX_DONE);
+ ret = IRQ_WAKE_THREAD;
+ }
+
+ if (ipcd & SHIM_BYT_IPCD_BUSY) {
+
+ /* new message from DSP, Mask Busy interrupt first */
+ snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR,
+ SHIM_IMRX,
+ SHIM_IMRX_BUSY,
+ SHIM_IMRX_BUSY);
+ ret = IRQ_WAKE_THREAD;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_NS(atom_irq_handler, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+irqreturn_t atom_irq_thread(int irq, void *context)
+{
+ struct snd_sof_dev *sdev = context;
+ u64 ipcx, ipcd;
+
+ ipcx = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCX);
+ ipcd = snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_IPCD);
+
+ /* reply message from DSP */
+ if (ipcx & SHIM_BYT_IPCX_DONE) {
+
+ spin_lock_irq(&sdev->ipc_lock);
+
+ /*
+ * handle immediate reply from DSP core. If the msg is
+ * found, set done bit in cmd_done which is called at the
+ * end of message processing function, else set it here
+ * because the done bit can't be set in cmd_done function
+ * which is triggered by msg
+ */
+ atom_get_reply(sdev);
+ snd_sof_ipc_reply(sdev, ipcx);
+
+ atom_dsp_done(sdev);
+
+ spin_unlock_irq(&sdev->ipc_lock);
+ }
+
+ /* new message from DSP */
+ if (ipcd & SHIM_BYT_IPCD_BUSY) {
+
+ /* Handle messages from DSP Core */
+ if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
+ snd_sof_dsp_panic(sdev, PANIC_OFFSET(ipcd) +
+ MBOX_OFFSET);
+ } else {
+ snd_sof_ipc_msgs_rx(sdev);
+ }
+
+ atom_host_done(sdev);
+ }
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_NS(atom_irq_thread, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+int atom_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
+{
+ /* unmask and prepare to receive Done interrupt */
+ snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IMRX,
+ SHIM_IMRX_DONE, 0);
+
+ /* send the message */
+ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+ msg->msg_size);
+ snd_sof_dsp_write64(sdev, DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(atom_send_msg, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+static void atom_get_reply(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_ipc_msg *msg = sdev->msg;
+ struct sof_ipc_reply reply;
+ int ret = 0;
+
+ /*
+ * Sometimes, there is unexpected reply ipc arriving. The reply
+ * ipc belongs to none of the ipcs sent from driver.
+ * In this case, the driver must ignore the ipc.
+ */
+ if (!msg) {
+ dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
+ return;
+ }
+
+ /* get reply */
+ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
+
+ if (reply.error < 0) {
+ memcpy(msg->reply_data, &reply, sizeof(reply));
+ ret = reply.error;
+ } else {
+ /* reply correct size ? */
+ if (reply.hdr.size != msg->reply_size) {
+ dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
+ msg->reply_size, reply.hdr.size);
+ ret = -EINVAL;
+ }
+
+ /* read the message */
+ if (msg->reply_size > 0)
+ sof_mailbox_read(sdev, sdev->host_box.offset,
+ msg->reply_data, msg->reply_size);
+ }
+
+ msg->reply_error = ret;
+}
+
+int atom_get_mailbox_offset(struct snd_sof_dev *sdev)
+{
+ return MBOX_OFFSET;
+}
+EXPORT_SYMBOL_NS(atom_get_mailbox_offset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+int atom_get_window_offset(struct snd_sof_dev *sdev, u32 id)
+{
+ return MBOX_OFFSET;
+}
+EXPORT_SYMBOL_NS(atom_get_window_offset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+static void atom_host_done(struct snd_sof_dev *sdev)
+{
+ /* clear BUSY bit and set DONE bit - accept new messages */
+ snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IPCD,
+ SHIM_BYT_IPCD_BUSY |
+ SHIM_BYT_IPCD_DONE,
+ SHIM_BYT_IPCD_DONE);
+
+ /* unmask and prepare to receive next new message */
+ snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IMRX,
+ SHIM_IMRX_BUSY, 0);
+}
+
+static void atom_dsp_done(struct snd_sof_dev *sdev)
+{
+ /* clear DONE bit - tell DSP we have completed */
+ snd_sof_dsp_update_bits64_unlocked(sdev, DSP_BAR, SHIM_IPCX,
+ SHIM_BYT_IPCX_DONE, 0);
+}
+
+/*
+ * DSP control.
+ */
+
+int atom_run(struct snd_sof_dev *sdev)
+{
+ int tries = 10;
+
+ /* release stall and wait to unstall */
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
+ SHIM_BYT_CSR_STALL, 0x0);
+ while (tries--) {
+ if (!(snd_sof_dsp_read64(sdev, DSP_BAR, SHIM_CSR) &
+ SHIM_BYT_CSR_PWAITMODE))
+ break;
+ msleep(100);
+ }
+ if (tries < 0) {
+ dev_err(sdev->dev, "error: unable to run DSP firmware\n");
+ atom_dump(sdev, SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
+ return -ENODEV;
+ }
+
+ /* return init core mask */
+ return 1;
+}
+EXPORT_SYMBOL_NS(atom_run, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+int atom_reset(struct snd_sof_dev *sdev)
+{
+ /* put DSP into reset, set reset vector and stall */
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
+ SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
+ SHIM_BYT_CSR_STALL,
+ SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
+ SHIM_BYT_CSR_STALL);
+
+ usleep_range(10, 15);
+
+ /* take DSP out of reset and keep stalled for FW loading */
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
+ SHIM_BYT_CSR_RST, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(atom_reset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
+ const char *sof_tplg_filename,
+ const char *ssp_str)
+{
+ const char *tplg_filename = NULL;
+ char *filename;
+ char *split_ext;
+
+ filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
+ if (!filename)
+ return NULL;
+
+ /* this assumes a .tplg extension */
+ split_ext = strsep(&filename, ".");
+ if (split_ext) {
+ tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
+ "%s-%s.tplg",
+ split_ext, ssp_str);
+ if (!tplg_filename)
+ return NULL;
+ }
+ return tplg_filename;
+}
+
+void atom_machine_select(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_pdata *sof_pdata = sdev->pdata;
+ const struct sof_dev_desc *desc = sof_pdata->desc;
+ struct snd_soc_acpi_mach *mach;
+ struct platform_device *pdev;
+ const char *tplg_filename;
+
+ mach = snd_soc_acpi_find_machine(desc->machines);
+ if (!mach) {
+ dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
+ return;
+ }
+
+ pdev = to_platform_device(sdev->dev);
+ if (soc_intel_is_byt_cr(pdev)) {
+ dev_dbg(sdev->dev,
+ "BYT-CR detected, SSP0 used instead of SSP2\n");
+
+ tplg_filename = fixup_tplg_name(sdev,
+ mach->sof_tplg_filename,
+ "ssp0");
+ } else {
+ tplg_filename = mach->sof_tplg_filename;
+ }
+
+ if (!tplg_filename) {
+ dev_dbg(sdev->dev,
+ "error: no topology filename\n");
+ return;
+ }
+
+ sof_pdata->tplg_filename = tplg_filename;
+ mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
+ sof_pdata->machine = mach;
+}
+EXPORT_SYMBOL_NS(atom_machine_select, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+/* Atom DAIs */
+struct snd_soc_dai_driver atom_dai[] = {
+{
+ .name = "ssp0-port",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+},
+{
+ .name = "ssp1-port",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+},
+{
+ .name = "ssp2-port",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 8,
+ }
+},
+{
+ .name = "ssp3-port",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+},
+{
+ .name = "ssp4-port",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+},
+{
+ .name = "ssp5-port",
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 8,
+ },
+},
+};
+EXPORT_SYMBOL_NS(atom_dai, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+void atom_set_mach_params(const struct snd_soc_acpi_mach *mach,
+ struct snd_sof_dev *sdev)
+{
+ struct snd_sof_pdata *pdata = sdev->pdata;
+ const struct sof_dev_desc *desc = pdata->desc;
+ struct snd_soc_acpi_mach_params *mach_params;
+
+ mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
+ mach_params->platform = dev_name(sdev->dev);
+ mach_params->num_dai_drivers = desc->ops->num_drv;
+ mach_params->dai_drivers = desc->ops->drv;
+}
+EXPORT_SYMBOL_NS(atom_set_mach_params, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/sof/intel/atom.h b/sound/soc/sof/intel/atom.h
new file mode 100644
index 000000000000..96a462c7a2e5
--- /dev/null
+++ b/sound/soc/sof/intel/atom.h
@@ -0,0 +1,74 @@
+/* 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) 2017-2021 Intel Corporation. All rights reserved.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+ */
+
+#ifndef __SOF_INTEL_ATOM_H
+#define __SOF_INTEL_ATOM_H
+
+/* DSP memories */
+#define IRAM_OFFSET 0x0C0000
+#define IRAM_SIZE (80 * 1024)
+#define DRAM_OFFSET 0x100000
+#define DRAM_SIZE (160 * 1024)
+#define SHIM_OFFSET 0x140000
+#define SHIM_SIZE_BYT 0x100
+#define SHIM_SIZE_CHT 0x118
+#define MBOX_OFFSET 0x144000
+#define MBOX_SIZE 0x1000
+#define EXCEPT_OFFSET 0x800
+#define EXCEPT_MAX_HDR_SIZE 0x400
+
+/* DSP peripherals */
+#define DMAC0_OFFSET 0x098000
+#define DMAC1_OFFSET 0x09c000
+#define DMAC2_OFFSET 0x094000
+#define DMAC_SIZE 0x420
+#define SSP0_OFFSET 0x0a0000
+#define SSP1_OFFSET 0x0a1000
+#define SSP2_OFFSET 0x0a2000
+#define SSP3_OFFSET 0x0a4000
+#define SSP4_OFFSET 0x0a5000
+#define SSP5_OFFSET 0x0a6000
+#define SSP_SIZE 0x100
+
+#define STACK_DUMP_SIZE 32
+
+#define PCI_BAR_SIZE 0x200000
+
+#define PANIC_OFFSET(x) (((x) & GENMASK_ULL(47, 32)) >> 32)
+
+/*
+ * Debug
+ */
+
+#define MBOX_DUMP_SIZE 0x30
+
+/* BARs */
+#define DSP_BAR 0
+#define PCI_BAR 1
+#define IMR_BAR 2
+
+irqreturn_t atom_irq_handler(int irq, void *context);
+irqreturn_t atom_irq_thread(int irq, void *context);
+
+int atom_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg);
+int atom_get_mailbox_offset(struct snd_sof_dev *sdev);
+int atom_get_window_offset(struct snd_sof_dev *sdev, u32 id);
+
+int atom_run(struct snd_sof_dev *sdev);
+int atom_reset(struct snd_sof_dev *sdev);
+void atom_dump(struct snd_sof_dev *sdev, u32 flags);
+
+void atom_machine_select(struct snd_sof_dev *sdev);
+void atom_set_mach_params(const struct snd_soc_acpi_mach *mach,
+ struct snd_sof_dev *sdev);
+
+extern struct snd_soc_dai_driver atom_dai[];
+
+#endif
diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c
index d9803e2ba67f..8edaf6fdd218 100644
--- a/sound/soc/sof/intel/byt.c
+++ b/sound/soc/sof/intel/byt.c
@@ -19,662 +19,66 @@
#include <sound/soc-acpi-intel-match.h>
#include <sound/intel-dsp-config.h>
#include "../ops.h"
+#include "atom.h"
#include "shim.h"
#include "../sof-acpi-dev.h"
#include "../sof-audio.h"
#include "../../intel/common/soc-intel-quirks.h"
-/* DSP memories */
-#define IRAM_OFFSET 0x0C0000
-#define IRAM_SIZE (80 * 1024)
-#define DRAM_OFFSET 0x100000
-#define DRAM_SIZE (160 * 1024)
-#define SHIM_OFFSET 0x140000
-#define SHIM_SIZE_BYT 0x100
-#define SHIM_SIZE_CHT 0x118
-#define MBOX_OFFSET 0x144000
-#define MBOX_SIZE 0x1000
-#define EXCEPT_OFFSET 0x800
-#define EXCEPT_MAX_HDR_SIZE 0x400
-
-/* DSP peripherals */
-#define DMAC0_OFFSET 0x098000
-#define DMAC1_OFFSET 0x09c000
-#define DMAC2_OFFSET 0x094000
-#define DMAC_SIZE 0x420
-#define SSP0_OFFSET 0x0a0000
-#define SSP1_OFFSET 0x0a1000
-#define SSP2_OFFSET 0x0a2000
-#define SSP3_OFFSET 0x0a4000
-#define SSP4_OFFSET 0x0a5000
-#define SSP5_OFFSET 0x0a6000
-#define SSP_SIZE 0x100
-
-#define BYT_STACK_DUMP_SIZE 32
-
-#define BYT_PCI_BAR_SIZE 0x200000
-
-#define BYT_PANIC_OFFSET(x) (((x) & GENMASK_ULL(47, 32)) >> 32)
-
-/*
- * Debug
- */
-
-#define MBOX_DUMP_SIZE 0x30
-
-/* BARs */
-#define BYT_DSP_BAR 0
-#define BYT_PCI_BAR 1
-#define BYT_IMR_BAR 2
-
static const struct snd_sof_debugfs_map byt_debugfs[] = {
- {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
+ {"dmac0", DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
SOF_DEBUGFS_ACCESS_ALWAYS},
- {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
+ {"dmac1", DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
+ {"ssp0", DSP_BAR, SSP0_OFFSET, SSP_SIZE,
SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
+ {"ssp1", DSP_BAR, SSP1_OFFSET, SSP_SIZE,
SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
+ {"ssp2", DSP_BAR, SSP2_OFFSET, SSP_SIZE,
SOF_DEBUGFS_ACCESS_ALWAYS},
- {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
+ {"iram", DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
SOF_DEBUGFS_ACCESS_D0_ONLY},
- {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
+ {"dram", DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
SOF_DEBUGFS_ACCESS_D0_ONLY},
- {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_BYT,
+ {"shim", DSP_BAR, SHIM_OFFSET, SHIM_SIZE_BYT,
SOF_DEBUGFS_ACCESS_ALWAYS},
};
-static void byt_host_done(struct snd_sof_dev *sdev);
-static void byt_dsp_done(struct snd_sof_dev *sdev);
-static void byt_get_reply(struct snd_sof_dev *sdev);
-
-/*
- * Debug
- */
-
-static void byt_get_registers(struct snd_sof_dev *sdev,
- struct sof_ipc_dsp_oops_xtensa *xoops,
- struct sof_ipc_panic_info *panic_info,
- u32 *stack, size_t stack_words)
-{
- u32 offset = sdev->dsp_oops_offset;
-
- /* first read regsisters */
- sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
-
- /* note: variable AR register array is not read */
-
- /* then get panic info */
- if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
- dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
- xoops->arch_hdr.totalsize);
- return;
- }
- offset += xoops->arch_hdr.totalsize;
- sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
-
- /* then get the stack */
- offset += sizeof(*panic_info);
- sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
-}
-
-static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
-{
- struct sof_ipc_dsp_oops_xtensa xoops;
- struct sof_ipc_panic_info panic_info;
- u32 stack[BYT_STACK_DUMP_SIZE];
- u64 status, panic, imrd, imrx;
-
- /* now try generic SOF status messages */
- status = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
- panic = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
- byt_get_registers(sdev, &xoops, &panic_info, stack,
- BYT_STACK_DUMP_SIZE);
- snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
- BYT_STACK_DUMP_SIZE);
-
- /* provide some context for firmware debug */
- imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
- imrd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRD);
- dev_err(sdev->dev,
- "error: ipc host -> DSP: pending %s complete %s raw 0x%llx\n",
- (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
- (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
- dev_err(sdev->dev,
- "error: mask host: pending %s complete %s raw 0x%llx\n",
- (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
- (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
- dev_err(sdev->dev,
- "error: ipc DSP -> host: pending %s complete %s raw 0x%llx\n",
- (status & SHIM_IPCD_BUSY) ? "yes" : "no",
- (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
- dev_err(sdev->dev,
- "error: mask DSP: pending %s complete %s raw 0x%llx\n",
- (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
- (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
-
-}
-
-/*
- * IPC Doorbell IRQ handler and thread.
- */
-
-static irqreturn_t byt_irq_handler(int irq, void *context)
-{
- struct snd_sof_dev *sdev = context;
- u64 ipcx, ipcd;
- int ret = IRQ_NONE;
-
- ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
- ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
-
- if (ipcx & SHIM_BYT_IPCX_DONE) {
-
- /* reply message from DSP, Mask Done interrupt first */
- snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
- SHIM_IMRX,
- SHIM_IMRX_DONE,
- SHIM_IMRX_DONE);
- ret = IRQ_WAKE_THREAD;
- }
-
- if (ipcd & SHIM_BYT_IPCD_BUSY) {
-
- /* new message from DSP, Mask Busy interrupt first */
- snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
- SHIM_IMRX,
- SHIM_IMRX_BUSY,
- SHIM_IMRX_BUSY);
- ret = IRQ_WAKE_THREAD;
- }
-
- return ret;
-}
-
-static irqreturn_t byt_irq_thread(int irq, void *context)
-{
- struct snd_sof_dev *sdev = context;
- u64 ipcx, ipcd;
-
- ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
- ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
-
- /* reply message from DSP */
- if (ipcx & SHIM_BYT_IPCX_DONE) {
-
- spin_lock_irq(&sdev->ipc_lock);
-
- /*
- * handle immediate reply from DSP core. If the msg is
- * found, set done bit in cmd_done which is called at the
- * end of message processing function, else set it here
- * because the done bit can't be set in cmd_done function
- * which is triggered by msg
- */
- byt_get_reply(sdev);
- snd_sof_ipc_reply(sdev, ipcx);
-
- byt_dsp_done(sdev);
-
- spin_unlock_irq(&sdev->ipc_lock);
- }
-
- /* new message from DSP */
- if (ipcd & SHIM_BYT_IPCD_BUSY) {
-
- /* Handle messages from DSP Core */
- if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
- snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +
- MBOX_OFFSET);
- } else {
- snd_sof_ipc_msgs_rx(sdev);
- }
-
- byt_host_done(sdev);
- }
-
- return IRQ_HANDLED;
-}
-
-static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
-{
- /* unmask and prepare to receive Done interrupt */
- snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
- SHIM_IMRX_DONE, 0);
-
- /* send the message */
- sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
- msg->msg_size);
- snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
-
- return 0;
-}
-
-static void byt_get_reply(struct snd_sof_dev *sdev)
-{
- struct snd_sof_ipc_msg *msg = sdev->msg;
- struct sof_ipc_reply reply;
- int ret = 0;
-
- /*
- * Sometimes, there is unexpected reply ipc arriving. The reply
- * ipc belongs to none of the ipcs sent from driver.
- * In this case, the driver must ignore the ipc.
- */
- if (!msg) {
- dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
- return;
- }
-
- /* get reply */
- sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
-
- if (reply.error < 0) {
- memcpy(msg->reply_data, &reply, sizeof(reply));
- ret = reply.error;
- } else {
- /* reply correct size ? */
- if (reply.hdr.size != msg->reply_size) {
- dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
- msg->reply_size, reply.hdr.size);
- ret = -EINVAL;
- }
-
- /* read the message */
- if (msg->reply_size > 0)
- sof_mailbox_read(sdev, sdev->host_box.offset,
- msg->reply_data, msg->reply_size);
- }
-
- msg->reply_error = ret;
-}
-
-static int byt_get_mailbox_offset(struct snd_sof_dev *sdev)
-{
- return MBOX_OFFSET;
-}
-
-static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id)
-{
- return MBOX_OFFSET;
-}
-
-static void byt_host_done(struct snd_sof_dev *sdev)
-{
- /* clear BUSY bit and set DONE bit - accept new messages */
- snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD,
- SHIM_BYT_IPCD_BUSY |
- SHIM_BYT_IPCD_DONE,
- SHIM_BYT_IPCD_DONE);
-
- /* unmask and prepare to receive next new message */
- snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
- SHIM_IMRX_BUSY, 0);
-}
-
-static void byt_dsp_done(struct snd_sof_dev *sdev)
-{
- /* clear DONE bit - tell DSP we have completed */
- snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
- SHIM_BYT_IPCX_DONE, 0);
-}
-
-/*
- * DSP control.
- */
-
-static int byt_run(struct snd_sof_dev *sdev)
-{
- int tries = 10;
-
- /* release stall and wait to unstall */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
- SHIM_BYT_CSR_STALL, 0x0);
- while (tries--) {
- if (!(snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_CSR) &
- SHIM_BYT_CSR_PWAITMODE))
- break;
- msleep(100);
- }
- if (tries < 0) {
- dev_err(sdev->dev, "error: unable to run DSP firmware\n");
- byt_dump(sdev, SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
- return -ENODEV;
- }
-
- /* return init core mask */
- return 1;
-}
-
-static int byt_reset(struct snd_sof_dev *sdev)
-{
- /* put DSP into reset, set reset vector and stall */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
- SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
- SHIM_BYT_CSR_STALL,
- SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
- SHIM_BYT_CSR_STALL);
-
- usleep_range(10, 15);
-
- /* take DSP out of reset and keep stalled for FW loading */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
- SHIM_BYT_CSR_RST, 0);
-
- return 0;
-}
-
-static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
- const char *sof_tplg_filename,
- const char *ssp_str)
-{
- const char *tplg_filename = NULL;
- char *filename;
- char *split_ext;
-
- filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
- if (!filename)
- return NULL;
-
- /* this assumes a .tplg extension */
- split_ext = strsep(&filename, ".");
- if (split_ext) {
- tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
- "%s-%s.tplg",
- split_ext, ssp_str);
- if (!tplg_filename)
- return NULL;
- }
- return tplg_filename;
-}
-
-static void byt_machine_select(struct snd_sof_dev *sdev)
-{
- struct snd_sof_pdata *sof_pdata = sdev->pdata;
- const struct sof_dev_desc *desc = sof_pdata->desc;
- struct snd_soc_acpi_mach *mach;
- struct platform_device *pdev;
- const char *tplg_filename;
-
- mach = snd_soc_acpi_find_machine(desc->machines);
- if (!mach) {
- dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
- return;
- }
-
- pdev = to_platform_device(sdev->dev);
- if (soc_intel_is_byt_cr(pdev)) {
- dev_dbg(sdev->dev,
- "BYT-CR detected, SSP0 used instead of SSP2\n");
-
- tplg_filename = fixup_tplg_name(sdev,
- mach->sof_tplg_filename,
- "ssp0");
- } else {
- tplg_filename = mach->sof_tplg_filename;
- }
-
- if (!tplg_filename) {
- dev_dbg(sdev->dev,
- "error: no topology filename\n");
- return;
- }
-
- sof_pdata->tplg_filename = tplg_filename;
- mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
- sof_pdata->machine = mach;
-}
-
-/* Baytrail DAIs */
-static struct snd_soc_dai_driver byt_dai[] = {
-{
- .name = "ssp0-port",
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 8,
- },
-},
-{
- .name = "ssp1-port",
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 8,
- },
-},
-{
- .name = "ssp2-port",
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 8,
- }
-},
-{
- .name = "ssp3-port",
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 8,
- },
-},
-{
- .name = "ssp4-port",
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 8,
- },
-},
-{
- .name = "ssp5-port",
- .playback = {
- .channels_min = 1,
- .channels_max = 8,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 8,
- },
-},
-};
-
-static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach,
- struct snd_sof_dev *sdev)
-{
- struct snd_sof_pdata *pdata = sdev->pdata;
- const struct sof_dev_desc *desc = pdata->desc;
- struct snd_soc_acpi_mach_params *mach_params;
-
- mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
- mach_params->platform = dev_name(sdev->dev);
- mach_params->num_dai_drivers = desc->ops->num_drv;
- mach_params->dai_drivers = desc->ops->drv;
-}
-
-/*
- * Probe and remove.
- */
-
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
-
-static int tangier_pci_probe(struct snd_sof_dev *sdev)
-{
- struct snd_sof_pdata *pdata = sdev->pdata;
- const struct sof_dev_desc *desc = pdata->desc;
- struct pci_dev *pci = to_pci_dev(sdev->dev);
- u32 base, size;
- int ret;
-
- /* DSP DMA can only access low 31 bits of host memory */
- ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
- if (ret < 0) {
- dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
- return ret;
- }
-
- /* LPE base */
- base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
- size = BYT_PCI_BAR_SIZE;
-
- dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
- sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
- if (!sdev->bar[BYT_DSP_BAR]) {
- dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
- base, size);
- return -ENODEV;
- }
- dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
-
- /* IMR base - optional */
- if (desc->resindex_imr_base == -1)
- goto irq;
-
- base = pci_resource_start(pci, desc->resindex_imr_base);
- size = pci_resource_len(pci, desc->resindex_imr_base);
-
- /* some BIOSes don't map IMR */
- if (base == 0x55aa55aa || base == 0x0) {
- dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
- goto irq;
- }
-
- dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
- sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
- if (!sdev->bar[BYT_IMR_BAR]) {
- dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
- base, size);
- return -ENODEV;
- }
- dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
-
-irq:
- /* register our IRQ */
- sdev->ipc_irq = pci->irq;
- dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
- ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
- byt_irq_handler, byt_irq_thread,
- 0, "AudioDSP", sdev);
- if (ret < 0) {
- dev_err(sdev->dev, "error: failed to register IRQ %d\n",
- sdev->ipc_irq);
- return ret;
- }
-
- /* enable BUSY and disable DONE Interrupt by default */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX,
- SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
- SHIM_IMRX_DONE);
-
- /* set default mailbox offset for FW ready message */
- sdev->dsp_box.offset = MBOX_OFFSET;
-
- return ret;
-}
-
-const struct snd_sof_dsp_ops sof_tng_ops = {
- /* device init */
- .probe = tangier_pci_probe,
-
- /* DSP core boot / reset */
- .run = byt_run,
- .reset = byt_reset,
-
- /* Register IO */
- .write = sof_io_write,
- .read = sof_io_read,
- .write64 = sof_io_write64,
- .read64 = sof_io_read64,
-
- /* Block IO */
- .block_read = sof_block_read,
- .block_write = sof_block_write,
-
- /* doorbell */
- .irq_handler = byt_irq_handler,
- .irq_thread = byt_irq_thread,
-
- /* ipc */
- .send_msg = byt_send_msg,
- .fw_ready = sof_fw_ready,
- .get_mailbox_offset = byt_get_mailbox_offset,
- .get_window_offset = byt_get_window_offset,
-
- .ipc_msg_data = intel_ipc_msg_data,
- .ipc_pcm_params = intel_ipc_pcm_params,
-
- /* machine driver */
- .machine_select = byt_machine_select,
- .machine_register = sof_machine_register,
- .machine_unregister = sof_machine_unregister,
- .set_mach_params = byt_set_mach_params,
-
- /* debug */
- .debug_map = byt_debugfs,
- .debug_map_count = ARRAY_SIZE(byt_debugfs),
- .dbg_dump = byt_dump,
-
- /* stream callbacks */
- .pcm_open = intel_pcm_open,
- .pcm_close = intel_pcm_close,
-
- /* module loading */
- .load_module = snd_sof_parse_module_memcpy,
-
- /*Firmware loading */
- .load_firmware = snd_sof_load_firmware_memcpy,
-
- /* DAI drivers */
- .drv = byt_dai,
- .num_drv = 3, /* we have only 3 SSPs on byt*/
-
- /* ALSA HW info flags */
- .hw_info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_BATCH,
-
- .arch_ops = &sof_xtensa_arch_ops,
-};
-EXPORT_SYMBOL_NS(sof_tng_ops, SND_SOC_SOF_MERRIFIELD);
-
-const struct sof_intel_dsp_desc tng_chip_info = {
- .cores_num = 1,
- .host_managed_cores_mask = 1,
+static const struct snd_sof_debugfs_map cht_debugfs[] = {
+ {"dmac0", DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"dmac1", DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"dmac2", DSP_BAR, DMAC2_OFFSET, DMAC_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp0", DSP_BAR, SSP0_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp1", DSP_BAR, SSP1_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp2", DSP_BAR, SSP2_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp3", DSP_BAR, SSP3_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp4", DSP_BAR, SSP4_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp5", DSP_BAR, SSP5_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"iram", DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
+ SOF_DEBUGFS_ACCESS_D0_ONLY},
+ {"dram", DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
+ SOF_DEBUGFS_ACCESS_D0_ONLY},
+ {"shim", DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
};
-EXPORT_SYMBOL_NS(tng_chip_info, SND_SOC_SOF_MERRIFIELD);
-
-#endif /* CONFIG_SND_SOC_SOF_MERRIFIELD */
-
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
static void byt_reset_dsp_disable_int(struct snd_sof_dev *sdev)
{
/* Disable Interrupt from both sides */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x3);
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x3);
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_IMRX, 0x3, 0x3);
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_IMRD, 0x3, 0x3);
/* Put DSP into reset, set reset vector */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_CSR,
SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL,
SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL);
}
@@ -689,7 +93,7 @@ static int byt_suspend(struct snd_sof_dev *sdev, u32 target_state)
static int byt_resume(struct snd_sof_dev *sdev)
{
/* enable BUSY and disable DONE Interrupt by default */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX,
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_IMRX,
SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
SHIM_IMRX_DONE);
@@ -703,33 +107,6 @@ static int byt_remove(struct snd_sof_dev *sdev)
return 0;
}
-static const struct snd_sof_debugfs_map cht_debugfs[] = {
- {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE,
- SOF_DEBUGFS_ACCESS_ALWAYS},
- {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
- SOF_DEBUGFS_ACCESS_D0_ONLY},
- {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
- SOF_DEBUGFS_ACCESS_D0_ONLY},
- {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT,
- SOF_DEBUGFS_ACCESS_ALWAYS},
-};
-
static int byt_acpi_probe(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *pdata = sdev->pdata;
@@ -760,17 +137,17 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev)
}
dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
- sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
- if (!sdev->bar[BYT_DSP_BAR]) {
+ sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size);
+ if (!sdev->bar[DSP_BAR]) {
dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
base, size);
return -ENODEV;
}
- dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
+ dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[DSP_BAR]);
/* TODO: add offsets */
- sdev->mmio_bar = BYT_DSP_BAR;
- sdev->mailbox_bar = BYT_DSP_BAR;
+ sdev->mmio_bar = DSP_BAR;
+ sdev->mailbox_bar = DSP_BAR;
/* IMR base - optional */
if (desc->resindex_imr_base == -1)
@@ -794,13 +171,13 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev)
}
dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
- sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
- if (!sdev->bar[BYT_IMR_BAR]) {
+ sdev->bar[IMR_BAR] = devm_ioremap(sdev->dev, base, size);
+ if (!sdev->bar[IMR_BAR]) {
dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
base, size);
return -ENODEV;
}
- dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
+ dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[IMR_BAR]);
irq:
/* register our IRQ */
@@ -810,7 +187,7 @@ irq:
dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
- byt_irq_handler, byt_irq_thread,
+ atom_irq_handler, atom_irq_thread,
IRQF_SHARED, "AudioDSP", sdev);
if (ret < 0) {
dev_err(sdev->dev, "error: failed to register IRQ %d\n",
@@ -819,7 +196,7 @@ irq:
}
/* enable BUSY and disable DONE Interrupt by default */
- snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX,
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_IMRX,
SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
SHIM_IMRX_DONE);
@@ -836,8 +213,8 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
.remove = byt_remove,
/* DSP core boot / reset */
- .run = byt_run,
- .reset = byt_reset,
+ .run = atom_run,
+ .reset = atom_reset,
/* Register IO */
.write = sof_io_write,
@@ -850,28 +227,28 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
.block_write = sof_block_write,
/* doorbell */
- .irq_handler = byt_irq_handler,
- .irq_thread = byt_irq_thread,
+ .irq_handler = atom_irq_handler,
+ .irq_thread = atom_irq_thread,
/* ipc */
- .send_msg = byt_send_msg,
+ .send_msg = atom_send_msg,
.fw_ready = sof_fw_ready,
- .get_mailbox_offset = byt_get_mailbox_offset,
- .get_window_offset = byt_get_window_offset,
+ .get_mailbox_offset = atom_get_mailbox_offset,
+ .get_window_offset = atom_get_window_offset,
.ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params,
/* machine driver */
- .machine_select = byt_machine_select,
+ .machine_select = atom_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
- .set_mach_params = byt_set_mach_params,
+ .set_mach_params = atom_set_mach_params,
/* debug */
.debug_map = byt_debugfs,
.debug_map_count = ARRAY_SIZE(byt_debugfs),
- .dbg_dump = byt_dump,
+ .dbg_dump = atom_dump,
/* stream callbacks */
.pcm_open = intel_pcm_open,
@@ -888,7 +265,7 @@ static const struct snd_sof_dsp_ops sof_byt_ops = {
.resume = byt_resume,
/* DAI drivers */
- .drv = byt_dai,
+ .drv = atom_dai,
.num_drv = 3, /* we have only 3 SSPs on byt*/
/* ALSA HW info flags */
@@ -913,8 +290,8 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
.remove = byt_remove,
/* DSP core boot / reset */
- .run = byt_run,
- .reset = byt_reset,
+ .run = atom_run,
+ .reset = atom_reset,
/* Register IO */
.write = sof_io_write,
@@ -927,28 +304,28 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
.block_write = sof_block_write,
/* doorbell */
- .irq_handler = byt_irq_handler,
- .irq_thread = byt_irq_thread,
+ .irq_handler = atom_irq_handler,
+ .irq_thread = atom_irq_thread,
/* ipc */
- .send_msg = byt_send_msg,
+ .send_msg = atom_send_msg,
.fw_ready = sof_fw_ready,
- .get_mailbox_offset = byt_get_mailbox_offset,
- .get_window_offset = byt_get_window_offset,
+ .get_mailbox_offset = atom_get_mailbox_offset,
+ .get_window_offset = atom_get_window_offset,
.ipc_msg_data = intel_ipc_msg_data,
.ipc_pcm_params = intel_ipc_pcm_params,
/* machine driver */
- .machine_select = byt_machine_select,
+ .machine_select = atom_machine_select,
.machine_register = sof_machine_register,
.machine_unregister = sof_machine_unregister,
- .set_mach_params = byt_set_mach_params,
+ .set_mach_params = atom_set_mach_params,
/* debug */
.debug_map = cht_debugfs,
.debug_map_count = ARRAY_SIZE(cht_debugfs),
- .dbg_dump = byt_dump,
+ .dbg_dump = atom_dump,
/* stream callbacks */
.pcm_open = intel_pcm_open,
@@ -965,9 +342,9 @@ static const struct snd_sof_dsp_ops sof_cht_ops = {
.resume = byt_resume,
/* DAI drivers */
- .drv = byt_dai,
+ .drv = atom_dai,
/* all 6 SSPs may be available for cherrytrail */
- .num_drv = ARRAY_SIZE(byt_dai),
+ .num_drv = 6,
/* ALSA HW info flags */
.hw_info = SNDRV_PCM_INFO_MMAP |
@@ -1073,9 +450,8 @@ static struct platform_driver snd_sof_acpi_intel_byt_driver = {
};
module_platform_driver(snd_sof_acpi_intel_byt_driver);
-#endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */
-
MODULE_LICENSE("Dual BSD/GPL");
MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
MODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);
+MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index fc25ee8f68dc..6f4771bf9de3 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -385,11 +385,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
if (i == HDA_FW_BOOT_ATTEMPTS) {
dev_err(sdev->dev, "error: dsp init failed after %d attempts with err: %d\n",
i, ret);
- dev_err(sdev->dev, "ROM error=0x%x: FW status=0x%x\n",
- snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_DSP_SRAM_REG_ROM_ERROR),
- snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_DSP_SRAM_REG_ROM_STATUS));
goto cleanup;
}
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index b00e8fcb2312..e1e368ff2b12 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -277,10 +277,12 @@ struct hda_dsp_msg_code {
const char *msg;
};
-static bool hda_use_msi = IS_ENABLED(CONFIG_PCI);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG)
+static bool hda_use_msi = true;
module_param_named(use_msi, hda_use_msi, bool, 0444);
MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode");
+#else
+#define hda_use_msi (1)
#endif
static char *hda_model;
@@ -392,28 +394,21 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
struct sof_ipc_dsp_oops_xtensa xoops;
struct sof_ipc_panic_info panic_info;
u32 stack[HDA_DSP_STACK_DUMP_SIZE];
- u32 status, panic;
- /* try APL specific status message types first */
+ /* print ROM/FW status */
hda_dsp_get_status(sdev);
- /* now try generic SOF status messages */
- status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
- HDA_DSP_SRAM_REG_FW_STATUS);
- panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP);
-
+ /* print panic info if FW boot is complete. Otherwise, print the extended ROM status */
if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) {
+ u32 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_STATUS);
+ u32 panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP);
+
hda_dsp_get_registers(sdev, &xoops, &panic_info, stack,
HDA_DSP_STACK_DUMP_SIZE);
snd_sof_get_status(sdev, status, panic, &xoops, &panic_info,
stack, HDA_DSP_STACK_DUMP_SIZE);
} else {
- sof_dev_dbg_or_err(sdev->dev, flags & SOF_DBG_DUMP_FORCE_ERR_LEVEL,
- "status = 0x%8.8x panic = 0x%8.8x\n",
- status, panic);
-
hda_dsp_dump_ext_rom_status(sdev, flags);
- hda_dsp_get_status(sdev);
}
}
@@ -485,9 +480,7 @@ static int hda_init(struct snd_sof_dev *sdev)
/* initialise hdac bus */
bus->addr = pci_resource_start(pci, 0);
-#if IS_ENABLED(CONFIG_PCI)
bus->remap_addr = pci_ioremap_bar(pci, 0);
-#endif
if (!bus->remap_addr) {
dev_err(bus->dev, "error: ioremap error\n");
return -ENXIO;
@@ -799,9 +792,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
goto hdac_bus_unmap;
/* DSP base */
-#if IS_ENABLED(CONFIG_PCI)
sdev->bar[HDA_DSP_BAR] = pci_ioremap_bar(pci, HDA_DSP_BAR);
-#endif
if (!sdev->bar[HDA_DSP_BAR]) {
dev_err(sdev->dev, "error: ioremap error\n");
ret = -ENXIO;
@@ -1069,7 +1060,7 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
/* find out how many identical parts are expected */
for (k = 0; k < link->num_adr; k++) {
- u64 adr2 = link->adr_d[i].adr;
+ u64 adr2 = link->adr_d[k].adr;
unsigned int part_id2, link_id2, mfg_id2;
mfg_id2 = SDW_MFG_ID(adr2);
diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c
index 88c3bf404dd7..a00262184efa 100644
--- a/sound/soc/sof/intel/pci-tgl.c
+++ b/sound/soc/sof/intel/pci-tgl.c
@@ -116,6 +116,8 @@ static const struct pci_device_id sof_pci_ids[] = {
.driver_data = (unsigned long)&adls_desc},
{ PCI_DEVICE(0x8086, 0x51c8), /* ADL-P */
.driver_data = (unsigned long)&adl_desc},
+ { PCI_DEVICE(0x8086, 0x51cc), /* ADL-M */
+ .driver_data = (unsigned long)&adl_desc},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, sof_pci_ids);
diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c
index 94b9704c0117..4ee1da397d4e 100644
--- a/sound/soc/sof/intel/pci-tng.c
+++ b/sound/soc/sof/intel/pci-tng.c
@@ -14,7 +14,10 @@
#include <sound/soc-acpi-intel-match.h>
#include <sound/sof.h>
#include "../ops.h"
+#include "atom.h"
+#include "shim.h"
#include "../sof-pci-dev.h"
+#include "../sof-audio.h"
/* platform specific devices */
#include "shim.h"
@@ -29,6 +32,170 @@ static struct snd_soc_acpi_mach sof_tng_machines[] = {
{}
};
+static const struct snd_sof_debugfs_map tng_debugfs[] = {
+ {"dmac0", DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"dmac1", DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp0", DSP_BAR, SSP0_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp1", DSP_BAR, SSP1_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"ssp2", DSP_BAR, SSP2_OFFSET, SSP_SIZE,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+ {"iram", DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
+ SOF_DEBUGFS_ACCESS_D0_ONLY},
+ {"dram", DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
+ SOF_DEBUGFS_ACCESS_D0_ONLY},
+ {"shim", DSP_BAR, SHIM_OFFSET, SHIM_SIZE_BYT,
+ SOF_DEBUGFS_ACCESS_ALWAYS},
+};
+
+static int tangier_pci_probe(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_pdata *pdata = sdev->pdata;
+ const struct sof_dev_desc *desc = pdata->desc;
+ struct pci_dev *pci = to_pci_dev(sdev->dev);
+ u32 base, size;
+ int ret;
+
+ /* DSP DMA can only access low 31 bits of host memory */
+ ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
+ if (ret < 0) {
+ dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
+ return ret;
+ }
+
+ /* LPE base */
+ base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
+ size = PCI_BAR_SIZE;
+
+ dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
+ sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size);
+ if (!sdev->bar[DSP_BAR]) {
+ dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
+ base, size);
+ return -ENODEV;
+ }
+ dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[DSP_BAR]);
+
+ /* IMR base - optional */
+ if (desc->resindex_imr_base == -1)
+ goto irq;
+
+ base = pci_resource_start(pci, desc->resindex_imr_base);
+ size = pci_resource_len(pci, desc->resindex_imr_base);
+
+ /* some BIOSes don't map IMR */
+ if (base == 0x55aa55aa || base == 0x0) {
+ dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
+ goto irq;
+ }
+
+ dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
+ sdev->bar[IMR_BAR] = devm_ioremap(sdev->dev, base, size);
+ if (!sdev->bar[IMR_BAR]) {
+ dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
+ base, size);
+ return -ENODEV;
+ }
+ dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[IMR_BAR]);
+
+irq:
+ /* register our IRQ */
+ sdev->ipc_irq = pci->irq;
+ dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
+ ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
+ atom_irq_handler, atom_irq_thread,
+ 0, "AudioDSP", sdev);
+ if (ret < 0) {
+ dev_err(sdev->dev, "error: failed to register IRQ %d\n",
+ sdev->ipc_irq);
+ return ret;
+ }
+
+ /* enable BUSY and disable DONE Interrupt by default */
+ snd_sof_dsp_update_bits64(sdev, DSP_BAR, SHIM_IMRX,
+ SHIM_IMRX_BUSY | SHIM_IMRX_DONE,
+ SHIM_IMRX_DONE);
+
+ /* set default mailbox offset for FW ready message */
+ sdev->dsp_box.offset = MBOX_OFFSET;
+
+ return ret;
+}
+
+const struct snd_sof_dsp_ops sof_tng_ops = {
+ /* device init */
+ .probe = tangier_pci_probe,
+
+ /* DSP core boot / reset */
+ .run = atom_run,
+ .reset = atom_reset,
+
+ /* Register IO */
+ .write = sof_io_write,
+ .read = sof_io_read,
+ .write64 = sof_io_write64,
+ .read64 = sof_io_read64,
+
+ /* Block IO */
+ .block_read = sof_block_read,
+ .block_write = sof_block_write,
+
+ /* doorbell */
+ .irq_handler = atom_irq_handler,
+ .irq_thread = atom_irq_thread,
+
+ /* ipc */
+ .send_msg = atom_send_msg,
+ .fw_ready = sof_fw_ready,
+ .get_mailbox_offset = atom_get_mailbox_offset,
+ .get_window_offset = atom_get_window_offset,
+
+ .ipc_msg_data = intel_ipc_msg_data,
+ .ipc_pcm_params = intel_ipc_pcm_params,
+
+ /* machine driver */
+ .machine_select = atom_machine_select,
+ .machine_register = sof_machine_register,
+ .machine_unregister = sof_machine_unregister,
+ .set_mach_params = atom_set_mach_params,
+
+ /* debug */
+ .debug_map = tng_debugfs,
+ .debug_map_count = ARRAY_SIZE(tng_debugfs),
+ .dbg_dump = atom_dump,
+
+ /* stream callbacks */
+ .pcm_open = intel_pcm_open,
+ .pcm_close = intel_pcm_close,
+
+ /* module loading */
+ .load_module = snd_sof_parse_module_memcpy,
+
+ /*Firmware loading */
+ .load_firmware = snd_sof_load_firmware_memcpy,
+
+ /* DAI drivers */
+ .drv = atom_dai,
+ .num_drv = 3, /* we have only 3 SSPs on byt*/
+
+ /* ALSA HW info flags */
+ .hw_info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_BATCH,
+
+ .arch_ops = &sof_xtensa_arch_ops,
+};
+
+const struct sof_intel_dsp_desc tng_chip_info = {
+ .cores_num = 1,
+ .host_managed_cores_mask = 1,
+};
+
static const struct sof_dev_desc tng_desc = {
.machines = sof_tng_machines,
.resindex_lpe_base = 3, /* IRAM, but subtract IRAM offset */
@@ -66,5 +233,7 @@ static struct pci_driver snd_sof_pci_intel_tng_driver = {
module_pci_driver(snd_sof_pci_intel_tng_driver);
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(SND_SOC_SOF_MERRIFIELD);
+MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
+MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c
index 6efaf766f2ab..2b38a77cd594 100644
--- a/sound/soc/sof/loader.c
+++ b/sound/soc/sof/loader.c
@@ -517,7 +517,7 @@ int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
return 0;
/* copy data from the DSP FW ready offset */
- sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready));
+ snd_sof_dsp_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready));
/* make sure ABI version is compatible */
ret = snd_sof_ipc_valid(sdev);
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index 323a0b3f561b..4a5d6e497f05 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -244,13 +244,13 @@ snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
static inline void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, u32 flags)
{
if (sof_ops(sdev)->dbg_dump)
- return sof_ops(sdev)->dbg_dump(sdev, flags);
+ sof_ops(sdev)->dbg_dump(sdev, flags);
}
static inline void snd_sof_ipc_dump(struct snd_sof_dev *sdev)
{
if (sof_ops(sdev)->ipc_dump)
- return sof_ops(sdev)->ipc_dump(sdev);
+ sof_ops(sdev)->ipc_dump(sdev);
}
/* register IO */
@@ -546,14 +546,16 @@ static inline const struct snd_sof_dsp_ops
(val) = snd_sof_dsp_read(sdev, bar, offset); \
if (cond) { \
dev_dbg(sdev->dev, \
- "FW Poll Status: reg=%#x successful\n", (val)); \
+ "FW Poll Status: reg[%#x]=%#x successful\n", \
+ (offset), (val)); \
break; \
} \
if (__timeout_us && \
ktime_compare(ktime_get(), __timeout) > 0) { \
(val) = snd_sof_dsp_read(sdev, bar, offset); \
dev_dbg(sdev->dev, \
- "FW Poll Status: reg=%#x timedout\n", (val)); \
+ "FW Poll Status: reg[%#x]=%#x timedout\n", \
+ (offset), (val)); \
break; \
} \
if (__sleep_us) \
diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c
index 7fbf09f9f17e..74982c04497b 100644
--- a/sound/soc/sof/sof-acpi-dev.c
+++ b/sound/soc/sof/sof-acpi-dev.c
@@ -60,7 +60,6 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc
{
struct device *dev = &pdev->dev;
struct snd_sof_pdata *sof_pdata;
- const struct snd_sof_dsp_ops *ops;
dev_dbg(dev, "ACPI DSP detected");
@@ -68,9 +67,7 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc
if (!sof_pdata)
return -ENOMEM;
- /* get ops for platform */
- ops = desc->ops;
- if (!ops) {
+ if (!desc->ops) {
dev_err(dev, "error: no matching ACPI descriptor ops\n");
return -ENODEV;
}
diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c
index c9c70645b377..d1a21edfa05d 100644
--- a/sound/soc/sof/sof-of-dev.c
+++ b/sound/soc/sof/sof-of-dev.c
@@ -70,7 +70,6 @@ static int sof_of_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
const struct sof_dev_desc *desc;
struct snd_sof_pdata *sof_pdata;
- const struct snd_sof_dsp_ops *ops;
dev_info(&pdev->dev, "DT DSP detected");
@@ -82,9 +81,7 @@ static int sof_of_probe(struct platform_device *pdev)
if (!desc)
return -ENODEV;
- /* get ops for platform */
- ops = desc->ops;
- if (!ops) {
+ if (!desc->ops) {
dev_err(dev, "error: no matching DT descriptor ops\n");
return -ENODEV;
}
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index 3489dc1b48f6..03119462f9e2 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -116,14 +116,11 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
const struct sof_dev_desc *desc =
(const struct sof_dev_desc *)pci_id->driver_data;
struct snd_sof_pdata *sof_pdata;
- const struct snd_sof_dsp_ops *ops;
int ret;
dev_dbg(&pci->dev, "PCI DSP detected");
- /* get ops for platform */
- ops = desc->ops;
- if (!ops) {
+ if (!desc->ops) {
dev_err(dev, "error: no matching PCI descriptor ops\n");
return -ENODEV;
}
@@ -141,7 +138,7 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return ret;
sof_pdata->name = pci_name(pci);
- sof_pdata->desc = (struct sof_dev_desc *)pci_id->driver_data;
+ sof_pdata->desc = desc;
sof_pdata->dev = dev;
sof_pdata->fw_filename = desc->default_fw_filename;
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 59abcfc9bd55..cc9585bfa4e9 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1063,6 +1063,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
scontrol->min_volume_step = le32_to_cpu(mc->min);
scontrol->max_volume_step = le32_to_cpu(mc->max);
scontrol->num_channels = le32_to_cpu(mc->num_channels);
+ scontrol->control_data->index = kc->index;
/* set cmd for mixer control */
if (le32_to_cpu(mc->max) == 1) {
@@ -1140,7 +1141,7 @@ static int sof_control_load_enum(struct snd_soc_component *scomp,
scontrol->comp_id = sdev->next_comp_id;
scontrol->num_channels = le32_to_cpu(ec->num_channels);
-
+ scontrol->control_data->index = kc->index;
scontrol->cmd = SOF_CTRL_CMD_ENUM;
dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d comp_id %d\n",
@@ -1188,6 +1189,7 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
scontrol->comp_id = sdev->next_comp_id;
scontrol->cmd = SOF_CTRL_CMD_BINARY;
+ scontrol->control_data->index = kc->index;
dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d\n",
scontrol->comp_id, scontrol->num_channels);
@@ -2133,7 +2135,7 @@ static int sof_get_control_data(struct snd_soc_component *scomp,
for (i = 0; i < widget->num_kcontrols; i++) {
kc = &widget->kcontrol_news[i];
- switch (widget->dobj.widget.kcontrol_type) {
+ switch (widget->dobj.widget.kcontrol_type[i]) {
case SND_SOC_TPLG_TYPE_MIXER:
sm = (struct soc_mixer_control *)kc->private_value;
wdata[i].control = sm->dobj.private;
@@ -2147,8 +2149,8 @@ static int sof_get_control_data(struct snd_soc_component *scomp,
wdata[i].control = se->dobj.private;
break;
default:
- dev_err(scomp->dev, "error: unknown kcontrol type %d in widget %s\n",
- widget->dobj.widget.kcontrol_type,
+ dev_err(scomp->dev, "error: unknown kcontrol type %u in widget %s\n",
+ widget->dobj.widget.kcontrol_type[i],
widget->name);
return -EINVAL;
}
@@ -2164,7 +2166,8 @@ static int sof_get_control_data(struct snd_soc_component *scomp,
return -EINVAL;
/* make sure data is valid - data can be updated at runtime */
- if (wdata[i].pdata->magic != SOF_ABI_MAGIC)
+ if (widget->dobj.widget.kcontrol_type[i] == SND_SOC_TPLG_TYPE_BYTES &&
+ wdata[i].pdata->magic != SOF_ABI_MAGIC)
return -EINVAL;
*size += wdata[i].pdata->size;
@@ -2605,7 +2608,7 @@ static int sof_widget_unload(struct snd_soc_component *scomp,
}
for (i = 0; i < widget->num_kcontrols; i++) {
kc = &widget->kcontrol_news[i];
- switch (dobj->widget.kcontrol_type) {
+ switch (widget->dobj.widget.kcontrol_type[i]) {
case SND_SOC_TPLG_TYPE_MIXER:
sm = (struct soc_mixer_control *)kc->private_value;
scontrol = sm->dobj.private;
@@ -3335,7 +3338,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index,
/* Copy common data to all config ipc structs */
for (i = 0; i < num_conf; i++) {
config[i].hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG;
- config[i].format = hw_config[i].fmt;
+ config[i].format = le32_to_cpu(hw_config[i].fmt);
config[i].type = common_config.type;
config[i].dai_index = common_config.dai_index;
}