summaryrefslogtreecommitdiff
path: root/chip/mt_scp/audio_codec_wov.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/mt_scp/audio_codec_wov.c')
-rw-r--r--chip/mt_scp/audio_codec_wov.c97
1 files changed, 97 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);
+}