summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorCezary Rojewski <cezary.rojewski@intel.com>2020-10-06 08:48:58 +0200
committerMark Brown <broonie@kernel.org>2020-10-06 15:12:21 +0100
commit07833cd0569bb73cc9f82814cdab921abb3dfb4a (patch)
tree8c4e10e2b2b4aef7d6441b149feb2631ea8281b1 /sound/soc
parent3056cb0082feccee9a0012440ee5e4ca6a6e80ac (diff)
ASoC: Intel: Remove baytrail solution
sound/soc/intel/baytrail is a niche solution which supports limited number of BYT products - as described by snd_soc_acpi_intel_baytrail_legacy_machines table. For a long time it's deprecated in favor of sound/soc/intel/atom solution with SOF providing support for some products too effectively rendering /baytrail/ redundant. Remove deprecated code from ASoC tree. Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Liam Girdwood <liam.r.girdwood@intel.com> Link: https://lore.kernel.org/r/20201006064907.16277-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/intel/Kconfig13
-rw-r--r--sound/soc/intel/Makefile1
-rw-r--r--sound/soc/intel/baytrail/Makefile5
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-dsp.c358
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-ipc.c772
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-ipc.h64
-rw-r--r--sound/soc/intel/baytrail/sst-baytrail-pcm.c459
7 files changed, 0 insertions, 1672 deletions
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index dfc20f2bb859..41f9c286b34c 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -63,19 +63,6 @@ config SND_SOC_INTEL_HASWELL
tristate
select SND_SOC_INTEL_CATPT
-config SND_SOC_INTEL_BAYTRAIL
- tristate "Baytrail (legacy) Platforms"
- depends on DMADEVICES && ACPI && SND_SST_ATOM_HIFI2_PLATFORM=n && SND_SOC_SOF_BAYTRAIL=n
- select SND_SOC_INTEL_SST
- select SND_SOC_INTEL_SST_ACPI
- select SND_SOC_INTEL_SST_FIRMWARE
- select SND_SOC_ACPI_INTEL_MATCH
- help
- If you have a Intel Baytrail platform connected to an I2S codec,
- then enable this option by saying Y or m. This was typically used
- for Baytrail Chromebooks but this option is now deprecated and is
- not recommended, use SND_SST_ATOM_HIFI2_PLATFORM instead.
-
config SND_SST_ATOM_HIFI2_PLATFORM
tristate
select SND_SOC_COMPRESS
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index c88c615f85f7..4e0248d2accc 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -3,7 +3,6 @@
obj-$(CONFIG_SND_SOC) += common/
# Platform Support
-obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/
obj-$(CONFIG_SND_SOC_INTEL_CATPT) += catpt/
obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/
diff --git a/sound/soc/intel/baytrail/Makefile b/sound/soc/intel/baytrail/Makefile
deleted file mode 100644
index 4d0806aac6bd..000000000000
--- a/sound/soc/intel/baytrail/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-snd-soc-sst-baytrail-pcm-objs := \
- sst-baytrail-ipc.o sst-baytrail-pcm.o sst-baytrail-dsp.o
-
-obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += snd-soc-sst-baytrail-pcm.o
diff --git a/sound/soc/intel/baytrail/sst-baytrail-dsp.c b/sound/soc/intel/baytrail/sst-baytrail-dsp.c
deleted file mode 100644
index 4116ba66a4c2..000000000000
--- a/sound/soc/intel/baytrail/sst-baytrail-dsp.c
+++ /dev/null
@@ -1,358 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel Baytrail SST DSP driver
- * Copyright (c) 2014, Intel Corporation.
- */
-
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/firmware.h>
-
-#include "../common/sst-dsp.h"
-#include "../common/sst-dsp-priv.h"
-#include "sst-baytrail-ipc.h"
-
-#define SST_BYT_FW_SIGNATURE_SIZE 4
-#define SST_BYT_FW_SIGN "$SST"
-
-#define SST_BYT_IRAM_OFFSET 0xC0000
-#define SST_BYT_DRAM_OFFSET 0x100000
-#define SST_BYT_SHIM_OFFSET 0x140000
-
-enum sst_ram_type {
- SST_BYT_IRAM = 1,
- SST_BYT_DRAM = 2,
- SST_BYT_CACHE = 3,
-};
-
-struct dma_block_info {
- enum sst_ram_type type; /* IRAM/DRAM */
- u32 size; /* Bytes */
- u32 ram_offset; /* Offset in I/DRAM */
- u32 rsvd; /* Reserved field */
-};
-
-struct fw_header {
- unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE];
- u32 file_size; /* size of fw minus this header */
- u32 modules; /* # of modules */
- u32 file_format; /* version of header format */
- u32 reserved[4];
-};
-
-struct sst_byt_fw_module_header {
- unsigned char signature[SST_BYT_FW_SIGNATURE_SIZE];
- u32 mod_size; /* size of module */
- u32 blocks; /* # of blocks */
- u32 type; /* codec type, pp lib */
- u32 entry_point;
-};
-
-static int sst_byt_parse_module(struct sst_dsp *dsp, struct sst_fw *fw,
- struct sst_byt_fw_module_header *module)
-{
- struct dma_block_info *block;
- struct sst_module *mod;
- struct sst_module_template template;
- int count;
-
- memset(&template, 0, sizeof(template));
- template.id = module->type;
- template.entry = module->entry_point;
-
- mod = sst_module_new(fw, &template, NULL);
- if (mod == NULL)
- return -ENOMEM;
-
- block = (void *)module + sizeof(*module);
-
- for (count = 0; count < module->blocks; count++) {
-
- if (block->size <= 0) {
- dev_err(dsp->dev, "block %d size invalid\n", count);
- return -EINVAL;
- }
-
- switch (block->type) {
- case SST_BYT_IRAM:
- mod->offset = block->ram_offset +
- dsp->addr.iram_offset;
- mod->type = SST_MEM_IRAM;
- break;
- case SST_BYT_DRAM:
- mod->offset = block->ram_offset +
- dsp->addr.dram_offset;
- mod->type = SST_MEM_DRAM;
- break;
- case SST_BYT_CACHE:
- mod->offset = block->ram_offset +
- (dsp->addr.fw_ext - dsp->addr.lpe);
- mod->type = SST_MEM_CACHE;
- break;
- default:
- dev_err(dsp->dev, "wrong ram type 0x%x in block0x%x\n",
- block->type, count);
- return -EINVAL;
- }
-
- mod->size = block->size;
- mod->data = (void *)block + sizeof(*block);
-
- sst_module_alloc_blocks(mod);
-
- block = (void *)block + sizeof(*block) + block->size;
- }
- return 0;
-}
-
-static int sst_byt_parse_fw_image(struct sst_fw *sst_fw)
-{
- struct fw_header *header;
- struct sst_byt_fw_module_header *module;
- struct sst_dsp *dsp = sst_fw->dsp;
- int ret, count;
-
- /* Read the header information from the data pointer */
- header = (struct fw_header *)sst_fw->dma_buf;
-
- /* verify FW */
- if ((strncmp(header->signature, SST_BYT_FW_SIGN, 4) != 0) ||
- (sst_fw->size != header->file_size + sizeof(*header))) {
- /* Invalid FW signature */
- dev_err(dsp->dev, "Invalid FW sign/filesize mismatch\n");
- return -EINVAL;
- }
-
- dev_dbg(dsp->dev,
- "header sign=%4s size=0x%x modules=0x%x fmt=0x%x size=%zu\n",
- header->signature, header->file_size, header->modules,
- header->file_format, sizeof(*header));
-
- module = (void *)sst_fw->dma_buf + sizeof(*header);
- for (count = 0; count < header->modules; count++) {
- /* module */
- ret = sst_byt_parse_module(dsp, sst_fw, module);
- if (ret < 0) {
- dev_err(dsp->dev, "invalid module %d\n", count);
- return ret;
- }
- module = (void *)module + sizeof(*module) + module->mod_size;
- }
-
- return 0;
-}
-
-static void sst_byt_dump_shim(struct sst_dsp *sst)
-{
- int i;
- u64 reg;
-
- for (i = 0; i <= 0xF0; i += 8) {
- reg = sst_dsp_shim_read64_unlocked(sst, i);
- if (reg)
- dev_dbg(sst->dev, "shim 0x%2.2x value 0x%16.16llx\n",
- i, reg);
- }
-
- for (i = 0x00; i <= 0xff; i += 4) {
- reg = readl(sst->addr.pci_cfg + i);
- if (reg)
- dev_dbg(sst->dev, "pci 0x%2.2x value 0x%8.8x\n",
- i, (u32)reg);
- }
-}
-
-static irqreturn_t sst_byt_irq(int irq, void *context)
-{
- struct sst_dsp *sst = (struct sst_dsp *) context;
- u64 isrx;
- irqreturn_t ret = IRQ_NONE;
-
- spin_lock(&sst->spinlock);
-
- isrx = sst_dsp_shim_read64_unlocked(sst, SST_ISRX);
- if (isrx & SST_ISRX_DONE) {
- /* ADSP has processed the message request from IA */
- sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCX,
- SST_BYT_IPCX_DONE, 0);
- ret = IRQ_WAKE_THREAD;
- }
- if (isrx & SST_BYT_ISRX_REQUEST) {
- /* mask message request from ADSP and do processing later */
- sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX,
- SST_BYT_IMRX_REQUEST,
- SST_BYT_IMRX_REQUEST);
- ret = IRQ_WAKE_THREAD;
- }
-
- spin_unlock(&sst->spinlock);
-
- return ret;
-}
-
-static void sst_byt_boot(struct sst_dsp *sst)
-{
- int tries = 10;
-
- /*
- * save the physical address of extended firmware block in the first
- * 4 bytes of the mailbox
- */
- memcpy_toio(sst->addr.lpe + SST_BYT_MAILBOX_OFFSET,
- &sst->pdata->fw_base, sizeof(u32));
-
- /* release stall and wait to unstall */
- sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_STALL, 0x0);
- while (tries--) {
- if (!(sst_dsp_shim_read64(sst, SST_CSR) &
- SST_BYT_CSR_PWAITMODE))
- break;
- msleep(100);
- }
- if (tries < 0) {
- dev_err(sst->dev, "unable to start DSP\n");
- sst_byt_dump_shim(sst);
- }
-}
-
-static void sst_byt_reset(struct sst_dsp *sst)
-{
- /* put DSP into reset, set reset vector and stall */
- sst_dsp_shim_update_bits64(sst, SST_CSR,
- SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL,
- SST_BYT_CSR_RST | SST_BYT_CSR_VECTOR_SEL | SST_BYT_CSR_STALL);
-
- udelay(10);
-
- /* take DSP out of reset and keep stalled for FW loading */
- sst_dsp_shim_update_bits64(sst, SST_CSR, SST_BYT_CSR_RST, 0);
-}
-
-struct sst_adsp_memregion {
- u32 start;
- u32 end;
- int blocks;
- enum sst_mem_type type;
-};
-
-/* BYT test stuff */
-static const struct sst_adsp_memregion byt_region[] = {
- {0xC0000, 0x100000, 8, SST_MEM_IRAM}, /* I-SRAM - 8 * 32kB */
- {0x100000, 0x140000, 8, SST_MEM_DRAM}, /* D-SRAM0 - 8 * 32kB */
-};
-
-static int sst_byt_resource_map(struct sst_dsp *sst, struct sst_pdata *pdata)
-{
- sst->addr.lpe_base = pdata->lpe_base;
- sst->addr.lpe = ioremap(pdata->lpe_base, pdata->lpe_size);
- if (!sst->addr.lpe)
- return -ENODEV;
-
- /* ADSP PCI MMIO config space */
- sst->addr.pci_cfg = ioremap(pdata->pcicfg_base, pdata->pcicfg_size);
- if (!sst->addr.pci_cfg) {
- iounmap(sst->addr.lpe);
- return -ENODEV;
- }
-
- /* SST Extended FW allocation */
- sst->addr.fw_ext = ioremap(pdata->fw_base, pdata->fw_size);
- if (!sst->addr.fw_ext) {
- iounmap(sst->addr.pci_cfg);
- iounmap(sst->addr.lpe);
- return -ENODEV;
- }
-
- /* SST Shim */
- sst->addr.shim = sst->addr.lpe + sst->addr.shim_offset;
-
- sst_dsp_mailbox_init(sst, SST_BYT_MAILBOX_OFFSET + 0x204,
- SST_BYT_IPC_MAX_PAYLOAD_SIZE,
- SST_BYT_MAILBOX_OFFSET,
- SST_BYT_IPC_MAX_PAYLOAD_SIZE);
-
- sst->irq = pdata->irq;
-
- return 0;
-}
-
-static int sst_byt_init(struct sst_dsp *sst, struct sst_pdata *pdata)
-{
- const struct sst_adsp_memregion *region;
- struct device *dev;
- int ret = -ENODEV, i, j, region_count;
- u32 offset, size;
-
- dev = sst->dev;
-
- switch (sst->id) {
- case SST_DEV_ID_BYT:
- region = byt_region;
- region_count = ARRAY_SIZE(byt_region);
- sst->addr.iram_offset = SST_BYT_IRAM_OFFSET;
- sst->addr.dram_offset = SST_BYT_DRAM_OFFSET;
- sst->addr.shim_offset = SST_BYT_SHIM_OFFSET;
- break;
- default:
- dev_err(dev, "failed to get mem resources\n");
- return ret;
- }
-
- ret = sst_byt_resource_map(sst, pdata);
- if (ret < 0) {
- dev_err(dev, "failed to map resources\n");
- return ret;
- }
-
- ret = dma_coerce_mask_and_coherent(sst->dma_dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- /* enable Interrupt from both sides */
- sst_dsp_shim_update_bits64(sst, SST_IMRX, 0x3, 0x0);
- sst_dsp_shim_update_bits64(sst, SST_IMRD, 0x3, 0x0);
-
- /* register DSP memory blocks - ideally we should get this from ACPI */
- for (i = 0; i < region_count; i++) {
- offset = region[i].start;
- size = (region[i].end - region[i].start) / region[i].blocks;
-
- /* register individual memory blocks */
- for (j = 0; j < region[i].blocks; j++) {
- sst_mem_block_register(sst, offset, size,
- region[i].type, NULL, j, sst);
- offset += size;
- }
- }
-
- return 0;
-}
-
-static void sst_byt_free(struct sst_dsp *sst)
-{
- sst_mem_block_unregister_all(sst);
- iounmap(sst->addr.lpe);
- iounmap(sst->addr.pci_cfg);
- iounmap(sst->addr.fw_ext);
-}
-
-struct sst_ops sst_byt_ops = {
- .reset = sst_byt_reset,
- .boot = sst_byt_boot,
- .write = sst_shim32_write,
- .read = sst_shim32_read,
- .write64 = sst_shim32_write64,
- .read64 = sst_shim32_read64,
- .ram_read = sst_memcpy_fromio_32,
- .ram_write = sst_memcpy_toio_32,
- .irq_handler = sst_byt_irq,
- .init = sst_byt_init,
- .free = sst_byt_free,
- .parse_fw = sst_byt_parse_fw_image,
-};
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
deleted file mode 100644
index 34746fd871b0..000000000000
--- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c
+++ /dev/null
@@ -1,772 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Intel Baytrail SST IPC Support
- * Copyright (c) 2014, Intel Corporation.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-#include <asm/div64.h>
-
-#include "sst-baytrail-ipc.h"
-#include "../common/sst-dsp.h"
-#include "../common/sst-dsp-priv.h"
-#include "../common/sst-ipc.h"
-
-/* IPC message timeout */
-#define IPC_TIMEOUT_MSECS 300
-#define IPC_BOOT_MSECS 200
-
-#define IPC_EMPTY_LIST_SIZE 8
-
-/* IPC header bits */
-#define IPC_HEADER_MSG_ID_MASK 0xff
-#define IPC_HEADER_MSG_ID(x) ((x) & IPC_HEADER_MSG_ID_MASK)
-#define IPC_HEADER_STR_ID_SHIFT 8
-#define IPC_HEADER_STR_ID_MASK 0x1f
-#define IPC_HEADER_STR_ID(x) (((x) & 0x1f) << IPC_HEADER_STR_ID_SHIFT)
-#define IPC_HEADER_LARGE_SHIFT 13
-#define IPC_HEADER_LARGE(x) (((x) & 0x1) << IPC_HEADER_LARGE_SHIFT)
-#define IPC_HEADER_DATA_SHIFT 16
-#define IPC_HEADER_DATA_MASK 0x3fff
-#define IPC_HEADER_DATA(x) (((x) & 0x3fff) << IPC_HEADER_DATA_SHIFT)
-
-/* mask for differentiating between notification and reply message */
-#define IPC_NOTIFICATION (0x1 << 7)
-
-/* I2L Stream config/control msgs */
-#define IPC_IA_ALLOC_STREAM 0x20
-#define IPC_IA_FREE_STREAM 0x21
-#define IPC_IA_PAUSE_STREAM 0x24
-#define IPC_IA_RESUME_STREAM 0x25
-#define IPC_IA_DROP_STREAM 0x26
-#define IPC_IA_START_STREAM 0x30
-
-/* notification messages */
-#define IPC_IA_FW_INIT_CMPLT 0x81
-#define IPC_SST_PERIOD_ELAPSED 0x97
-
-/* IPC messages between host and ADSP */
-struct sst_byt_address_info {
- u32 addr;
- u32 size;
-} __packed;
-
-struct sst_byt_str_type {
- u8 codec_type;
- u8 str_type;
- u8 operation;
- u8 protected_str;
- u8 time_slots;
- u8 reserved;
- u16 result;
-} __packed;
-
-struct sst_byt_pcm_params {
- u8 num_chan;
- u8 pcm_wd_sz;
- u8 use_offload_path;
- u8 reserved;
- u32 sfreq;
- u8 channel_map[8];
-} __packed;
-
-struct sst_byt_frames_info {
- u16 num_entries;
- u16 rsrvd;
- u32 frag_size;
- struct sst_byt_address_info ring_buf_info[8];
-} __packed;
-
-struct sst_byt_alloc_params {
- struct sst_byt_str_type str_type;
- struct sst_byt_pcm_params pcm_params;
- struct sst_byt_frames_info frame_info;
-} __packed;
-
-struct sst_byt_alloc_response {
- struct sst_byt_str_type str_type;
- u8 reserved[88];
-} __packed;
-
-struct sst_byt_start_stream_params {
- u32 byte_offset;
-} __packed;
-
-struct sst_byt_tstamp {
- u64 ring_buffer_counter;
- u64 hardware_counter;
- u64 frames_decoded;
- u64 bytes_decoded;
- u64 bytes_copied;
- u32 sampling_frequency;
- u32 channel_peak[8];
-} __packed;
-
-struct sst_byt_fw_version {
- u8 build;
- u8 minor;
- u8 major;
- u8 type;
-} __packed;
-
-struct sst_byt_fw_build_info {
- u8 date[16];
- u8 time[16];
-} __packed;
-
-struct sst_byt_fw_init {
- struct sst_byt_fw_version fw_version;
- struct sst_byt_fw_build_info build_info;
- u16 result;
- u8 module_id;
- u8 debug_info;
-} __packed;
-
-struct sst_byt_stream;
-struct sst_byt;
-
-/* stream infomation */
-struct sst_byt_stream {
- struct list_head node;
-
- /* configuration */
- struct sst_byt_alloc_params request;
- struct sst_byt_alloc_response reply;
-
- /* runtime info */
- struct sst_byt *byt;
- int str_id;
- bool commited;
- bool running;
-
- /* driver callback */
- u32 (*notify_position)(struct sst_byt_stream *stream, void *data);
- void *pdata;
-};
-
-/* SST Baytrail IPC data */
-struct sst_byt {
- struct device *dev;
- struct sst_dsp *dsp;
-
- /* stream */
- struct list_head stream_list;
-
- /* boot */
- wait_queue_head_t boot_wait;
- bool boot_complete;
- struct sst_fw *fw;
-
- /* IPC messaging */
- struct sst_generic_ipc ipc;
-};
-
-static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id)
-{
- return IPC_HEADER_MSG_ID(msg_id) | IPC_HEADER_STR_ID(str_id) |
- IPC_HEADER_LARGE(large) | IPC_HEADER_DATA(data) |
- SST_BYT_IPCX_BUSY;
-}
-
-static inline u16 sst_byt_header_msg_id(u64 header)
-{
- return header & IPC_HEADER_MSG_ID_MASK;
-}
-
-static inline u8 sst_byt_header_str_id(u64 header)
-{
- return (header >> IPC_HEADER_STR_ID_SHIFT) & IPC_HEADER_STR_ID_MASK;
-}
-
-static inline u16 sst_byt_header_data(u64 header)
-{
- return (header >> IPC_HEADER_DATA_SHIFT) & IPC_HEADER_DATA_MASK;
-}
-
-static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt,
- int stream_id)
-{
- struct sst_byt_stream *stream;
-
- list_for_each_entry(stream, &byt->stream_list, node) {
- if (stream->str_id == stream_id)
- return stream;
- }
-
- return NULL;
-}
-
-static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg)
-{
- struct sst_byt_stream *stream;
- u64 header = msg->tx.header;
- u8 stream_id = sst_byt_header_str_id(header);
- u8 stream_msg = sst_byt_header_msg_id(header);
-
- stream = sst_byt_get_stream(byt, stream_id);
- if (stream == NULL)
- return;
-
- switch (stream_msg) {
- case IPC_IA_DROP_STREAM:
- case IPC_IA_PAUSE_STREAM:
- case IPC_IA_FREE_STREAM:
- stream->running = false;
- break;
- case IPC_IA_START_STREAM:
- case IPC_IA_RESUME_STREAM:
- stream->running = true;
- break;
- }
-}
-
-static int sst_byt_process_reply(struct sst_byt *byt, u64 header)
-{
- struct ipc_message *msg;
-
- msg = sst_ipc_reply_find_msg(&byt->ipc, header);
- if (msg == NULL)
- return 1;
-
- msg->rx.header = header;
- if (header & IPC_HEADER_LARGE(true)) {
- msg->rx.size = sst_byt_header_data(header);
- sst_dsp_inbox_read(byt->dsp, msg->rx.data, msg->rx.size);
- }
-
- /* update any stream states */
- sst_byt_stream_update(byt, msg);
-
- list_del(&msg->list);
- /* wake up */
- sst_ipc_tx_msg_reply_complete(&byt->ipc, msg);
-
- return 1;
-}
-
-static void sst_byt_fw_ready(struct sst_byt *byt, u64 header)
-{
- dev_dbg(byt->dev, "ipc: DSP is ready 0x%llX\n", header);
-
- byt->boot_complete = true;
- wake_up(&byt->boot_wait);
-}
-
-static int sst_byt_process_notification(struct sst_byt *byt,
- unsigned long *flags)
-{
- struct sst_dsp *sst = byt->dsp;
- struct sst_byt_stream *stream;
- u64 header;
- u8 msg_id, stream_id;
-
- header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
- msg_id = sst_byt_header_msg_id(header);
-
- switch (msg_id) {
- case IPC_SST_PERIOD_ELAPSED:
- stream_id = sst_byt_header_str_id(header);
- stream = sst_byt_get_stream(byt, stream_id);
- if (stream && stream->running && stream->notify_position) {
- spin_unlock_irqrestore(&sst->spinlock, *flags);
- stream->notify_position(stream, stream->pdata);
- spin_lock_irqsave(&sst->spinlock, *flags);
- }
- break;
- case IPC_IA_FW_INIT_CMPLT:
- sst_byt_fw_ready(byt, header);
- break;
- }
-
- return 1;
-}
-
-static irqreturn_t sst_byt_irq_thread(int irq, void *context)
-{
- struct sst_dsp *sst = (struct sst_dsp *) context;
- struct sst_byt *byt = sst_dsp_get_thread_context(sst);
- struct sst_generic_ipc *ipc = &byt->ipc;
- u64 header;
- unsigned long flags;
-
- spin_lock_irqsave(&sst->spinlock, flags);
-
- header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
- if (header & SST_BYT_IPCD_BUSY) {
- if (header & IPC_NOTIFICATION) {
- /* message from ADSP */
- sst_byt_process_notification(byt, &flags);
- } else {
- /* reply from ADSP */
- sst_byt_process_reply(byt, header);
- }
- /*
- * clear IPCD BUSY bit and set DONE bit. Tell DSP we have
- * processed the message and can accept new. Clear data part
- * of the header
- */
- sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCD,
- SST_BYT_IPCD_DONE | SST_BYT_IPCD_BUSY |
- IPC_HEADER_DATA(IPC_HEADER_DATA_MASK),
- SST_BYT_IPCD_DONE);
- /* unmask message request interrupts */
- sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX,
- SST_BYT_IMRX_REQUEST, 0);
- }
-
- spin_unlock_irqrestore(&sst->spinlock, flags);
-
- /* continue to send any remaining messages... */
- schedule_work(&ipc->kwork);
-
- return IRQ_HANDLED;
-}
-
-/* stream API */
-struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id,
- u32 (*notify_position)(struct sst_byt_stream *stream, void *data),
- void *data)
-{
- struct sst_byt_stream *stream;
- struct sst_dsp *sst = byt->dsp;
- unsigned long flags;
-
- stream = kzalloc(sizeof(*stream), GFP_KERNEL);
- if (stream == NULL)
- return NULL;
-
- spin_lock_irqsave(&sst->spinlock, flags);
- list_add(&stream->node, &byt->stream_list);
- stream->notify_position = notify_position;
- stream->pdata = data;
- stream->byt = byt;
- stream->str_id = id;
- spin_unlock_irqrestore(&sst->spinlock, flags);
-
- return stream;
-}
-
-int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream,
- int bits)
-{
- stream->request.pcm_params.pcm_wd_sz = bits;
- return 0;
-}
-
-int sst_byt_stream_set_channels(struct sst_byt *byt,
- struct sst_byt_stream *stream, u8 channels)
-{
- stream->request.pcm_params.num_chan = channels;
- return 0;
-}
-
-int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream,
- unsigned int rate)
-{
- stream->request.pcm_params.sfreq = rate;
- return 0;
-}
-
-/* stream sonfiguration */
-int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream,
- int codec_type, int stream_type, int operation)
-{
- stream->request.str_type.codec_type = codec_type;
- stream->request.str_type.str_type = stream_type;
- stream->request.str_type.operation = operation;
- stream->request.str_type.time_slots = 0xc;
-
- return 0;
-}
-
-int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream,
- uint32_t buffer_addr, uint32_t buffer_size)
-{
- stream->request.frame_info.num_entries = 1;
- stream->request.frame_info.ring_buf_info[0].addr = buffer_addr;
- stream->request.frame_info.ring_buf_info[0].size = buffer_size;
- /* calculate bytes per 4 ms fragment */
- stream->request.frame_info.frag_size =
- stream->request.pcm_params.sfreq *
- stream->request.pcm_params.num_chan *
- stream->request.pcm_params.pcm_wd_sz / 8 *
- 4 / 1000;
- return 0;
-}
-
-int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream)
-{
- struct sst_ipc_message request, reply = {0};
- int ret;
-
- request.header = sst_byt_header(IPC_IA_ALLOC_STREAM,
- sizeof(stream->request) + sizeof(u32),
- true, stream->str_id);
- request.data = &stream->request;
- request.size = sizeof(stream->request);
- reply.data = &stream->reply;
- reply.size = sizeof(stream->reply);
-
- ret = sst_ipc_tx_message_wait(&byt->ipc, request, &reply);
- if (ret < 0) {
- dev_err(byt->dev, "ipc: error stream commit failed\n");
- return ret;
- }
-
- stream->commited = true;
-
- return 0;
-}
-
-int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
-{
- struct sst_ipc_message request = {0};
- int ret = 0;
- struct sst_dsp *sst = byt->dsp;
- unsigned long flags;
-
- if (!stream->commited)
- goto out;
-
- request.header = sst_byt_header(IPC_IA_FREE_STREAM,
- 0, false, stream->str_id);
- ret = sst_ipc_tx_message_wait(&byt->ipc, request, NULL);
- if (ret < 0) {
- dev_err(byt->dev, "ipc: free stream %d failed\n",
- stream->str_id);
- return -EAGAIN;
- }
-
- stream->commited = false;
-out:
- spin_lock_irqsave(&sst->spinlock, flags);
- list_del(&stream->node);
- kfree(stream);
- spin_unlock_irqrestore(&sst->spinlock, flags);
-
- return ret;
-}
-
-static int sst_byt_stream_operations(struct sst_byt *byt, int type,
- int stream_id, int wait)
-{
- struct sst_ipc_message request = {0};
-
- request.header = sst_byt_header(type, 0, false, stream_id);
- if (wait)
- return sst_ipc_tx_message_wait(&byt->ipc, request, NULL);
- else
- return sst_ipc_tx_message_nowait(&byt->ipc, request);
-}
-
-/* stream ALSA trigger operations */
-int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream,
- u32 start_offset)
-{
- struct sst_byt_start_stream_params start_stream;
- struct sst_ipc_message request;
- int ret;
-
- start_stream.byte_offset = start_offset;
- request.header = sst_byt_header(IPC_IA_START_STREAM,
- sizeof(start_stream) + sizeof(u32),
- true, stream->str_id);
- request.data = &start_stream;
- request.size = sizeof(start_stream);
-
- ret = sst_ipc_tx_message_nowait(&byt->ipc, request);
- if (ret < 0)
- dev_err(byt->dev, "ipc: error failed to start stream %d\n",
- stream->str_id);
-
- return ret;
-}
-
-int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream)
-{
- int ret;
-
- /* don't stop streams that are not commited */
- if (!stream->commited)
- return 0;
-
- ret = sst_byt_stream_operations(byt, IPC_IA_DROP_STREAM,
- stream->str_id, 0);
- if (ret < 0)
- dev_err(byt->dev, "ipc: error failed to stop stream %d\n",
- stream->str_id);
- return ret;
-}
-
-int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream)
-{
- int ret;
-
- ret = sst_byt_stream_operations(byt, IPC_IA_PAUSE_STREAM,
- stream->str_id, 0);
- if (ret < 0)
- dev_err(byt->dev, "ipc: error failed to pause stream %d\n",
- stream->str_id);
-
- return ret;
-}
-
-int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream)
-{
- int ret;
-
- ret = sst_byt_stream_operations(byt, IPC_IA_RESUME_STREAM,
- stream->str_id, 0);
- if (ret < 0)
- dev_err(byt->dev, "ipc: error failed to resume stream %d\n",
- stream->str_id);
-
- return ret;
-}
-
-int sst_byt_get_dsp_position(struct sst_byt *byt,
- struct sst_byt_stream *stream, int buffer_size)
-{
- struct sst_dsp *sst = byt->dsp;
- struct sst_byt_tstamp fw_tstamp;
- u8 str_id = stream->str_id;
- u32 tstamp_offset;
-
- tstamp_offset = SST_BYT_TIMESTAMP_OFFSET + str_id * sizeof(fw_tstamp);
- memcpy_fromio(&fw_tstamp,
- sst->addr.lpe + tstamp_offset, sizeof(fw_tstamp));
-
- return do_div(fw_tstamp.ring_buffer_counter, buffer_size);
-}
-
-struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt)
-{
- return byt->dsp;
-}
-
-static struct sst_dsp_device byt_dev = {
- .thread = sst_byt_irq_thread,
- .ops = &sst_byt_ops,
-};
-
-int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata)
-{
- struct sst_byt *byt = pdata->dsp;
-
- dev_dbg(byt->dev, "dsp reset\n");
- sst_dsp_reset(byt->dsp);
- sst_ipc_drop_all(&byt->ipc);
- dev_dbg(byt->dev, "dsp in reset\n");
-
- dev_dbg(byt->dev, "free all blocks and unload fw\n");
- sst_fw_unload(byt->fw);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_late);
-
-int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata)
-{
- struct sst_byt *byt = pdata->dsp;
- int ret;
-
- dev_dbg(byt->dev, "reload dsp fw\n");
-
- sst_dsp_reset(byt->dsp);
-
- ret = sst_fw_reload(byt->fw);
- if (ret < 0) {
- dev_err(dev, "error: failed to reload firmware\n");
- return ret;
- }
-
- /* wait for DSP boot completion */
- byt->boot_complete = false;
- sst_dsp_boot(byt->dsp);
- dev_dbg(byt->dev, "dsp booting...\n");
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(sst_byt_dsp_boot);
-
-int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata)
-{
- struct sst_byt *byt = pdata->dsp;
- int err;
-
- dev_dbg(byt->dev, "wait for dsp reboot\n");
-
- err = wait_event_timeout(byt->boot_wait, byt->boot_complete,
- msecs_to_jiffies(IPC_BOOT_MSECS));
- if (err == 0) {
- dev_err(byt->dev, "ipc: error DSP boot timeout\n");
- return -EIO;
- }
-
- dev_dbg(byt->dev, "dsp rebooted\n");
- return 0;
-}
-EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready);
-
-static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
-{
- if (msg->tx.header & IPC_HEADER_LARGE(true))
- sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
-
- sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->tx.header);
-}
-
-static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text)
-{
- struct sst_dsp *sst = ipc->dsp;
- u64 isr, ipcd, imrx, ipcx;
-
- ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX);
- isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX);
- ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
- imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX);
-
- dev_err(ipc->dev,
- "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n",
- text, ipcx, isr, ipcd, imrx);
-}
-
-static void byt_tx_data_copy(struct ipc_message *msg, char *tx_data,
- size_t tx_size)
-{
- /* msg content = lower 32-bit of the header + data */
- *(u32 *)msg->tx.data = (u32)(msg->tx.header & (u32)-1);
- memcpy(msg->tx.data + sizeof(u32), tx_data, tx_size);
- msg->tx.size += sizeof(u32);
-}
-
-static u64 byt_reply_msg_match(u64 header, u64 *mask)
-{
- /* match reply to message sent based on msg and stream IDs */
- *mask = IPC_HEADER_MSG_ID_MASK |
- IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT;
- header &= *mask;
-
- return header;
-}
-
-static bool byt_is_dsp_busy(struct sst_dsp *dsp)
-{
- u64 ipcx;
-
- ipcx = sst_dsp_shim_read64_unlocked(dsp, SST_IPCX);
- return (ipcx & (SST_BYT_IPCX_BUSY | SST_BYT_IPCX_DONE));
-}
-
-int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
-{
- struct sst_byt *byt;
- struct sst_generic_ipc *ipc;
- struct sst_fw *byt_sst_fw;
- struct sst_byt_fw_init init;
- int err;
-
- dev_dbg(dev, "initialising Byt DSP IPC\n");
-
- byt = devm_kzalloc(dev, sizeof(*byt), GFP_KERNEL);
- if (byt == NULL)
- return -ENOMEM;
-
- byt->dev = dev;
-
- ipc = &byt->ipc;
- ipc->dev = dev;
- ipc->ops.tx_msg = byt_tx_msg;
- ipc->ops.shim_dbg = byt_shim_dbg;
- ipc->ops.tx_data_copy = byt_tx_data_copy;
- ipc->ops.reply_msg_match = byt_reply_msg_match;
- ipc->ops.is_dsp_busy = byt_is_dsp_busy;
- ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES;
- ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES;
-
- err = sst_ipc_init(ipc);
- if (err != 0)
- goto ipc_init_err;
-
- INIT_LIST_HEAD(&byt->stream_list);
- init_waitqueue_head(&byt->boot_wait);
- byt_dev.thread_context = byt;
-
- /* init SST shim */
- byt->dsp = sst_dsp_new(dev, &byt_dev, pdata);
- if (byt->dsp == NULL) {
- err = -ENODEV;
- goto dsp_new_err;
- }
-
- ipc->dsp = byt->dsp;