# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
- control.o trace.o utils.o sof-audio.o stream-ipc.o
+ control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o
snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += sof-probes.o
snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += compress.o
snd-sof-nocodec-objs := nocodec.o
+snd-sof-utils-objs := sof-utils.o
+
obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o
obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o
+obj-$(CONFIG_SND_SOC_SOF) += snd-sof-utils.o
obj-$(CONFIG_SND_SOC_SOF_ACPI_DEV) += snd-sof-acpi.o
obj-$(CONFIG_SND_SOC_SOF_OF_DEV) += snd-sof-of.o
#include <sound/compress_driver.h>
#include "sof-audio.h"
#include "sof-priv.h"
+#include "sof-utils.h"
static void sof_set_transferred_bytes(struct snd_compr_tstamp *tstamp,
u64 host_pos, u64 buffer_size)
--- /dev/null
+// 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-2022 Intel Corporation. All rights reserved.
+//
+// Author: Keyon Jie <yang.jie@linux.intel.com>
+//
+
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/platform_device.h>
+#include <asm/unaligned.h>
+#include <sound/soc.h>
+#include <sound/sof.h>
+#include "sof-priv.h"
+#include "ops.h"
+
+/*
+ * Register IO
+ *
+ * The sof_io_xyz() wrappers are typically referenced in snd_sof_dsp_ops
+ * structures and cannot be inlined.
+ */
+
+void sof_io_write(struct snd_sof_dev *sdev, void __iomem *addr, u32 value)
+{
+ writel(value, addr);
+}
+EXPORT_SYMBOL(sof_io_write);
+
+u32 sof_io_read(struct snd_sof_dev *sdev, void __iomem *addr)
+{
+ return readl(addr);
+}
+EXPORT_SYMBOL(sof_io_read);
+
+void sof_io_write64(struct snd_sof_dev *sdev, void __iomem *addr, u64 value)
+{
+ writeq(value, addr);
+}
+EXPORT_SYMBOL(sof_io_write64);
+
+u64 sof_io_read64(struct snd_sof_dev *sdev, void __iomem *addr)
+{
+ return readq(addr);
+}
+EXPORT_SYMBOL(sof_io_read64);
+
+/*
+ * IPC Mailbox IO
+ */
+
+void sof_mailbox_write(struct snd_sof_dev *sdev, u32 offset,
+ void *message, size_t bytes)
+{
+ void __iomem *dest = sdev->bar[sdev->mailbox_bar] + offset;
+
+ memcpy_toio(dest, message, bytes);
+}
+EXPORT_SYMBOL(sof_mailbox_write);
+
+void sof_mailbox_read(struct snd_sof_dev *sdev, u32 offset,
+ void *message, size_t bytes)
+{
+ void __iomem *src = sdev->bar[sdev->mailbox_bar] + offset;
+
+ memcpy_fromio(message, src, bytes);
+}
+EXPORT_SYMBOL(sof_mailbox_read);
+
+/*
+ * Memory copy.
+ */
+
+int sof_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
+ u32 offset, void *src, size_t size)
+{
+ int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
+ const u8 *src_byte = src;
+ void __iomem *dest;
+ u32 affected_mask;
+ u32 tmp;
+ int m, n;
+
+ if (bar < 0)
+ return bar;
+
+ dest = sdev->bar[bar] + offset;
+
+ m = size / 4;
+ n = size % 4;
+
+ /* __iowrite32_copy use 32bit size values so divide by 4 */
+ __iowrite32_copy(dest, src, m);
+
+ if (n) {
+ affected_mask = (1 << (8 * n)) - 1;
+
+ /* first read the 32bit data of dest, then change affected
+ * bytes, and write back to dest. For unaffected bytes, it
+ * should not be changed
+ */
+ tmp = ioread32(dest + m * 4);
+ tmp &= ~affected_mask;
+
+ tmp |= *(u32 *)(src_byte + m * 4) & affected_mask;
+ iowrite32(tmp, dest + m * 4);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sof_block_write);
+
+int sof_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
+ u32 offset, void *dest, size_t size)
+{
+ int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
+
+ if (bar < 0)
+ return bar;
+
+ memcpy_fromio(dest, sdev->bar[bar] + offset, size);
+
+ return 0;
+}
+EXPORT_SYMBOL(sof_block_read);
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "sof-probes.h"
#endif
+#include "sof-utils.h"
/* Create DMA buffer page table for DSP */
static int create_page_table(struct snd_soc_component *component,
void snd_sof_new_platform_drv(struct snd_sof_dev *sdev);
-int snd_sof_create_page_table(struct device *dev,
- struct snd_dma_buffer *dmab,
- unsigned char *page_table, size_t size);
-
/*
* Firmware loading.
*/
--- /dev/null
+// 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-2022 Intel Corporation. All rights reserved.
+//
+// Author: Keyon Jie <yang.jie@linux.intel.com>
+//
+
+#include <asm/unaligned.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/device.h>
+#include <sound/memalloc.h>
+#include <linux/module.h>
+#include "sof-utils.h"
+
+/*
+ * Generic buffer page table creation.
+ * Take the each physical page address and drop the least significant unused
+ * bits from each (based on PAGE_SIZE). Then pack valid page address bits
+ * into compressed page table.
+ */
+
+int snd_sof_create_page_table(struct device *dev,
+ struct snd_dma_buffer *dmab,
+ unsigned char *page_table, size_t size)
+{
+ int i, pages;
+
+ pages = snd_sgbuf_aligned_pages(size);
+
+ dev_dbg(dev, "generating page table for %p size 0x%zx pages %d\n",
+ dmab->area, size, pages);
+
+ for (i = 0; i < pages; i++) {
+ /*
+ * The number of valid address bits for each page is 20.
+ * idx determines the byte position within page_table
+ * where the current page's address is stored
+ * in the compressed page_table.
+ * This can be calculated by multiplying the page number by 2.5.
+ */
+ u32 idx = (5 * i) >> 1;
+ u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT;
+ u8 *pg_table;
+
+ dev_vdbg(dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn);
+
+ pg_table = (u8 *)(page_table + idx);
+
+ /*
+ * pagetable compression:
+ * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5
+ * ___________pfn 0__________ __________pfn 1___________ _pfn 2...
+ * .... .... .... .... .... .... .... .... .... .... ....
+ * It is created by:
+ * 1. set current location to 0, PFN index i to 0
+ * 2. put pfn[i] at current location in Little Endian byte order
+ * 3. calculate an intermediate value as
+ * x = (pfn[i+1] << 4) | (pfn[i] & 0xf)
+ * 4. put x at offset (current location + 2) in LE byte order
+ * 5. increment current location by 5 bytes, increment i by 2
+ * 6. continue to (2)
+ */
+ if (i & 1)
+ put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4,
+ pg_table);
+ else
+ put_unaligned_le32(pfn, pg_table);
+ }
+
+ return pages;
+}
+EXPORT_SYMBOL(snd_sof_create_page_table);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- /dev/null
+/* 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) 2022 Intel Corporation. All rights reserved.
+ */
+
+#ifndef __SOC_SOF_UTILS_H
+#define __SOC_SOF_UTILS_H
+
+struct snd_dma_buffer;
+struct device;
+
+int snd_sof_create_page_table(struct device *dev,
+ struct snd_dma_buffer *dmab,
+ unsigned char *page_table, size_t size);
+
+#endif
#include <linux/sched/signal.h>
#include "sof-priv.h"
#include "ops.h"
+#include "sof-utils.h"
#define TRACE_FILTER_ELEMENTS_PER_ENTRY 4
#define TRACE_FILTER_MAX_CONFIG_STRING_LENGTH 1024
+++ /dev/null
-// 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 Intel Corporation. All rights reserved.
-//
-// Author: Keyon Jie <yang.jie@linux.intel.com>
-//
-
-#include <linux/io-64-nonatomic-lo-hi.h>
-#include <linux/platform_device.h>
-#include <asm/unaligned.h>
-#include <sound/soc.h>
-#include <sound/sof.h>
-#include "sof-priv.h"
-#include "ops.h"
-
-/*
- * Register IO
- *
- * The sof_io_xyz() wrappers are typically referenced in snd_sof_dsp_ops
- * structures and cannot be inlined.
- */
-
-void sof_io_write(struct snd_sof_dev *sdev, void __iomem *addr, u32 value)
-{
- writel(value, addr);
-}
-EXPORT_SYMBOL(sof_io_write);
-
-u32 sof_io_read(struct snd_sof_dev *sdev, void __iomem *addr)
-{
- return readl(addr);
-}
-EXPORT_SYMBOL(sof_io_read);
-
-void sof_io_write64(struct snd_sof_dev *sdev, void __iomem *addr, u64 value)
-{
- writeq(value, addr);
-}
-EXPORT_SYMBOL(sof_io_write64);
-
-u64 sof_io_read64(struct snd_sof_dev *sdev, void __iomem *addr)
-{
- return readq(addr);
-}
-EXPORT_SYMBOL(sof_io_read64);
-
-/*
- * IPC Mailbox IO
- */
-
-void sof_mailbox_write(struct snd_sof_dev *sdev, u32 offset,
- void *message, size_t bytes)
-{
- void __iomem *dest = sdev->bar[sdev->mailbox_bar] + offset;
-
- memcpy_toio(dest, message, bytes);
-}
-EXPORT_SYMBOL(sof_mailbox_write);
-
-void sof_mailbox_read(struct snd_sof_dev *sdev, u32 offset,
- void *message, size_t bytes)
-{
- void __iomem *src = sdev->bar[sdev->mailbox_bar] + offset;
-
- memcpy_fromio(message, src, bytes);
-}
-EXPORT_SYMBOL(sof_mailbox_read);
-
-/*
- * Memory copy.
- */
-
-int sof_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
- u32 offset, void *src, size_t size)
-{
- int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
- const u8 *src_byte = src;
- void __iomem *dest;
- u32 affected_mask;
- u32 tmp;
- int m, n;
-
- if (bar < 0)
- return bar;
-
- dest = sdev->bar[bar] + offset;
-
- m = size / 4;
- n = size % 4;
-
- /* __iowrite32_copy use 32bit size values so divide by 4 */
- __iowrite32_copy(dest, src, m);
-
- if (n) {
- affected_mask = (1 << (8 * n)) - 1;
-
- /* first read the 32bit data of dest, then change affected
- * bytes, and write back to dest. For unaffected bytes, it
- * should not be changed
- */
- tmp = ioread32(dest + m * 4);
- tmp &= ~affected_mask;
-
- tmp |= *(u32 *)(src_byte + m * 4) & affected_mask;
- iowrite32(tmp, dest + m * 4);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(sof_block_write);
-
-int sof_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
- u32 offset, void *dest, size_t size)
-{
- int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
-
- if (bar < 0)
- return bar;
-
- memcpy_fromio(dest, sdev->bar[bar] + offset, size);
-
- return 0;
-}
-EXPORT_SYMBOL(sof_block_read);
-
-/*
- * Generic buffer page table creation.
- * Take the each physical page address and drop the least significant unused
- * bits from each (based on PAGE_SIZE). Then pack valid page address bits
- * into compressed page table.
- */
-
-int snd_sof_create_page_table(struct device *dev,
- struct snd_dma_buffer *dmab,
- unsigned char *page_table, size_t size)
-{
- int i, pages;
-
- pages = snd_sgbuf_aligned_pages(size);
-
- dev_dbg(dev, "generating page table for %p size 0x%zx pages %d\n",
- dmab->area, size, pages);
-
- for (i = 0; i < pages; i++) {
- /*
- * The number of valid address bits for each page is 20.
- * idx determines the byte position within page_table
- * where the current page's address is stored
- * in the compressed page_table.
- * This can be calculated by multiplying the page number by 2.5.
- */
- u32 idx = (5 * i) >> 1;
- u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT;
- u8 *pg_table;
-
- dev_vdbg(dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn);
-
- pg_table = (u8 *)(page_table + idx);
-
- /*
- * pagetable compression:
- * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5
- * ___________pfn 0__________ __________pfn 1___________ _pfn 2...
- * .... .... .... .... .... .... .... .... .... .... ....
- * It is created by:
- * 1. set current location to 0, PFN index i to 0
- * 2. put pfn[i] at current location in Little Endian byte order
- * 3. calculate an intermediate value as
- * x = (pfn[i+1] << 4) | (pfn[i] & 0xf)
- * 4. put x at offset (current location + 2) in LE byte order
- * 5. increment current location by 5 bytes, increment i by 2
- * 6. continue to (2)
- */
- if (i & 1)
- put_unaligned_le32((pg_table[0] & 0xf) | pfn << 4,
- pg_table);
- else
- put_unaligned_le32(pfn, pg_table);
- }
-
- return pages;
-}
-EXPORT_SYMBOL(snd_sof_create_page_table);