From e0d9bb6fdef6fe87dac52ea7f26281f8d3239a7a Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Wed, 27 Feb 2019 13:11:21 +0800 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1490801 Reviewed-by: Nicolas Boichat --- chip/mt_scp/audio_codec_wov.c | 97 +++++++++++++++++++++++++++++++++++++++++++ chip/mt_scp/build.mk | 1 + chip/mt_scp/registers.h | 43 +++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 chip/mt_scp/audio_codec_wov.c 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) -- cgit v1.2.1