summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@chromium.org>2019-02-27 13:11:21 +0800
committerCommit Bot <commit-bot@chromium.org>2019-09-19 07:59:10 +0000
commite0d9bb6fdef6fe87dac52ea7f26281f8d3239a7a (patch)
treefaa7c74175dd83a713a558e7c15f2ddedf013084
parent6c657aea1aafe3443ab92c19a6a952c3dcb1dc3e (diff)
downloadchrome-ec-e0d9bb6fdef6fe87dac52ea7f26281f8d3239a7a.tar.gz
chip/mt_scp: support audio codec WoV
BRANCH=none BUG=b:122027734, b:123268236 TEST=1. define CONFIG_AUDIO_CODEC in board.h 2. define CONFIG_AUDIO_CODEC_DMIC in board.h 3. define CONFIG_AUDIO_CODEC_DMIC_SOFTWARE_GAIN in board.h 4. define CONFIG_AUDIO_CODEC_DMIC_MAX_SOFTWARE_GAIN in board.h 5. define CONFIG_AUDIO_CODEC_WOV in board.h 6. make BOARD=kukui_scp -j Change-Id: I51e22947c3f535c9a504033c502ec2ff1c688e6a Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1490801 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--chip/mt_scp/audio_codec_wov.c97
-rw-r--r--chip/mt_scp/build.mk1
-rw-r--r--chip/mt_scp/registers.h43
3 files changed, 141 insertions, 0 deletions
diff --git a/chip/mt_scp/audio_codec_wov.c b/chip/mt_scp/audio_codec_wov.c
new file mode 100644
index 0000000000..bff8f776b7
--- /dev/null
+++ b/chip/mt_scp/audio_codec_wov.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "audio_codec.h"
+#include "hooks.h"
+#include "memmap.h"
+#include "registers.h"
+#include "task.h"
+#include "util.h"
+
+/* VIF FIFO irq is triggered above this level */
+#define WOV_TRIGGER_LEVEL 160
+
+int audio_codec_wov_enable_notifier(void)
+{
+ SCP_VIF_FIFO_DATA_THRE = WOV_TRIGGER_LEVEL + 1;
+ SCP_VIF_FIFO_EN |= VIF_FIFO_IRQ_EN;
+
+ task_enable_irq(SCP_IRQ_MAD_FIFO);
+
+ return EC_SUCCESS;
+}
+
+int audio_codec_wov_disable_notifier(void)
+{
+ SCP_VIF_FIFO_EN &= ~VIF_FIFO_IRQ_EN;
+
+ task_disable_irq(SCP_IRQ_MAD_FIFO);
+
+ return EC_SUCCESS;
+}
+
+int audio_codec_wov_enable(void)
+{
+ SCP_VIF_FIFO_EN = 0;
+
+ SCP_RXIF_CFG0 = (RXIF_CFG0_RESET_VAL & ~RXIF_RGDL2_MASK) |
+ RXIF_RGDL2_DMIC_16K;
+ SCP_RXIF_CFG1 = RXIF_CFG1_RESET_VAL;
+
+ SCP_VIF_FIFO_EN |= VIF_FIFO_RSTN;
+
+ return EC_SUCCESS;
+}
+
+int audio_codec_wov_disable(void)
+{
+ SCP_VIF_FIFO_EN = 0;
+
+ return EC_SUCCESS;
+}
+
+static size_t wov_fifo_level(void)
+{
+ uint32_t fifo_status = SCP_VIF_FIFO_STATUS;
+
+ if (!(fifo_status & VIF_FIFO_VALID))
+ return 0;
+
+ if (fifo_status & VIF_FIFO_FULL)
+ return VIF_FIFO_MAX;
+
+ return VIF_FIFO_LEVEL(fifo_status);
+}
+
+int32_t audio_codec_wov_read(void *buf, uint32_t count)
+{
+ int16_t *out = buf;
+
+ count >>= 1;
+
+ while (count-- && wov_fifo_level())
+ *out++ = SCP_VIF_FIFO_DATA;
+
+ return (void *)out - buf;
+}
+
+static void wov_fifo_interrupt_handler(void)
+{
+#ifdef HAS_TASK_WOV
+ task_wake(TASK_ID_WOV);
+#endif
+
+ audio_codec_wov_disable_notifier();
+
+ /* Read to clear */
+ SCP_VIF_FIFO_IRQ_STATUS;
+}
+DECLARE_IRQ(SCP_IRQ_MAD_FIFO, wov_fifo_interrupt_handler, 2);
+
+int audio_codec_memmap_ap_to_ec(uintptr_t ap_addr, uintptr_t *ec_addr)
+{
+ return memmap_ap_to_scp(ap_addr, ec_addr);
+}
diff --git a/chip/mt_scp/build.mk b/chip/mt_scp/build.mk
index 151876a1c8..fa6164056e 100644
--- a/chip/mt_scp/build.mk
+++ b/chip/mt_scp/build.mk
@@ -26,6 +26,7 @@ endif
endif
# Optional chip modules
+chip-$(CONFIG_AUDIO_CODEC_WOV)+=audio_codec_wov.o
chip-$(CONFIG_COMMON_TIMER)+=hrtimer.o
chip-$(CONFIG_I2C)+=i2c.o
chip-$(CONFIG_IPI)+=ipi.o ipi_table.o
diff --git a/chip/mt_scp/registers.h b/chip/mt_scp/registers.h
index dd70d6b273..6196a936e2 100644
--- a/chip/mt_scp/registers.h
+++ b/chip/mt_scp/registers.h
@@ -187,6 +187,49 @@
#define SCP_L1_EXT_ADDR_OTHER_LSB_MASK (BIT(SCP_REMAP_ADDR_SHIFT) - 1)
#define SCP_L1_EXT_ADDR_OTHER_MSB_MASK ((~0) << SCP_REMAP_ADDR_SHIFT)
+/* Audio/voice FIFO */
+#define SCP_AUDIO_BASE (SCP_CFG_BASE + 0x1000)
+#define SCP_VIF_FIFO_EN REG32(SCP_AUDIO_BASE)
+#define VIF_FIFO_RSTN (1 << 0)
+#define VIF_FIFO_IRQ_EN (1 << 1)
+#define VIF_FIFO_SRAM_PWR (1 << 2)
+#define VIF_FIFO_RSTN_STATUS (1 << 4)
+#define SCP_VIF_FIFO_STATUS REG32(SCP_AUDIO_BASE + 0x04)
+#define VIF_FIFO_VALID (1 << 0)
+#define VIF_FIFO_FULL (1 << 4)
+#define VIF_FIFO_LEVEL(status) (((status) >> 16) & 0xff)
+#define VIF_FIFO_MAX 256
+#define SCP_VIF_FIFO_DATA REG32(SCP_AUDIO_BASE + 0x08)
+#define SCP_VIF_FIFO_DATA_THRE REG32(SCP_AUDIO_BASE + 0x0C)
+/* VIF IRQ status clears on read! */
+#define SCP_VIF_FIFO_IRQ_STATUS REG32(SCP_AUDIO_BASE + 0x10)
+/* Audio/voice serial interface */
+#define SCP_RXIF_CFG0 REG32(SCP_AUDIO_BASE + 0x14)
+#define RXIF_CFG0_RESET_VAL 0x2A130001
+#define RXIF_AFE_ON (1 << 0)
+#define RXIF_SCKINV (1 << 1)
+#define RXIF_RG_DL_2_IN_MODE(mode) (((mode) & 0xf) << 8)
+#define RXIF_RGDL2_AMIC_16K (0x1 << 8)
+#define RXIF_RGDL2_DMIC_16K (0x2 << 8)
+#define RXIF_RGDL2_DMIC_LP_16K (0x3 << 8)
+#define RXIF_RGDL2_AMIC_32K (0x5 << 8)
+#define RXIF_RGDL2_MASK (0xf << 8)
+#define RXIF_UP8X_RSP(p) (((p) & 0x7) << 16)
+#define RXIF_RG_RX_READEN (1 << 19)
+#define RXIF_MONO (1 << 20)
+#define RXIF_RG_CLK_A16P7K_EN(cnt) (((cnt) & 0xff) << 24)
+#define SCP_RXIF_CFG1 REG32(SCP_AUDIO_BASE + 0x18)
+#define RXIF_CFG1_RESET_VAL 0x33180014
+#define RXIF_RG_SYNC_CNT_TBL(t) ((t) & 0x1ff)
+#define RXIF_RG_SYNC_SEARCH_TBL(t) (((t) & 0x1f) << 16)
+#define RXIF_RG_SYNC_CHECK_ROUND(r) (((r) & 0xf) << 24)
+#define RXIF_RG_INSYNC_CHECK_ROUND(r) (((r) & 0xf) << 28)
+#define SCP_RXIF_CFG2 REG32(SCP_AUDIO_BASE + 0x1C)
+#define RXIF_SYNC_WORD(w) ((w) & 0xffff)
+#define SCP_RXIF_OUT REG32(SCP_AUDIO_BASE + 0x20)
+#define SCP_RXIF_STATUS REG32(SCP_AUDIO_BASE + 0x24)
+#define SCP_RXIF_IRQ_EN REG32(SCP_AUDIO_BASE + 0x28)
+
/* INTC control */
#define SCP_INTC_BASE (SCP_CFG_BASE + 0x2000)
#define SCP_INTC_IRQ_STATUS REG32(SCP_INTC_BASE)